Home » geronimo-2.2-source-release » org.apache.geronimo.web25.deployment » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.geronimo.web25.deployment;
   19   
   20   import java.io.File;
   21   import java.io.IOException;
   22   import java.io.StringWriter;
   23   import java.net.URI;
   24   import java.net.URISyntaxException;
   25   import java.net.URL;
   26   import java.util.ArrayList;
   27   import java.util.Collection;
   28   import java.util.Collections;
   29   import java.util.Enumeration;
   30   import java.util.HashMap;
   31   import java.util.LinkedHashSet;
   32   import java.util.LinkedList;
   33   import java.util.List;
   34   import java.util.Map;
   35   import java.util.jar.JarEntry;
   36   import java.util.jar.JarFile;
   37   import java.util.zip.ZipEntry;
   38   
   39   import javax.xml.namespace.QName;
   40   import javax.xml.namespace.NamespaceContext;
   41   import javax.xml.stream.XMLStreamReader;
   42   import javax.xml.stream.XMLStreamException;
   43   import javax.xml.stream.Location;
   44   import javax.xml.parsers.ParserConfigurationException;
   45   import javax.xml.bind.JAXBException;
   46   import javax.security.auth.message.module.ServerAuthModule;
   47   
   48   import org.apache.geronimo.common.DeploymentException;
   49   import org.apache.geronimo.deployment.ClassPathList;
   50   import org.apache.geronimo.deployment.ModuleIDBuilder;
   51   import org.apache.geronimo.deployment.ModuleList;
   52   import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
   53   import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
   54   import org.apache.geronimo.deployment.util.DeploymentUtil;
   55   import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
   56   import org.apache.geronimo.gbean.AbstractName;
   57   import org.apache.geronimo.gbean.AbstractNameQuery;
   58   import org.apache.geronimo.gbean.GBeanData;
   59   import org.apache.geronimo.gbean.GBeanInfoBuilder;
   60   import org.apache.geronimo.j2ee.annotation.Holder;
   61   import org.apache.geronimo.j2ee.deployment.EARContext;
   62   import org.apache.geronimo.j2ee.deployment.Module;
   63   import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
   64   import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
   65   import org.apache.geronimo.j2ee.deployment.NamingBuilder;
   66   import org.apache.geronimo.j2ee.deployment.WebModule;
   67   import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
   68   import org.apache.geronimo.j2ee.deployment.annotation.SecurityAnnotationHelper;
   69   import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
   70   import org.apache.geronimo.kernel.Kernel;
   71   import org.apache.geronimo.kernel.Naming;
   72   import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
   73   import org.apache.geronimo.kernel.config.Configuration;
   74   import org.apache.geronimo.kernel.config.ConfigurationModuleType;
   75   import org.apache.geronimo.kernel.config.ConfigurationStore;
   76   import org.apache.geronimo.kernel.repository.Artifact;
   77   import org.apache.geronimo.kernel.repository.Environment;
   78   import org.apache.geronimo.kernel.repository.ImportType;
   79   import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
   80   import org.apache.geronimo.schema.SchemaConversionUtils;
   81   import org.apache.geronimo.security.jacc.ComponentPermissions;
   82   import org.apache.geronimo.security.jaspi.AuthConfigProviderGBean;
   83   import org.apache.geronimo.security.jaspi.ServerAuthConfigGBean;
   84   import org.apache.geronimo.security.jaspi.ServerAuthContextGBean;
   85   import org.apache.geronimo.security.jaspi.ServerAuthModuleGBean;
   86   import org.apache.geronimo.web25.deployment.security.SpecSecurityBuilder;
   87   import org.apache.geronimo.web25.deployment.security.AuthenticationWrapper;
   88   import org.apache.geronimo.xbeans.geronimo.j2ee.GerSecurityDocument;
   89   import org.apache.geronimo.xbeans.javaee.FilterMappingType;
   90   import org.apache.geronimo.xbeans.javaee.FilterType;
   91   import org.apache.geronimo.xbeans.javaee.FullyQualifiedClassType;
   92   import org.apache.geronimo.xbeans.javaee.ListenerType;
   93   import org.apache.geronimo.xbeans.javaee.SecurityConstraintType;
   94   import org.apache.geronimo.xbeans.javaee.ServletMappingType;
   95   import org.apache.geronimo.xbeans.javaee.ServletType;
   96   import org.apache.geronimo.xbeans.javaee.UrlPatternType;
   97   import org.apache.geronimo.xbeans.javaee.WebAppDocument;
   98   import org.apache.geronimo.xbeans.javaee.WebAppType;
   99   import org.apache.geronimo.xbeans.javaee.WebResourceCollectionType;
  100   import org.apache.geronimo.components.jaspi.model.ConfigProviderType;
  101   import org.apache.geronimo.components.jaspi.model.JaspiXmlUtil;
  102   import org.apache.geronimo.components.jaspi.model.ServerAuthConfigType;
  103   import org.apache.geronimo.components.jaspi.model.ServerAuthContextType;
  104   import org.apache.geronimo.components.jaspi.model.AuthModuleType;
  105   import org.apache.xbean.finder.ClassFinder;
  106   import org.apache.xmlbeans.XmlCursor;
  107   import org.apache.xmlbeans.XmlDocumentProperties;
  108   import org.apache.xmlbeans.XmlException;
  109   import org.apache.xmlbeans.XmlObject;
  110   import org.slf4j.Logger;
  111   import org.slf4j.LoggerFactory;
  112   import org.xml.sax.SAXException;
  113   
  114   /**
  115    * @version $Rev: 802422 $ $Date: 2009-08-08 10:13:25 -0700 (Sat, 08 Aug 2009) $
  116    */
  117   public abstract class AbstractWebModuleBuilder implements ModuleBuilder {
  118   
  119       public final static NamingBuilder.Key<GBeanData> DEFAULT_JSP_SERVLET_KEY = new NamingBuilder.Key<GBeanData>() {
  120           public GBeanData get(Map context) {
  121               return (GBeanData) context.get(this);
  122           }
  123   
  124       };
  125       private static final Logger log = LoggerFactory.getLogger(AbstractWebModuleBuilder.class);
  126   
  127       private static final QName TAGLIB = new QName(SchemaConversionUtils.JAVAEE_NAMESPACE, "taglib");
  128   
  129       private static final String LINE_SEP = System.getProperty("line.separator");
  130   
  131       protected static final AbstractNameQuery MANAGED_CONNECTION_FACTORY_PATTERN;
  132       private static final AbstractNameQuery ADMIN_OBJECT_PATTERN;
  133       protected static final AbstractNameQuery STATELESS_SESSION_BEAN_PATTERN;
  134       protected static final AbstractNameQuery STATEFUL_SESSION_BEAN_PATTERN;
  135       protected static final AbstractNameQuery ENTITY_BEAN_PATTERN;
  136       protected final Kernel kernel;
  137       protected final NamespaceDrivenBuilderCollection serviceBuilders;
  138       protected final ResourceEnvironmentSetter resourceEnvironmentSetter;
  139       protected final Collection<WebServiceBuilder> webServiceBuilder;
  140   
  141       protected final NamingBuilder namingBuilders;
  142       protected final Collection<ModuleBuilderExtension> moduleBuilderExtensions;
  143   
  144       private static final QName SECURITY_QNAME = GerSecurityDocument.type.getDocumentElementName();
  145   
  146       /**
  147        * Manifest classpath entries in a war configuration must be resolved relative to the war configuration, not the
  148        * enclosing ear configuration.  Resolving relative to he war configuration using this offset produces the same
  149        * effect as URI.create(module.targetPath()).resolve(mcpEntry) executed in the ear configuration.
  150        */
  151       private static final URI RELATIVE_MODULE_BASE_URI = URI.create("../");
  152   
  153       protected AbstractWebModuleBuilder(Kernel kernel, Collection<NamespaceDrivenBuilder> serviceBuilders, NamingBuilder namingBuilders, ResourceEnvironmentSetter resourceEnvironmentSetter, Collection<WebServiceBuilder> webServiceBuilder, Collection<ModuleBuilderExtension> moduleBuilderExtensions) {
  154           this.kernel = kernel;
  155           this.serviceBuilders = new NamespaceDrivenBuilderCollection(serviceBuilders);
  156           this.namingBuilders = namingBuilders;
  157           this.resourceEnvironmentSetter = resourceEnvironmentSetter;
  158           this.webServiceBuilder = webServiceBuilder;
  159           this.moduleBuilderExtensions = moduleBuilderExtensions == null? new ArrayList<ModuleBuilderExtension>(): moduleBuilderExtensions;
  160       }
  161   
  162       static {
  163           MANAGED_CONNECTION_FACTORY_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.JCA_MANAGED_CONNECTION_FACTORY));
  164           ADMIN_OBJECT_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.JCA_ADMIN_OBJECT));
  165           STATELESS_SESSION_BEAN_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.STATELESS_SESSION_BEAN));
  166           STATEFUL_SESSION_BEAN_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.STATEFUL_SESSION_BEAN));
  167           ENTITY_BEAN_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.ENTITY_BEAN));
  168   
  169       }
  170   
  171       public NamingBuilder getNamingBuilders() {
  172           return namingBuilders;
  173       }
  174   
  175       protected void addGBeanDependencies(EARContext earContext, GBeanData webModuleData) {
  176           Configuration earConfiguration = earContext.getConfiguration();
  177           addDependencies(earContext.findGBeanDatas(earConfiguration, MANAGED_CONNECTION_FACTORY_PATTERN), webModuleData);
  178           addDependencies(earContext.findGBeanDatas(earConfiguration, ADMIN_OBJECT_PATTERN), webModuleData);
  179           addDependencies(earContext.findGBeanDatas(earConfiguration, STATELESS_SESSION_BEAN_PATTERN), webModuleData);
  180           addDependencies(earContext.findGBeanDatas(earConfiguration, STATEFUL_SESSION_BEAN_PATTERN), webModuleData);
  181           addDependencies(earContext.findGBeanDatas(earConfiguration, ENTITY_BEAN_PATTERN), webModuleData);
  182       }
  183   
  184       private void addDependencies(LinkedHashSet<GBeanData> dependencies, GBeanData webModuleData) {
  185           for (GBeanData dependency: dependencies) {
  186               AbstractName dependencyName = dependency.getAbstractName();
  187               webModuleData.addDependency(dependencyName);
  188           }
  189       }
  190   
  191       public Module createModule(File plan, JarFile moduleFile, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
  192           return createModule(plan, moduleFile, ".", null, true, null, null, naming, idBuilder);
  193       }
  194   
  195       public Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
  196           return createModule(plan, moduleFile, targetPath, specDDUrl, false, (String) moduleContextInfo, earName, naming, idBuilder);
  197       }
  198   
  199       protected abstract Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException;
  200   
  201       /**
  202        * Some servlets will have multiple url patterns.  However, webservice servlets
  203        * will only have one, which is what this method is intended for.
  204        *
  205        * @param webApp      spec deployment descriptor
  206        * @param contextRoot context root for web app from application.xml or geronimo plan
  207        * @return map of servlet names to path mapped to them.  Possibly inaccurate except for web services.
  208        */
  209       protected Map<String, String> buildServletNameToPathMap(WebAppType webApp, String contextRoot) {
  210           if (contextRoot == null) {
  211               contextRoot = "";
  212           } else if (!contextRoot.startsWith("/")) {        
  213               contextRoot = "/" + contextRoot;
  214           }
  215           Map<String, String> map = new HashMap<String, String>();
  216           ServletMappingType[] servletMappings = webApp.getServletMappingArray();
  217           for (ServletMappingType servletMapping : servletMappings) {
  218               String servletName = servletMapping.getServletName().getStringValue().trim();
  219               UrlPatternType[] urlPatterns = servletMapping.getUrlPatternArray();
  220   
  221               for (int i = 0; urlPatterns != null && (i < urlPatterns.length); i++) {
  222                   map.put(servletName, contextRoot + urlPatterns[i].getStringValue().trim());
  223               }
  224           }
  225           return map;
  226       }
  227   
  228       protected String determineDefaultContextRoot(WebAppType webApp, boolean isStandAlone, JarFile moduleFile, String targetPath) {
  229   
  230           if (webApp != null && webApp.getId() != null) {
  231               return webApp.getId();
  232           }
  233   
  234           if (isStandAlone) {
  235               // default configId is based on the moduleFile name
  236               return "/" + trimPath(new File(moduleFile.getName()).getName());
  237           }
  238   
  239           // default configId is based on the module uri from the application.xml
  240           return trimPath(targetPath);
  241       }
  242   
  243       private String trimPath(String path) {
  244   
  245           if (path == null) {
  246               return null;
  247           }
  248   
  249           if (path.endsWith(".war")) {
  250               path = path.substring(0, path.length() - 4);
  251           }
  252           if (path.endsWith("/")) {
  253               path = path.substring(0, path.length() - 1);
  254           }
  255   
  256           return path;
  257       }
  258   
  259       public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repositories) throws DeploymentException {
  260           EARContext moduleContext;
  261           if (module.isStandAlone()) {
  262               moduleContext = earContext;
  263           } else {
  264               Environment environment = module.getEnvironment();
  265               Artifact earConfigId = earContext.getConfigID();
  266               Artifact configId = new Artifact(earConfigId.getGroupId(), earConfigId.getArtifactId() + "_" + module.getTargetPath(), earConfigId.getVersion(), "car");
  267               environment.setConfigId(configId);
  268               environment.addDependency(earConfigId, ImportType.ALL);
  269               File configurationDir = new File(earContext.getBaseDir(), module.getTargetPath());
  270               configurationDir.mkdirs();
  271   
  272               // construct the web app deployment context... this is the same class used by the ear context
  273               try {
  274                   File inPlaceConfigurationDir = null;
  275                   if (null != earContext.getInPlaceConfigurationDir()) {
  276                       inPlaceConfigurationDir = new File(earContext.getInPlaceConfigurationDir(), module.getTargetPath());
  277                   }
  278                   moduleContext = new EARContext(configurationDir,
  279                           inPlaceConfigurationDir,
  280                           environment,
  281                           ConfigurationModuleType.WAR,
  282                           module.getModuleName(),
  283                           earContext);
  284               } catch (DeploymentException e) {
  285                   cleanupConfigurationDir(configurationDir);
  286                   throw e;
  287               }
  288           }
  289           module.setEarContext(moduleContext);
  290           module.setRootEarContext(earContext);
  291   
  292           try {
  293               ClassPathList manifestcp = new ClassPathList();
  294               // add the warfile's content to the configuration
  295               JarFile warFile = module.getModuleFile();
  296               Enumeration<JarEntry> entries = warFile.entries();
  297               List<ZipEntry> libs = new ArrayList<ZipEntry>();
  298               while (entries.hasMoreElements()) {
  299                   ZipEntry entry = entries.nextElement();
  300                   URI targetPath = new URI(null, entry.getName(), null);
  301                   if (entry.getName().equals("WEB-INF/web.xml")) {
  302                       moduleContext.addFile(targetPath, module.getOriginalSpecDD());
  303                   } else if (entry.getName().startsWith("WEB-INF/lib") && entry.getName().endsWith(".jar")) {
  304                       // keep a collection of all libs in the war
  305                       // libs must be installed after WEB-INF/classes which must be installed after this copy phase
  306                       libs.add(entry);
  307                   } else {
  308                       moduleContext.addFile(targetPath, warFile, entry);
  309                   }
  310               }
  311   
  312               // always add WEB-INF/classes to the classpath regardless of whether
  313               // any classes exist.  This must be searched BEFORE the WEB-INF/lib jar files,
  314               // per the servlet specifications.
  315               moduleContext.getConfiguration().addToClassPath("WEB-INF/classes/");
  316               manifestcp.add("WEB-INF/classes/");
  317   
  318               // install the libs
  319               for (ZipEntry entry : libs) {
  320                   URI targetPath = new URI(null, entry.getName(), null);
  321                   moduleContext.addInclude(targetPath, warFile, entry);
  322                   manifestcp.add(entry.getName());
  323               }
  324   
  325               // add the manifest classpath entries declared in the war to the class loader
  326               // we have to explicitly add these since we are unpacking the web module
  327               // and the url class loader will not pick up a manifest from an unpacked dir
  328               moduleContext.addManifestClassPath(warFile, RELATIVE_MODULE_BASE_URI);
  329               moduleContext.getGeneralData().put(ClassPathList.class, manifestcp);
  330   
  331           } catch (IOException e) {
  332               throw new DeploymentException("Problem deploying war", e);
  333           } catch (URISyntaxException e) {
  334               throw new DeploymentException("Could not construct URI for location of war entry", e);
  335           } finally {
  336               if (!module.isStandAlone()) {
  337                   try {
  338                       moduleContext.flush();
  339                   } catch (IOException e) {
  340                       throw new DeploymentException("Problem closing war context", e);
  341                   }
  342               }
  343           }
  344           for (ModuleBuilderExtension mbe: moduleBuilderExtensions) {
  345               mbe.installModule(earFile, earContext, module, configurationStores, targetConfigurationStore, repositories);
  346           }
  347       }
  348   
  349       protected void basicInitContext(EARContext earContext, Module module, XmlObject gerWebApp, boolean hasSecurityRealmName) throws DeploymentException {
  350           //complete manifest classpath
  351           EARContext moduleContext = module.getEarContext();
  352           ClassPathList manifestcp = (ClassPathList) moduleContext.getGeneralData().get(ClassPathList.class);
  353           ModuleList moduleLocations = (ModuleList) module.getRootEarContext().getGeneralData().get(ModuleList.class);
  354           URI baseUri = URI.create(module.getTargetPath());
  355           URI resolutionUri = invertURI(baseUri);
  356           earContext.getCompleteManifestClassPath(module.getModuleFile(), baseUri, resolutionUri, manifestcp, moduleLocations);
  357   
  358   
  359           WebAppType webApp = (WebAppType) module.getSpecDD();
  360           if ((webApp.getSecurityConstraintArray().length > 0 || webApp.getSecurityRoleArray().length > 0)) {
  361               if (!hasSecurityRealmName) {
  362                   throw new DeploymentException("web.xml for web app " + module.getName() + " includes security elements but Geronimo deployment plan is not provided or does not contain <security-realm-name> element necessary to configure security accordingly.");
  363               }
  364           }
  365           if (hasSecurityRealmName) {
  366               earContext.setHasSecurity(true);
  367           }
  368           //TODO think about how to provide a default security realm name
  369           XmlObject[] securityElements = XmlBeansUtil.selectSubstitutionGroupElements(SECURITY_QNAME, gerWebApp);
  370           if (securityElements.length > 0 && !hasSecurityRealmName) {
  371               throw new DeploymentException("You have supplied a security configuration for web app " + module.getName() + " but no security-realm-name to allow login");
  372           }
  373           getNamingBuilders().buildEnvironment(webApp, module.getVendorDD(), module.getEnvironment());
  374           //this is silly
  375           getNamingBuilders().initContext(webApp, gerWebApp, module);
  376   
  377           Map servletNameToPathMap = buildServletNameToPathMap((WebAppType) module.getSpecDD(), ((WebModule) module).getContextRoot());
  378   
  379           Map sharedContext = module.getSharedContext();
  380           for (Object aWebServiceBuilder : webServiceBuilder) {
  381               WebServiceBuilder serviceBuilder = (WebServiceBuilder) aWebServiceBuilder;
  382               serviceBuilder.findWebServices(module, false, servletNameToPathMap, module.getEnvironment(), sharedContext);
  383           }
  384           serviceBuilders.build(gerWebApp, earContext, module.getEarContext());
  385       }
  386   
  387       static URI invertURI(URI baseUri) {
  388           URI resolutionUri = URI.create(".");
  389           for (URI test = baseUri; !test.equals(RELATIVE_MODULE_BASE_URI); test = test.resolve(RELATIVE_MODULE_BASE_URI)) {
  390               resolutionUri = resolutionUri.resolve(RELATIVE_MODULE_BASE_URI);
  391           }
  392           return resolutionUri;
  393       }
  394   
  395       protected WebAppDocument convertToServletSchema(XmlObject xmlObject) throws XmlException {
  396   
  397           String schemaLocationURL = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd";
  398           String version = "2.5";
  399           XmlCursor cursor = xmlObject.newCursor();
  400           try {
  401               cursor.toStartDoc();
  402               cursor.toFirstChild();
  403               if ("http://java.sun.com/xml/ns/j2ee".equals(cursor.getName().getNamespaceURI())) {
  404                   SchemaConversionUtils.convertSchemaVersion(cursor, SchemaConversionUtils.JAVAEE_NAMESPACE, schemaLocationURL, version);
  405                   XmlObject result = xmlObject.changeType(WebAppDocument.type);
  406                   XmlBeansUtil.validateDD(result);
  407                   return (WebAppDocument) result;
  408               }
  409   
  410               if ("http://java.sun.com/xml/ns/javaee".equals(cursor.getName().getNamespaceURI())) {
  411                   SchemaConversionUtils.convertSchemaVersion(cursor, SchemaConversionUtils.JAVAEE_NAMESPACE, schemaLocationURL, version);
  412                   XmlObject result = xmlObject.changeType(WebAppDocument.type);
  413                   XmlBeansUtil.validateDD(result);
  414                   return (WebAppDocument) result;
  415               }
  416   
  417               //otherwise assume DTD
  418               XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
  419               String publicId = xmlDocumentProperties.getDoctypePublicId();
  420               boolean is22 = "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN".equals(publicId);
  421               if ("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN".equals(publicId) ||
  422                       is22) {
  423                   XmlCursor moveable = xmlObject.newCursor();
  424                   try {
  425                       moveable.toStartDoc();
  426                       moveable.toFirstChild();
  427   
  428                       SchemaConversionUtils.convertToSchema(cursor, SchemaConversionUtils.JAVAEE_NAMESPACE, schemaLocationURL, version);
  429                       cursor.toStartDoc();
  430                       cursor.toChild(SchemaConversionUtils.JAVAEE_NAMESPACE, "web-app");
  431                       cursor.toFirstChild();
  432                       SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
  433                       SchemaConversionUtils.convertToJNDIEnvironmentRefsGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
  434                       cursor.push();
  435                       if (cursor.toNextSibling(TAGLIB)) {
  436                           cursor.toPrevSibling();
  437                           moveable.toCursor(cursor);
  438                           cursor.beginElement("jsp-config", SchemaConversionUtils.JAVAEE_NAMESPACE);
  439                           while (moveable.toNextSibling(TAGLIB)) {
  440                               moveable.moveXml(cursor);
  441                           }
  442                       }
  443                       cursor.pop();
  444                       do {
  445                           String name = cursor.getName().getLocalPart();
  446                           if ("filter".equals(name) || "servlet".equals(name) || "context-param".equals(name)) {
  447                               cursor.push();
  448                               cursor.toFirstChild();
  449                               SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
  450                               while (cursor.toNextSibling(SchemaConversionUtils.JAVAEE_NAMESPACE, "init-param")) {
  451                                   cursor.push();
  452                                   cursor.toFirstChild();
  453                                   SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
  454                                   cursor.pop();
  455                               }
  456                               cursor.pop();
  457                               cursor.push();
  458                               if (cursor.toChild(SchemaConversionUtils.JAVAEE_NAMESPACE, "jsp-file")) {
  459                                   String jspFile = cursor.getTextValue();
  460                                   if (!jspFile.startsWith("/")){
  461                                       if (is22) {
  462                                           cursor.setTextValue("/" + jspFile);
  463                                       } else {
  464                                           throw new XmlException("jsp-file does not start with / and this is not a 2.2 web app: " + jspFile);
  465                                       }
  466                                   }
  467                               }
  468                               cursor.pop();
  469                           }
  470                       } while (cursor.toNextSibling());
  471                   } finally {
  472                       moveable.dispose();
  473                   }
  474               }
  475           } finally {
  476               cursor.dispose();
  477           }
  478           XmlObject result = xmlObject.changeType(WebAppDocument.type);
  479           if (result != null) {
  480               XmlBeansUtil.validateDD(result);
  481               return (WebAppDocument) result;
  482           }
  483           XmlBeansUtil.validateDD(xmlObject);
  484           return (WebAppDocument) xmlObject;
  485       }
  486   
  487       protected ComponentPermissions buildSpecSecurityConfig(WebAppType webApp) {
  488           SpecSecurityBuilder builder = new SpecSecurityBuilder();
  489           return builder.buildSpecSecurityConfig(webApp);
  490       }
  491   
  492       protected void configureLocalJaspicProvider(AuthenticationWrapper authType, String contextPath, Module module, GBeanData securityFactoryData) throws DeploymentException, GBeanAlreadyExistsException {
  493           EARContext moduleContext = module.getEarContext();
  494           GBeanData authConfigProviderData = null;
  495           AbstractName providerName = moduleContext.getNaming().createChildName(module.getModuleName(), "authConfigProvider", GBeanInfoBuilder.DEFAULT_J2EE_TYPE);
  496           try {
  497               if (authType.isSetConfigProvider()) {
  498                   authConfigProviderData = new GBeanData(providerName, AuthConfigProviderGBean.class);
  499                   final XmlCursor xmlCursor = authType.getConfigProvider().newCursor();
  500                   try {
  501                       XMLStreamReader reader = new InternWrapper(xmlCursor.newXMLStreamReader());
  502                       ConfigProviderType configProviderType = JaspiXmlUtil.loadConfigProvider(reader);
  503                       StringWriter out = new StringWriter();
  504                       JaspiXmlUtil.writeConfigProvider(configProviderType, out);
  505                       authConfigProviderData.setAttribute("config", out.toString());
  506                   } finally {
  507                       xmlCursor.dispose();
  508                   }
  509               } else if (authType.isSetServerAuthConfig()) {
  510                   authConfigProviderData = new GBeanData(providerName, ServerAuthConfigGBean.class);
  511                   final XmlCursor xmlCursor = authType.getServerAuthConfig().newCursor();
  512                   try {
  513                       XMLStreamReader reader = new InternWrapper(xmlCursor.newXMLStreamReader());
  514                       ServerAuthConfigType serverAuthConfigType = JaspiXmlUtil.loadServerAuthConfig(reader);
  515                       StringWriter out = new StringWriter();
  516                       JaspiXmlUtil.writeServerAuthConfig(serverAuthConfigType, out);
  517                       authConfigProviderData.setAttribute("config", out.toString());
  518                   } finally {
  519                       xmlCursor.dispose();
  520                   }
  521               } else if (authType.isSetServerAuthContext()) {
  522                   authConfigProviderData = new GBeanData(providerName, ServerAuthContextGBean.class);
  523                   final XmlCursor xmlCursor = authType.getServerAuthContext().newCursor();
  524                   try {
  525                       XMLStreamReader reader = new InternWrapper(xmlCursor.newXMLStreamReader());
  526                       ServerAuthContextType serverAuthContextType = JaspiXmlUtil.loadServerAuthContext(reader);
  527                       StringWriter out = new StringWriter();
  528                       JaspiXmlUtil.writeServerAuthContext(serverAuthContextType, out);
  529                       authConfigProviderData.setAttribute("config", out.toString());
  530                   } finally {
  531                       xmlCursor.dispose();
  532                   }
  533               } else if (authType.isSetServerAuthModule()) {
  534                   authConfigProviderData = new GBeanData(providerName, ServerAuthModuleGBean.class);
  535                   final XmlCursor xmlCursor = authType.getServerAuthModule().newCursor();
  536                   try {
  537                       XMLStreamReader reader = new InternWrapper(xmlCursor.newXMLStreamReader());
  538                       AuthModuleType<ServerAuthModule> authModuleType = JaspiXmlUtil.loadServerAuthModule(reader);
  539                       StringWriter out = new StringWriter();
  540                       JaspiXmlUtil.writeServerAuthModule(authModuleType, out);
  541                       authConfigProviderData.setAttribute("config", out.toString());
  542                       authConfigProviderData.setAttribute("messageLayer", "Http");
  543                       authConfigProviderData.setAttribute("appContext", contextPath);
  544                       //TODO ??
  545                       authConfigProviderData.setAttribute("authenticationID", contextPath);
  546                   } finally {
  547                       xmlCursor.dispose();
  548                   }
  549               }
  550           } catch (ParserConfigurationException e) {
  551               throw new DeploymentException("Could not read auth config", e);
  552           } catch (IOException e) {
  553               throw new DeploymentException("Could not read auth config", e);
  554           } catch (SAXException e) {
  555               throw new DeploymentException("Could not read auth config", e);
  556           } catch (JAXBException e) {
  557               throw new DeploymentException("Could not read auth config", e);
  558           } catch (XMLStreamException e) {
  559               throw new DeploymentException("Could not read auth config", e);
  560           }
  561           if (authConfigProviderData != null) {
  562               moduleContext.addGBean(authConfigProviderData);
  563               securityFactoryData.addDependency(authConfigProviderData.getAbstractName());
  564           }
  565       }
  566   
  567       protected static void check(WebAppType webApp) throws DeploymentException {
  568           checkURLPattern(webApp);
  569           checkMultiplicities(webApp);
  570       }
  571   
  572       private static void checkURLPattern(WebAppType webApp) throws DeploymentException {
  573   
  574           FilterMappingType[] filterMappings = webApp.getFilterMappingArray();
  575           for (FilterMappingType filterMapping : filterMappings) {
  576               UrlPatternType[] urlPatterns = filterMapping.getUrlPatternArray();
  577               for (int j = 0; (urlPatterns != null) && (j < urlPatterns.length); j++) {
  578                   checkString(urlPatterns[j].getStringValue().trim());
  579               }
  580           }
  581   
  582           ServletMappingType[] servletMappings = webApp.getServletMappingArray();
  583           for (ServletMappingType servletMapping : servletMappings) {
  584               UrlPatternType[] urlPatterns = servletMapping.getUrlPatternArray();
  585               for (int j = 0; (urlPatterns != null) && (j < urlPatterns.length); j++) {
  586                   checkString(urlPatterns[j].getStringValue().trim());
  587               }
  588           }
  589   
  590           SecurityConstraintType[] constraints = webApp.getSecurityConstraintArray();
  591           for (SecurityConstraintType constraint : constraints) {
  592               WebResourceCollectionType[] collections = constraint.getWebResourceCollectionArray();
  593               for (WebResourceCollectionType collection : collections) {
  594                   UrlPatternType[] patterns = collection.getUrlPatternArray();
  595                   for (UrlPatternType pattern : patterns) {
  596                       checkString(pattern.getStringValue().trim());
  597                   }
  598               }
  599           }
  600       }
  601   
  602       protected static void checkString(String pattern) throws DeploymentException {
  603           //j2ee_1_4.xsd explicitly requires preserving all whitespace. Do not trim.
  604           if (pattern.indexOf(0x0D) >= 0) throw new DeploymentException("<url-pattern> must not contain CR(#xD)");
  605           if (pattern.indexOf(0x0A) >= 0) throw new DeploymentException("<url-pattern> must not contain LF(#xA)");
  606       }
  607   
  608       private static void checkMultiplicities(WebAppType webApp) throws DeploymentException {
  609           if (webApp.getSessionConfigArray().length > 1)
  610               throw new DeploymentException("Multiple <session-config> elements found");
  611           if (webApp.getJspConfigArray().length > 1)
  612               throw new DeploymentException("Multiple <jsp-config> elements found");
  613           if (webApp.getLoginConfigArray().length > 1)
  614               throw new DeploymentException("Multiple <login-config> elements found");
  615       }
  616   
  617       private boolean cleanupConfigurationDir(File configurationDir) {
  618           LinkedList<String> cannotBeDeletedList = new LinkedList<String>();
  619   
  620           if (!DeploymentUtil.recursiveDelete(configurationDir, cannotBeDeletedList)) {
  621               // Output a message to help user track down file problem
  622               log.warn("Unable to delete " + cannotBeDeletedList.size() +
  623                       " files while recursively deleting directory "
  624                       + configurationDir.getAbsolutePath() + LINE_SEP +
  625                       "The first file that could not be deleted was:" + LINE_SEP + "  " +
  626                       (!cannotBeDeletedList.isEmpty() ? cannotBeDeletedList.getFirst() : ""));
  627               return false;
  628           }
  629           return true;
  630       }
  631   
  632   
  633       protected ClassFinder createWebAppClassFinder(WebAppType webApp, WebModule webModule) throws DeploymentException {
  634           // Get the classloader from the module's EARContext
  635           ClassLoader classLoader = webModule.getEarContext().getClassLoader();
  636           return createWebAppClassFinder(webApp, classLoader);
  637       }
  638   
  639       public static ClassFinder createWebAppClassFinder(WebAppType webApp, ClassLoader classLoader) throws DeploymentException {
  640           //------------------------------------------------------------------------------------
  641           // Find the list of classes from the web.xml we want to search for annotations in
  642           //------------------------------------------------------------------------------------
  643           List<Class> classes = new ArrayList<Class>();
  644   
  645           // Get all the servlets from the deployment descriptor
  646           ServletType[] servlets = webApp.getServletArray();
  647           for (ServletType servlet : servlets) {
  648               FullyQualifiedClassType cls = servlet.getServletClass();
  649               if (cls != null) {                              // Don't try this for JSPs
  650                   Class<?> clas;
  651                   try {
  652                       clas = classLoader.loadClass(cls.getStringValue());
  653                   } catch (ClassNotFoundException e) {
  654                       throw new DeploymentException("AbstractWebModuleBuilder: Could not load servlet class: " + cls.getStringValue(), e);
  655                   }
  656                   addClass(classes, clas);
  657               }
  658           }
  659   
  660           // Get all the listeners from the deployment descriptor
  661           ListenerType[] listeners = webApp.getListenerArray();
  662           for (ListenerType listener : listeners) {
  663               FullyQualifiedClassType cls = listener.getListenerClass();
  664               Class<?> clas;
  665               try {
  666                   clas = classLoader.loadClass(cls.getStringValue());
  667               } catch (ClassNotFoundException e) {
  668                   throw new DeploymentException("AbstractWebModuleBuilder: Could not load listener class: " + cls.getStringValue(), e);
  669               }
  670               addClass(classes, clas);
  671           }
  672   
  673           // Get all the filters from the deployment descriptor
  674           FilterType[] filters = webApp.getFilterArray();
  675           for (FilterType filter : filters) {
  676               FullyQualifiedClassType cls = filter.getFilterClass();
  677               Class<?> clas;
  678               try {
  679                   clas = classLoader.loadClass(cls.getStringValue());
  680               } catch (ClassNotFoundException e) {
  681                   throw new DeploymentException("AbstractWebModuleBuilder: Could not load filter class: " + cls.getStringValue(), e);
  682               }
  683               addClass(classes, clas);
  684           }
  685   
  686           // see https://issues.apache.org/jira/browse/GERONIMO-3421 .
  687           // if the user has botched her classloader config (perhaps by
  688           // not including a jar that her app needs) then ClassFinder
  689           // will throw NoClassDefFoundError.  we want to indicate that
  690           // it's the user's error and provide a little context to help
  691           // her fix it.
  692           try {
  693               return new ClassFinder(classes);
  694           } catch (NoClassDefFoundError e) {
  695               throw new DeploymentException("Classloader for " + webApp.getId() + "can't find " + e.getMessage(), e);
  696           }
  697       }
  698   
  699       private static void addClass(List<Class> classes, Class<?> clas) {
  700           while (clas != Object.class) {
  701               classes.add(clas);
  702               clas = clas.getSuperclass();
  703           }
  704       }
  705   
  706       protected void configureBasicWebModuleAttributes(WebAppType webApp, XmlObject vendorPlan, EARContext moduleContext, EARContext earContext, WebModule webModule, GBeanData webModuleData) throws DeploymentException {
  707           Map<NamingBuilder.Key, Object> buildingContext = new HashMap<NamingBuilder.Key, Object>();
  708           buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, moduleContext.getModuleName());
  709   
  710           if (!webApp.getMetadataComplete()) {
  711               // Create a classfinder and populate it for the naming builder(s). The absence of a
  712               // classFinder in the module will convey whether metadata-complete is set (or not)
  713               webModule.setClassFinder(createWebAppClassFinder(webApp, webModule));
  714               SecurityAnnotationHelper.processAnnotations(webApp, webModule.getClassFinder());
  715           }
  716           //N.B. we use the ear context which has all the gbeans we could possibly be looking up from this ear.
  717           //nope, persistence units can be in the war.
  718           //This means that you cannot use the default environment of the web builder to add configs that will be searched.
  719           getNamingBuilders().buildNaming(webApp, vendorPlan, webModule, buildingContext);
  720   
  721           Map compContext = NamingBuilder.JNDI_KEY.get(buildingContext);
  722           Holder holder = NamingBuilder.INJECTION_KEY.get(buildingContext);
  723   
  724           webModule.getSharedContext().put(WebModule.WEB_APP_DATA, webModuleData);
  725           webModule.getSharedContext().put(NamingBuilder.JNDI_KEY, compContext);
  726           webModule.getSharedContext().put(NamingBuilder.INJECTION_KEY, holder);
  727           if (moduleContext.getServerName() != null) {
  728               webModuleData.setReferencePattern("J2EEServer", moduleContext.getServerName());
  729           }
  730           if (!webModule.isStandAlone()) {
  731               webModuleData.setReferencePattern("J2EEApplication", earContext.getModuleName());
  732           }
  733   
  734           webModuleData.setAttribute("holder", holder);
  735   
  736           //Add dependencies on managed connection factories and ejbs in this app
  737           //This is overkill, but allows for people not using java:comp context (even though we don't support it)
  738           //and sidesteps the problem of circular references between ejbs.
  739           if (earContext != moduleContext) {
  740               addGBeanDependencies(earContext, webModuleData);
  741           }
  742   
  743           webModuleData.setAttribute("componentContext", compContext);
  744           webModuleData.setReferencePattern("TransactionManager", moduleContext.getTransactionManagerName());
  745           webModuleData.setReferencePattern("TrackedConnectionAssociator", moduleContext.getConnectionTrackerName());
  746       }
  747   
  748       private static class InternWrapper implements XMLStreamReader {
  749           private final XMLStreamReader delegate;
  750   
  751           private InternWrapper(XMLStreamReader delegate) {
  752               this.delegate = delegate;
  753           }
  754   
  755           public void close() throws XMLStreamException {
  756                    delegate.close();
  757               }
  758   
  759               public int getAttributeCount() {
  760                   return  delegate.getAttributeCount();
  761               }
  762   
  763               public String getAttributeLocalName(int i) {
  764                   return  delegate.getAttributeLocalName(i);
  765               }
  766   
  767               public QName getAttributeName(int i) {
  768                   return  delegate.getAttributeName(i);
  769               }
  770   
  771               public String getAttributeNamespace(int i) {
  772                   return  delegate.getAttributeNamespace(i);
  773               }
  774   
  775               public String getAttributePrefix(int i) {
  776                   return  delegate.getAttributePrefix(i);
  777               }
  778   
  779               public String getAttributeType(int i) {
  780                   return  delegate.getAttributeType(i);
  781               }
  782   
  783               public String getAttributeValue(int i) {
  784                   return  delegate.getAttributeValue(i);
  785               }
  786   
  787               public String getAttributeValue(String s, String s1) {
  788                   return  delegate.getAttributeValue(s, s1);
  789               }
  790   
  791               public String getCharacterEncodingScheme() {
  792                   return  delegate.getCharacterEncodingScheme();
  793               }
  794   
  795               public String getElementText() throws XMLStreamException {
  796                   return  delegate.getElementText();
  797               }
  798   
  799               public String getEncoding() {
  800                   return  delegate.getEncoding();
  801               }
  802   
  803               public int getEventType() {
  804                   return  delegate.getEventType();
  805               }
  806   
  807               public String getLocalName() {
  808                   return  delegate.getLocalName().intern();
  809               }
  810   
  811               public Location getLocation() {
  812                   return  delegate.getLocation();
  813               }
  814   
  815               public QName getName() {
  816                   return  delegate.getName();
  817               }
  818   
  819               public NamespaceContext getNamespaceContext() {
  820                   return  delegate.getNamespaceContext();
  821               }
  822   
  823               public int getNamespaceCount() {
  824                   return  delegate.getNamespaceCount();
  825               }
  826   
  827               public String getNamespacePrefix(int i) {
  828                   return  delegate.getNamespacePrefix(i);
  829               }
  830   
  831               public String getNamespaceURI() {
  832                   return  delegate.getNamespaceURI().intern();
  833               }
  834   
  835               public String getNamespaceURI(int i) {
  836                   return  delegate.getNamespaceURI(i);
  837               }
  838   
  839               public String getNamespaceURI(String s) {
  840                   return  delegate.getNamespaceURI(s);
  841               }
  842   
  843               public String getPIData() {
  844                   return  delegate.getPIData();
  845               }
  846   
  847               public String getPITarget() {
  848                   return  delegate.getPITarget();
  849               }
  850   
  851               public String getPrefix() {
  852                   return  delegate.getPrefix();
  853               }
  854   
  855               public Object getProperty(String s) throws IllegalArgumentException {
  856                   return  delegate.getProperty(s);
  857               }
  858   
  859               public String getText() {
  860                   return  delegate.getText();
  861               }
  862   
  863               public char[] getTextCharacters() {
  864                   return  delegate.getTextCharacters();
  865               }
  866   
  867               public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException {
  868                   return  delegate.getTextCharacters(i, chars, i1, i2);
  869               }
  870   
  871               public int getTextLength() {
  872                   return  delegate.getTextLength();
  873               }
  874   
  875               public int getTextStart() {
  876                   return  delegate.getTextStart();
  877               }
  878   
  879               public String getVersion() {
  880                   return  delegate.getVersion();
  881               }
  882   
  883               public boolean hasName() {
  884                   return  delegate.hasName();
  885               }
  886   
  887               public boolean hasNext() throws XMLStreamException {
  888                   return  delegate.hasNext();
  889               }
  890   
  891               public boolean hasText() {
  892                   return  delegate.hasText();
  893               }
  894   
  895               public boolean isAttributeSpecified(int i) {
  896                   return  delegate.isAttributeSpecified(i);
  897               }
  898   
  899               public boolean isCharacters() {
  900                   return  delegate.isCharacters();
  901               }
  902   
  903               public boolean isEndElement() {
  904                   return  delegate.isEndElement();
  905               }
  906   
  907               public boolean isStandalone() {
  908                   return  delegate.isStandalone();
  909               }
  910   
  911               public boolean isStartElement() {
  912                   return  delegate.isStartElement();
  913               }
  914   
  915               public boolean isWhiteSpace() {
  916                   return  delegate.isWhiteSpace();
  917               }
  918   
  919               public int next() throws XMLStreamException {
  920                   return  delegate.next();
  921               }
  922   
  923               public int nextTag() throws XMLStreamException {
  924                   return  delegate.nextTag();
  925               }
  926   
  927               public void require(int i, String s, String s1) throws XMLStreamException {
  928                    delegate.require(i, s, s1);
  929               }
  930   
  931               public boolean standaloneSet() {
  932                   return  delegate.standaloneSet();
  933               }
  934       }
  935       
  936   }

Home » geronimo-2.2-source-release » org.apache.geronimo.web25.deployment » [javadoc | source]