Package org.jboss.deployment

Source Code of org.jboss.deployment.EARStructure

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.deployment;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.jboss.deployers.spi.DeploymentException;
import org.jboss.deployers.spi.structure.ContextInfo;
import org.jboss.deployers.structure.spi.helpers.RelativeDeploymentContextComparator;
import org.jboss.deployers.vfs.plugins.structure.AbstractVFSArchiveStructureDeployer;
import org.jboss.deployers.vfs.spi.structure.StructureContext;
import org.jboss.metadata.ear.jboss.JBossAppMetaData;
import org.jboss.metadata.ear.jboss.ServiceModuleMetaData;
import org.jboss.metadata.ear.jboss.JBossAppMetaData.ModuleOrder;
import org.jboss.metadata.ear.spec.AbstractModule;
import org.jboss.metadata.ear.spec.ConnectorModuleMetaData;
import org.jboss.metadata.ear.spec.EarMetaData;
import org.jboss.metadata.ear.spec.EjbModuleMetaData;
import org.jboss.metadata.ear.spec.JavaModuleMetaData;
import org.jboss.metadata.ear.spec.ModuleMetaData;
import org.jboss.metadata.ear.spec.ModulesMetaData;
import org.jboss.metadata.ear.spec.WebModuleMetaData;
import org.jboss.vfs.VFSUtils;
import org.jboss.vfs.VirtualFile;
import org.jboss.vfs.VirtualFileFilter;
import org.jboss.vfs.util.SuffixMatchFilter;
import org.jboss.vfs.util.automount.Automounter;
import org.jboss.xb.binding.Unmarshaller;
import org.jboss.xb.binding.UnmarshallerFactory;
import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingResolver;
import org.jboss.xb.binding.sunday.unmarshalling.SingletonSchemaResolverFactory;

/**
* Structure deployer for EARs.
*
* @author Bill Burke
* @author Scott.Stark@jboss.org
* @author adrian@jboss.org
* @version $Revision: 102183 $
*/
public class EARStructure extends AbstractVFSArchiveStructureDeployer
{
   /**
    * The default ear/lib filter
    */
   public static final VirtualFileFilter DEFAULT_EAR_LIB_FILTER = new SuffixMatchFilter(".jar");

   /**
    * The ear/lib filter
    */
   private VirtualFileFilter earLibFilter = DEFAULT_EAR_LIB_FILTER;
   /** The schema resolver used to determine which schema to use for application.xml/jboss-app.xml */
   private SchemaBindingResolver resolver = SingletonSchemaResolverFactory.getInstance().getSchemaBindingResolver();
   /** unmarshaller factory */
   UnmarshallerFactory unmarshallerFactory = UnmarshallerFactory.newInstance();
   /** The root in classpath flag */
   private boolean includeEarRootInClasspath = true;
   /** The ear child context comparator */
   private String comparatorClassName;
   /** whether to validate deployment descriptors */
   private boolean useValidation = true;

   /**
    * Set the relative order to 1000 by default
    */
   public EARStructure()
   {
      setRelativeOrder(1000);
   }

   /**
    * Get the earLibFilter.
    *
    * @return the earLibFilter.
    */
   public VirtualFileFilter getEarLibFilter()
   {
      return earLibFilter;
   }

   /**
    * Set the earLibFilter.
    *
    * @param earLibFilter the earLibFilter.
    * @throws IllegalArgumentException for a null filter
    */
   public void setEarLibFilter(VirtualFileFilter earLibFilter)
   {
      if (earLibFilter == null)
         throw new IllegalArgumentException("Null filter");
      this.earLibFilter = earLibFilter;
   }

   /**
    * Get the schema resolver
    * @return the schema resolver
    */
   public SchemaBindingResolver getResolver()
   {
      return resolver;
   }
   /**
    * Set the schema resolver
    * @param resolver the schema resolver
    */
   public void setResolver(SchemaBindingResolver resolver)
   {
      this.resolver = resolver;
   }
  
   @Override
   protected boolean hasValidSuffix(String name)
   {
      return name.toLowerCase().endsWith(".ear");
   }

   public boolean doDetermineStructure(StructureContext structureContext) throws DeploymentException
   {
      ContextInfo context;
      boolean valid;
      boolean trace = log.isTraceEnabled();
      VirtualFile file = structureContext.getFile();
      try
      {
         if (hasValidName(file) == false)
            return false;

         context = createContext(structureContext, "META-INF");
         context.setComparatorClassName(comparatorClassName);

         VirtualFile applicationXml = getMetaDataFile(file, "META-INF/application.xml");
         VirtualFile jbossAppXml = getMetaDataFile(file, "META-INF/jboss-app.xml");
         VirtualFile lib;

         boolean scan = true;

         Unmarshaller unmarshaller = unmarshallerFactory.newUnmarshaller();
         unmarshaller.setValidation(useValidation);
         EarMetaData specMetaData = null;
         JBossAppMetaData appMetaData = null;
         if (applicationXml != null)
         {
            InputStream in = applicationXml.openStream();
            try
            {
               specMetaData = (EarMetaData) unmarshaller.unmarshal(in, resolver);
            }
            finally
            {
               in.close();
            }
            scan = false;
         }
         if (jbossAppXml != null)
         {
            InputStream in = jbossAppXml.openStream();
            try
            {
               appMetaData = (JBossAppMetaData) unmarshaller.unmarshal(in, resolver);
            }
            finally
            {
               in.close();
            }
         }
         // Need a metadata instance and there will not be one if there are no descriptors
         if (appMetaData == null)
         {
            appMetaData = new JBossAppMetaData();
         }
         // Create the merged view
         appMetaData.merge(appMetaData, specMetaData);

         String libDir = appMetaData.getLibraryDirectory();
         if (libDir == null || libDir.length() > 0)
         {
            if (libDir == null)
               libDir = "lib";

            // Add the ear lib contents to the classpath
            if(trace)
               log.trace("Checking for ear lib directory: "+libDir);
            try
            {
               lib = file.getChild(libDir);
               if (lib.exists())
               {
                  if(trace)
                     log.trace("Found ear lib directory: "+lib);
                  List<VirtualFile> archives = lib.getChildren(earLibFilter);
                  for (VirtualFile archive : archives)
                  {
                     Automounter.mount(file, archive);
                     addClassPath(structureContext, archive, true, true, context);
                     // add any jars with persistence.xml as a deployment
                     if (archive.getChild("META-INF/persistence.xml").exists())
                     {
                        log.trace(archive.getName() + " in ear lib directory has persistence units");
                        if (structureContext.determineChildStructure(archive) == false)
                        {
                           throw new RuntimeException(archive.getName()
                                 + " in lib directory has persistence.xml but is not a recognized deployment, .ear: "
                                 + file.getName());
                        }
                     }
                     else if (trace)
                        log.trace(archive.getPathName() + " does not contain META-INF/persistence.xml");
                  }
               }
               else if (trace)
                  log.trace("No lib directory in ear archive.");
            }
            catch (IOException e)
            {
               // TODO - should we throw this fwd?
               log.warn("Exception while searching for lib dir: " + e);
            }
         }
         else if (trace)
         {
            log.trace("Ignoring library directory, got empty library-directory element.");
         }

         // Add the ear manifest locations?
         addClassPath(structureContext, file, includeEarRootInClasspath, true, context);

         // TODO: need to scan for annotationss
         if( scan )
         {
            scanEar(file, appMetaData);
         }

         // Create subdeployments for the ear modules
         ModulesMetaData modules = appMetaData.getModules();
         if(modules != null)
         {
            for (ModuleMetaData mod : modules)
            {
               String fileName = mod.getFileName();
               if (fileName != null && (fileName = fileName.trim()).length() > 0)
               {
                  if (log.isTraceEnabled())
                     log.trace("Checking application.xml module: " + fileName);

                  VirtualFile module = file.getChild(fileName);
                  if (module.exists() == false)
                  {
                     throw new RuntimeException(fileName + " module listed in application.xml does not exist within .ear " + file.toURI());


                  }
                  // Ask the deployers to analyze this
                  if(structureContext.determineChildStructure(module) == false)
                  {
                     throw new RuntimeException(fileName
                           + " module listed in application.xml is not a recognized deployment, .ear: "
                           + file.getName());
                  }
               }
            }

            if (appMetaData.getModuleOrderEnum() == ModuleOrder.STRICT)
            {
               context.setComparatorClassName(RelativeDeploymentContextComparator.class.getName());
               int i = 0;
               for (ContextInfo ctx : structureContext.getMetaData().getContexts())
               {
                  ctx.setRelativeOrder(i++);
               }
            }
         }

         valid = true;
      }
      catch(Exception e)
      {
         throw new RuntimeException("Error determining structure: " + file.getName(), e);
      }

      return valid;
   }

   /**
   For an ear without an application.xml, determine modules via:
   a. All ear modules with an extension of .war are considered web modules. The
    context root of the web module is the name of the file relative to the root
    of the application package, with the .war extension removed.
   b. All ear modules with extension of .rar are considered resource adapters.
   c. A directory named lib is considered to be the library directory, as
    described in Section�EE.8.2.1, �Bundled Libraries.�
   d. For all ear modules with a filename extension of .jar, but not in the lib
    directory, do the following:
   i. If the JAR file contains a META-INF/MANIFEST.MF file with a Main-Class
    attribute, or contains a META-INF/application-client.xml file, consider the
    jar file to be an application client module.
   ii. If the JAR file contains a META-INF/ejb-jar.xml file, or contains any
   class with an EJB component annotation (Stateless, etc.), consider the JAR
    file to be an EJB module.
   iii. All other JAR files are ignored unless referenced by a JAR file
    discovered above using one of the JAR file reference mechanisms such as the
    Class-Path header in a manifest file.
    * TODO: rewrite using vfs
    */
   private void scanEar(VirtualFile root, JBossAppMetaData appMetaData) throws IOException
   {
      List<VirtualFile> archives = root.getChildren();
      if (archives != null)
      {
         String earPath = root.getPathName();
         ModulesMetaData modules = appMetaData.getModules();
         if (modules == null)
         {
            modules = new ModulesMetaData();
            appMetaData.setModules(modules);
         }
         for (VirtualFile vfArchive : archives)
         {
            String filename = earRelativePath(earPath, vfArchive.getPathName());
            // Check if the module already exists, i.e. it is declared in jboss-app.xml
            ModuleMetaData moduleMetaData = appMetaData.getModule(filename);
            int type = typeFromSuffix(filename, vfArchive);
            if (type >= 0 && moduleMetaData == null)
            {
               moduleMetaData = new ModuleMetaData();
               AbstractModule module = null;
               switch(type)
               {
                  case J2eeModuleMetaData.EJB:
                     module = new EjbModuleMetaData();
                     break;
                  case J2eeModuleMetaData.CLIENT:
                     module = new JavaModuleMetaData();
                     break;
                  case J2eeModuleMetaData.CONNECTOR:
                     module = new ConnectorModuleMetaData();
                     break;
                  case J2eeModuleMetaData.SERVICE:
                  case J2eeModuleMetaData.HAR:
                     module = new ServiceModuleMetaData();
                     break;
                  case J2eeModuleMetaData.WEB:
                     module = new WebModuleMetaData();
                     break;
               }
               module.setFileName(filename);
               moduleMetaData.setValue(module);
               modules.add(moduleMetaData);
            }
         }
      }
   }

   private int typeFromSuffix(String path, VirtualFile archive)
      throws IOException
   {
      int type = -1;
      if( path.endsWith(".war") )
         type = J2eeModuleMetaData.WEB;
      else if( path.endsWith(".rar") )
         type = J2eeModuleMetaData.CONNECTOR;
      else if( path.endsWith(".har") )
         type = J2eeModuleMetaData.HAR;
      else if( path.endsWith(".sar") )
         type = J2eeModuleMetaData.SERVICE;
      else if( path.endsWith(".jar") )
      {
         // Look for a META-INF/application-client.xml
         VirtualFile mfFile = getMetaDataFile(archive, "META-INF/MANIFEST.MF");
         VirtualFile clientXml = getMetaDataFile(archive, "META-INF/application-client.xml");
         VirtualFile ejbXml = getMetaDataFile(archive, "META-INF/ejb-jar.xml");
         VirtualFile jbossXml = getMetaDataFile(archive, "META-INF/jboss.xml");

         if( clientXml != null )
         {
            type = J2eeModuleMetaData.CLIENT;
         }
         else if( mfFile != null )
         {
            Manifest mf = VFSUtils.readManifest(mfFile);
            Attributes attrs = mf.getMainAttributes();
            if( attrs.containsKey(Attributes.Name.MAIN_CLASS) )
            {
               type = J2eeModuleMetaData.CLIENT;
            }
            else
            {
               // TODO: scan for annotations. Assume EJB for now
               type = J2eeModuleMetaData.EJB;
            }
         }
         else if( ejbXml != null || jbossXml != null )
         {
            type = J2eeModuleMetaData.EJB;
         }
         else
         {
            // TODO: scan for annotations. Assume EJB for now
            type = J2eeModuleMetaData.EJB;
         }
      }

      return type;
   }

   private String earRelativePath(String earPath, String pathName)
   {
      StringBuilder tmp = new StringBuilder(pathName);
      tmp.delete(0, earPath.length() + 1);
      return tmp.toString();
   }

   private VirtualFile getMetaDataFile(VirtualFile file, String path)
   {
      VirtualFile metaFile = null;
      metaFile = file.getChild(path);
      return metaFile.exists() ? metaFile : null;
   }

   public void setIncludeEarRootInClasspath(boolean includeEarRootInClasspath)
   {
      this.includeEarRootInClasspath = includeEarRootInClasspath;
   }

   public void setComparatorClassName(String comparatorClassName)
   {
      this.comparatorClassName = comparatorClassName;
   }

   public void setUseValidation(boolean validateXml)
   {
      this.useValidation = validateXml;
   }

   public boolean isUseValidation()
   {
      return useValidation;
   }
}
TOP

Related Classes of org.jboss.deployment.EARStructure

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.