Author: djencks Date: Sun Sep 26 22:02:32 2010 New Revision: 1001535 URL: http://svn.apache.org/viewvc?rev=1001535&view=rev Log: GERONIMO-5624 fix up dynamic security constraint processing for jetty Modified: geronimo/server/trunk/plugins/j2ee/geronimo-web/src/main/java/org/apache/geronimo/web/security/WebSecurityConstraintStore.java geronimo/server/trunk/plugins/jetty8/geronimo-jetty8/src/main/java/org/apache/geronimo/jetty8/handler/GeronimoWebAppContext.java Modified: geronimo/server/trunk/plugins/j2ee/geronimo-web/src/main/java/org/apache/geronimo/web/security/WebSecurityConstraintStore.java URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/j2ee/geronimo-web/src/main/java/org/apache/geronimo/web/security/WebSecurityConstraintStore.java?rev=1001535&r1=1001534&r2=1001535&view=diff ============================================================================== --- geronimo/server/trunk/plugins/j2ee/geronimo-web/src/main/java/org/apache/geronimo/web/security/WebSecurityConstraintStore.java (original) +++ geronimo/server/trunk/plugins/j2ee/geronimo-web/src/main/java/org/apache/geronimo/web/security/WebSecurityConstraintStore.java Sun Sep 26 22:02:32 2010 @@ -66,6 +66,7 @@ public class WebSecurityConstraintStore private Map containerCreatedDynamicServletNameClassMap = new HashMap(); private Map dynamicServletNameSecurityElementMap = new LinkedHashMap(); + private Map registrationSecurityElementMap = new LinkedHashMap(); private Set securityRoles = new HashSet(); @@ -91,10 +92,27 @@ public class WebSecurityConstraintStore initialize(); } + public void setAnnotationScanRequired(boolean scanRequired) { + annotationScanRequired = scanRequired; + } + public void addContainerCreatedDynamicServlet(javax.servlet.Servlet servlet) { containerCreatedDynamicServlets.put(servlet, null); } + public boolean isContainerCreatedDynamicServlet(javax.servlet.Servlet servlet) { + return containerCreatedDynamicServlets.containsKey(servlet); + } + + public void addContainerCreatedDynamicServletEntry(ServletRegistration.Dynamic registration, String servletClass) { + if (annotationScanRequired) { + ServletSecurityElement servletSecurityElement = processServletConstraintAnnotation(servletClass); + if (servletSecurityElement != null) { + setDynamicServletSecurity(registration, servletSecurityElement); + } + } + } + public void addContainerCreatedDynamicServletEntry(String servletName, String servletClass) { containerCreatedDynamicServletNameClassMap.put(servletName, servletClass); } @@ -123,11 +141,12 @@ public class WebSecurityConstraintStore List securityConstraints = new ArrayList(); //Scan ServletSecurity annotation if required if (annotationScanRequired) { - for (ServletInfo servlet : webXmlAppInfo.servlets) { - Collection urlPatterns = servletContext.getServletRegistration(servlet.servletName).getMappings(); - urlPatterns.removeAll(webXmlConstraintUrlPatterns); - processServletConstraintAnnotation(securityConstraints, servlet.servletName, servlet.servletClass, urlPatterns); - } + //these will already have been added and be in the containerCreatedDynamicServletNameClassMap +// for (ServletInfo servlet : webXmlAppInfo.servlets) { +// Collection urlPatterns = servletContext.getServletRegistration(servlet.servletName).getMappings(); +// urlPatterns.removeAll(webXmlConstraintUrlPatterns); +// processServletConstraintAnnotation(securityConstraints, servlet.servletName, servlet.servletClass, urlPatterns); +// } for (Map.Entry entry : containerCreatedDynamicServletNameClassMap.entrySet()) { String servletName = entry.getKey(); @@ -145,16 +164,18 @@ public class WebSecurityConstraintStore urlPatterns.removeAll(webXmlConstraintUrlPatterns); processServletSecurityElement(securityConstraints, entry.getValue(), urlPatterns); } + for (Map.Entry entry : registrationSecurityElementMap.entrySet()) { + Collection urlPatterns = entry.getKey().registration.getMappings(); + urlPatterns.removeAll(webXmlConstraintUrlPatterns); + processServletSecurityElement(securityConstraints, entry.getValue(), urlPatterns); + } + webXmlAppInfo.securityConstraints.addAll(securityConstraints); return webXmlAppInfo; } - public boolean isContainerCreatedDynamicServlet(javax.servlet.Servlet servlet) { - return containerCreatedDynamicServlets.containsKey(servlet); - } - public Set setDynamicServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement constraint) { - dynamicServletNameSecurityElementMap.put(registration.getName(), constraint); + registrationSecurityElementMap.put(new RegistrationKey(registration), constraint); Set uneffectedUrlPatterns = new HashSet(registration.getMappings()); uneffectedUrlPatterns.retainAll(webXmlConstraintUrlPatterns); return uneffectedUrlPatterns; @@ -184,13 +205,11 @@ public class WebSecurityConstraintStore } private SecurityConstraintInfo newHTTPSecurityConstraint(String[] rolesAllowed, TransportGuarantee transportGuarantee, ServletSecurity.EmptyRoleSemantic emptyRoleSemantic, - String[] omissionMethods, Collection urlPatterns) { - SecurityConstraintInfo securityConstraint = newSecurityConstraint(rolesAllowed, transportGuarantee, emptyRoleSemantic, omissionMethods.length > 0); + Collection omissionMethods, Collection urlPatterns) { + SecurityConstraintInfo securityConstraint = newSecurityConstraint(rolesAllowed, transportGuarantee, emptyRoleSemantic, !omissionMethods.isEmpty()); if (securityConstraint != null) { WebResourceCollectionInfo webResourceCollection = securityConstraint.webResourceCollections.get(0); - for (String omissionMethod : omissionMethods) { - webResourceCollection.httpMethods.add(omissionMethod); - } + webResourceCollection.httpMethods.addAll(omissionMethods); webResourceCollection.urlPatterns.addAll(urlPatterns); webResourceCollection.omission = true; } @@ -246,6 +265,24 @@ public class WebSecurityConstraintStore } } + private ServletSecurityElement processServletConstraintAnnotation(String servletClassName) { + try { + Class cls = bundle.loadClass(servletClassName); + if (!javax.servlet.Servlet.class.isAssignableFrom(cls)) { + return null; + } + ServletSecurity servletSecurity = cls.getAnnotation(ServletSecurity.class); + if (servletSecurity == null) { + return null; + } + return new ServletSecurityElement(servletSecurity); + } catch (ClassNotFoundException e) { + //Should never occur, as webservice builder have already checked it. + logger.error("Fail to load class", e); + } + return null; + } + private void processServletSecurityAnnotation(List securityConstraints, ServletSecurity servletSecurity, Collection urlPatterns) { processServletSecurityElement(securityConstraints, new ServletSecurityElement(servletSecurity), urlPatterns); } @@ -263,11 +300,30 @@ public class WebSecurityConstraintStore } } SecurityConstraintInfo securityConstraint = newHTTPSecurityConstraint(servletSecurityElement.getRolesAllowed(), servletSecurityElement.getTransportGuarantee(), - servletSecurityElement.getEmptyRoleSemantic(), servletSecurityElement.getMethodNames().toArray(new String[0]), urlPatterns); + servletSecurityElement.getEmptyRoleSemantic(), servletSecurityElement.getMethodNames(), urlPatterns); if (securityConstraint != null) { securityConstraints.add(securityConstraint); } declareRoles(servletSecurityElement.getRolesAllowed()); } + private final static class RegistrationKey { + private final ServletRegistration.Dynamic registration; + + private RegistrationKey(ServletRegistration.Dynamic registration) { + this.registration = registration; + } + + @Override + public boolean equals(Object o) { + return (o instanceof RegistrationKey) && + registration.getName().equals(((RegistrationKey)o).registration.getName()); + } + + @Override + public int hashCode() { + return registration.getName().hashCode(); + } + } + } Modified: geronimo/server/trunk/plugins/jetty8/geronimo-jetty8/src/main/java/org/apache/geronimo/jetty8/handler/GeronimoWebAppContext.java URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/jetty8/geronimo-jetty8/src/main/java/org/apache/geronimo/jetty8/handler/GeronimoWebAppContext.java?rev=1001535&r1=1001534&r2=1001535&view=diff ============================================================================== --- geronimo/server/trunk/plugins/jetty8/geronimo-jetty8/src/main/java/org/apache/geronimo/jetty8/handler/GeronimoWebAppContext.java (original) +++ geronimo/server/trunk/plugins/jetty8/geronimo-jetty8/src/main/java/org/apache/geronimo/jetty8/handler/GeronimoWebAppContext.java Sun Sep 26 22:02:32 2010 @@ -59,6 +59,7 @@ import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; @@ -139,6 +140,7 @@ public class GeronimoWebAppContext exten try { Assembler assembler = new Assembler(); assembler.assemble(getServletContext(), webAppInfo); + webSecurityConstraintStore.setAnnotationScanRequired(true); ((GeronimoWebAppContext.Context) _scontext).webXmlProcessed = true; super.doStart(); if (applicationPolicyConfigurationManager != null) { @@ -270,8 +272,17 @@ public class GeronimoWebAppContext exten return paths; } - @Override + protected ServletRegistration.Dynamic dynamicHolderAdded(ServletHolder holder) { + ServletRegistration.Dynamic registration = holder.getRegistration(); + String servletClassName = holder.getClassName(); + Servlet servlet = holder.getServletInstance(); + if (servlet == null || webSecurityConstraintStore.isContainerCreatedDynamicServlet(servlet)) { + webSecurityConstraintStore.addContainerCreatedDynamicServletEntry(registration, servletClassName); + } + return registration; + } + public Set setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) { return webSecurityConstraintStore.setDynamicServletSecurity(registration, servletSecurityElement); }