You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by do...@apache.org on 2002/05/11 04:05:13 UTC

cvs commit: jakarta-avalon-phoenix/src/xdocs environment-xml-specification.xml

donaldp     02/05/10 19:05:13

  Modified:    src/java/org/apache/avalon/phoenix/components/classloader
                        DefaultClassLoaderManager.java DefaultPolicy.java
               src/java/org/apache/avalon/phoenix/components/deployer
                        DefaultDeployer.java Resources.properties
               src/java/org/apache/avalon/phoenix/components/embeddor
                        DefaultEmbeddor.java
               src/java/org/apache/avalon/phoenix/interfaces
                        ClassLoaderManager.java
               src/xdocs environment-xml-specification.xml
  Added:       src/java/org/apache/avalon/phoenix/components/deployer/installer
                        FileDigest.java Installation.java
                        InstallationException.java Installer.java
                        Resources.properties package.html
  Removed:     src/java/org/apache/avalon/phoenix/tools/installer
                        FileDigest.java Installation.java
                        InstallationException.java Installer.java
                        Resources.properties package.html
  Log:
  Reworked Installation, deployment etc so that the Jars and classes in an
  application are extracted to a temporary "work" directory (defaults to sub-dir $PHOENIX_HOME/work).
  
  Each deployment uses a unique directory thus there will not be any problem with the JVM caching the Classes loaded from a URL. Each work directory is deleted at undeployment.
  
  Unfortunately people who were relying on the <policy/> section may need to change some options in certain circumstances. If previously you were assigning permissions to jars based on the jars being included in the applicaiton directory via something like
  
  <grant code-base="file:${app.home}${/}SAR-INF${/}lib${/}*">
  
  This will need to be updated to use URLs of the form
  
  <grant code-base="sar:/SAR-INF/lib/*">
  
  Revision  Changes    Path
  1.31      +7 -3      jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/DefaultClassLoaderManager.java
  
  Index: DefaultClassLoaderManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/DefaultClassLoaderManager.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- DefaultClassLoaderManager.java	10 May 2002 11:08:56 -0000	1.30
  +++ DefaultClassLoaderManager.java	11 May 2002 02:05:13 -0000	1.31
  @@ -108,6 +108,7 @@
       public ClassLoader createClassLoader( final Configuration environment,
                                             final File source,
                                             final File homeDirectory,
  +                                          final File workDirectory,
                                             final String[] classPath )
           throws Exception
       {
  @@ -120,7 +121,8 @@
   
           //Configure policy
           final Configuration policyConfig = environment.getChild( "policy" );
  -        final Policy policy = configurePolicy( policyConfig, homeDirectory );
  +        final Policy policy =
  +            configurePolicy( policyConfig, homeDirectory, workDirectory );
   
           final File[] extensions = getOptionalPackagesFor( classPath );
           if( getLogger().isDebugEnabled() )
  @@ -252,10 +254,12 @@
        * @throws ConfigurationException if an error occurs
        */
       private Policy configurePolicy( final Configuration configuration,
  -                                    final File baseDirectory )
  +                                    final File baseDirectory,
  +                                    final File workDirectory )
           throws ConfigurationException
       {
  -        final DefaultPolicy policy = new DefaultPolicy( baseDirectory );
  +        final DefaultPolicy policy =
  +            new DefaultPolicy( baseDirectory, workDirectory );
           policy.enableLogging( getLogger() );
           policy.configure( configuration );
           return policy;
  
  
  
  1.6       +56 -2     jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/DefaultPolicy.java
  
  Index: DefaultPolicy.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/DefaultPolicy.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DefaultPolicy.java	16 Mar 2002 00:11:54 -0000	1.5
  +++ DefaultPolicy.java	11 May 2002 02:05:13 -0000	1.6
  @@ -42,15 +42,25 @@
       private static final Resources REZ =
           ResourceManager.getPackageResources( DefaultPolicy.class );
   
  +    private static final String SAR_PROTOCOL = "sar:";
  +    private static final String SAR_INF = SAR_PROTOCOL + "SAR-INF/";
  +    private static final String CLASSES = SAR_INF + "classes";
  +    private static final String LIB = SAR_INF + "lib";
  +
  +    private final File m_baseDirectory;
  +    private final File m_workDirectory;
       private DefaultContext m_context;
   
  -    protected DefaultPolicy( final File baseDirectory )
  +    protected DefaultPolicy( final File baseDirectory,
  +                             final File workDirectory )
       {
           final HashMap map = new HashMap();
           map.putAll( System.getProperties() );
           m_context = new DefaultContext( map );
           m_context.put( "/", File.separator );
           m_context.put( "app.home", baseDirectory );
  +        m_workDirectory = workDirectory;
  +        m_baseDirectory = baseDirectory;
       }
   
       public void configure( final Configuration configuration )
  @@ -68,7 +78,8 @@
           }
           else
           {
  -            final String message = REZ.getString( "policy.notice.full-perms" );
  +            final String message =
  +                REZ.getString( "policy.notice.full-perms" );
               getLogger().info( message );
               final Permissions permissions = createPermissionSetFor( getInclusiveURL(), null );
               permissions.add( new java.security.AllPermission() );
  @@ -173,6 +184,7 @@
           if( null != codeBase )
           {
               codeBase = expand( codeBase );
  +            codeBase = expandSarURL( codeBase );
           }
   
           final Certificate[] signers = getSigners( signedBy, keyStoreName, keyStores );
  @@ -225,6 +237,48 @@
           final Permission permission = createPermission( type, target, actions, signers );
   
           permissions.add( permission );
  +    }
  +
  +    /**
  +     * Expand any URLs with sar: protocol so that
  +     * they accurately match the actual location
  +     *
  +     * @param codeBase the input url
  +     * @return the result url, modified to file url if it
  +     *         is protocol "sar:"
  +     * @throws ConfigurationException if invalidly specified URL
  +     */
  +    private String expandSarURL( final String codeBase )
  +        throws ConfigurationException
  +    {
  +        if( codeBase.startsWith( SAR_PROTOCOL ) )
  +        {
  +            final String filename =
  +                codeBase.substring( 4 ).replace( '/', File.separatorChar );
  +            File baseDir = null;
  +            if( codeBase.startsWith( CLASSES ) ||
  +                codeBase.startsWith( LIB ) )
  +            {
  +                baseDir = m_workDirectory;
  +            }
  +            else
  +            {
  +                baseDir = m_baseDirectory;
  +            }
  +            final File file = new File( baseDir, filename );
  +            try
  +            {
  +                return file.toURL().toString();
  +            }
  +            catch( MalformedURLException e )
  +            {
  +                throw new ConfigurationException( e.getMessage(), e );
  +            }
  +        }
  +        else
  +        {
  +            return codeBase;
  +        }
       }
   
       private String expand( final String value )
  
  
  
  1.26      +37 -6     jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/DefaultDeployer.java
  
  Index: DefaultDeployer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/DefaultDeployer.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- DefaultDeployer.java	10 May 2002 15:32:14 -0000	1.25
  +++ DefaultDeployer.java	11 May 2002 02:05:13 -0000	1.26
  @@ -13,9 +13,11 @@
   import java.net.URL;
   import java.util.Hashtable;
   import java.util.Map;
  +import java.util.Set;
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.avalon.framework.activity.Initializable;
  +import org.apache.avalon.framework.activity.Disposable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  @@ -39,8 +41,8 @@
   import org.apache.avalon.phoenix.tools.assembler.Assembler;
   import org.apache.avalon.phoenix.tools.assembler.AssemblyException;
   import org.apache.avalon.phoenix.tools.configuration.ConfigurationBuilder;
  -import org.apache.avalon.phoenix.tools.installer.Installation;
  -import org.apache.avalon.phoenix.tools.installer.Installer;
  +import org.apache.avalon.phoenix.components.deployer.installer.Installation;
  +import org.apache.avalon.phoenix.components.deployer.installer.Installer;
   import org.apache.avalon.phoenix.tools.verifier.SarVerifier;
   import org.apache.log.Hierarchy;
   
  @@ -51,7 +53,7 @@
    */
   public class DefaultDeployer
       extends AbstractLogEnabled
  -    implements Deployer, Parameterizable, Serviceable, Initializable, DeployerMBean
  +    implements Deployer, Parameterizable, Serviceable, Initializable, Disposable, DeployerMBean
   {
       private static final Resources REZ =
           ResourceManager.getPackageResources( DefaultDeployer.class );
  @@ -125,6 +127,33 @@
       }
   
       /**
  +     * Dispose the dpeloyer which effectively means undeploying
  +     * all the currently deployed apps.
  +     */
  +    public void dispose()
  +    {
  +        final Set set = m_installations.keySet();
  +        final String[] applications =
  +            (String[])set.toArray( new String[set.size() ] );
  +        for( int i = 0; i < applications.length; i++ )
  +        {
  +            final String name = applications[ i ];
  +            try
  +            {
  +                undeploy( name );
  +            }
  +            catch( final DeploymentException de )
  +            {
  +                final String message =
  +                    REZ.getString( "deploy.undeploy-indispose.error",
  +                    name,
  +                    de.getMessage() );
  +                getLogger().error( message, de );
  +            }
  +        }
  +    }
  +
  +    /**
        * Undeploy an application.
        *
        * @param name the name of deployment
  @@ -154,7 +183,7 @@
                   m_repository.storeConfiguration( name, blocks[ i ], null );
               }
   
  -            m_installer.uninstall( installation );
  +            m_installer.uninstall( installation, m_baseWorkDirectory );
           }
           catch( final Exception e )
           {
  @@ -195,7 +224,8 @@
           try
           {
               //m_baseWorkDirectory
  -            final Installation installation = m_installer.install( location );
  +            final Installation installation =
  +                m_installer.install( location, m_baseWorkDirectory );
   
               final Configuration config = getConfigurationFor( installation.getConfig() );
               final Configuration server = getConfigurationFor( installation.getEnvironment() );
  @@ -206,7 +236,8 @@
               final ClassLoader classLoader =
                   m_classLoaderManager.createClassLoader( server,
                                                           installation.getSource(),
  -                                                        directory,
  +                                                        installation.getDirectory(),
  +                                                        installation.getWorkDirectory(),
                                                           installation.getClassPath() );
               //assemble all the blocks for application
               final SarMetaData metaData =
  
  
  
  1.13      +2 -1      jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/Resources.properties,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Resources.properties	10 May 2002 15:32:14 -0000	1.12
  +++ Resources.properties	11 May 2002 02:05:13 -0000	1.13
  @@ -7,4 +7,5 @@
   deploy.bad-workdir.error=Bad work directory "{0}" specified.
   deploy.workdir-nocreate.error=Failed to create work directory {0}.
   deploy.workdir-notadir.error=Work directory {0} is not a directory.
  -deploy.create-dir.notice=Work directory does not exist, attempting to create directory {0}.
  \ No newline at end of file
  +deploy.create-dir.notice=Work directory does not exist, attempting to create directory {0}.
  +deploy.undeploy-indispose.error=Error undeploying application "{0}" when disposing Deployer. (Reason: {1})
  \ No newline at end of file
  
  
  
  1.1                  jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/installer/FileDigest.java
  
  Index: FileDigest.java
  ===================================================================
  package org.apache.avalon.phoenix.components.deployer.installer;
  
  import java.io.File;
  
  /**
   * FileDigest holds file deployment information. Information
   * used to verify if file was modified since deployment.
   *
   * @version $Revision: 1.1 $ $Date: 2002/05/11 02:05:13 $
   */
  public class FileDigest
  {
      private final File m_file;
      private final long m_checksum;
  
      /** Create a new FileDigest object.
       *
       * @param file the file.
       * @param checksum the checksum value of the file.
       */
      public FileDigest( final File file, final long checksum )
      {
          m_file = file;
          m_checksum = checksum;
      }
  
      /** Retrieve the file.
       *
       * @return the file.
       */
      public File getFile()
      {
          return m_file;
      }
  
      /** Retrieve the checksum calculated at deployment time.
       *
       * @return the checksum value.
       */
      public long getChecksum()
      {
          return m_checksum;
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/installer/Installation.java
  
  Index: Installation.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.phoenix.components.deployer.installer;
  
  import java.io.File;
  
  /**
   * Descriptor for installation.
   * This descriptor contains all the information relating to
   * installed application. In particular it locates all the
   * jars in Classpath, config files and installation directory.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/05/11 02:05:13 $
   */
  public final class Installation
  {
      ///The source of installation (usually a directory in .sar format or a .sar file)
      private final File m_source;
  
      ///Directory in which application is installed
      private final File m_directory;
  
      ///Directory in which application temporary/work data is stored
      private final File m_workDirectory;
  
      ///URL to block configuration data
      private final String m_config;
  
      ///URL to assembly data
      private final String m_assembly;
  
      ///URL to application configuration data
      private final String m_environment;
  
      ///ClassPath for application
      private final String[] m_classPath;
  
      ///Info for expanded files
      private final FileDigest[] m_digests;
  
      ///Installation timestamp
      private final long m_timestamp;
  
      public Installation( final File source,
                           final File directory,
                           final File workDirectory,
                           final String config,
                           final String assembly,
                           final String environment,
                           final String[] classPath,
                           final FileDigest[] digests,
                           final long timestamp )
      {
          m_source = source;
          m_directory = directory;
          m_workDirectory = workDirectory;
          m_config = config;
          m_assembly = assembly;
          m_environment = environment;
          m_classPath = classPath;
          m_digests = digests;
          m_timestamp = timestamp;
      }
  
      /**
       * Get the source of application. (Usually a
       * directory in .sar format or a .sar)
       *
       * @return the source of application
       */
      public File getSource()
      {
          return m_source;
      }
  
      /**
       * Get directory application is installed into.
       *
       * @return the applications base directory
       */
      public File getDirectory()
      {
          return m_directory;
      }
  
      /**
       * Get the directory in which temporary data for this application
       * is stored.
       *
       * @return the work directory for application.
       */
      public File getWorkDirectory()
      {
          return m_workDirectory;
      }
  
      /**
       * Retrieve location of applications config.xml file.
       *
       * @return url to config.xml file
       */
      public String getConfig()
      {
          return m_config;
      }
  
      /**
       * Retrieve location of applications assembly.xml file.
       *
       * @return url to assembly.xml file
       */
      public String getAssembly()
      {
          return m_assembly;
      }
  
      /**
       * Retrieve location of applications environment.xml file.
       *
       * @return url to environment.xml file
       */
      public String getEnvironment()
      {
          return m_environment;
      }
  
      /**
       * Retrieve ClassPath for application.
       *
       * @return the classpath
       */
      public String[] getClassPath()
      {
          return m_classPath;
      }
  
      /** Retrieve file digests.
       *
       * @return the file digest list.
       */
      public FileDigest[] getFileDigests()
      {
          return m_digests;
      }
  
      /** Retrieve the timestamp.
       *
       * @return the timestamp when installation occured.
       */
      public long getTimestamp()
      {
          return m_timestamp;
      }
  }
  
  
  
  1.1                  jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/installer/InstallationException.java
  
  Index: InstallationException.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.phoenix.components.deployer.installer;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * Exception to indicate error deploying.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/05/11 02:05:13 $
   */
  public final class InstallationException
      extends CascadingException
  {
      /**
       * Construct a new <code>InstallationException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public InstallationException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>InstallationException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public InstallationException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  1.1                  jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/installer/Installer.java
  
  Index: Installer.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.phoenix.components.deployer.installer;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.Enumeration;
  import java.util.zip.CRC32;
  import java.util.zip.CheckedInputStream;
  import java.util.zip.Checksum;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipFile;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.excalibur.io.ExtensionFileFilter;
  import org.apache.avalon.excalibur.io.FileUtil;
  import org.apache.avalon.excalibur.io.IOUtil;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * An Installer is responsible for taking a URL for Sar
   * and installing it as appropriate.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/05/11 02:05:13 $
   */
  public class Installer
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( Installer.class );
  
      private static final String OLD_ASSEMBLY_XML = "conf" + File.separator + "assembly.xml";
  
      private static final String OLD_CONFIG_XML = "conf" + File.separator + "config.xml";
      private static final String OLD_SERVER_XML = "conf" + File.separator + "server.xml";
      private static final String OLD_BLOCKS = "blocks";
      private static final String OLD_LIB = "lib";
  
      private static final String META_INF = "META-INF";
      private static final String SAR_INF = "SAR-INF";
      private static final String LIB = "SAR-INF/lib";
      private static final String CLASSES = "SAR-INF/classes/";
  
      //The names on the native filesystem
      private static final String FS_CONFIG_XML = "SAR-INF" + File.separator + "config.xml";
      private static final String FS_ASSEMBLY_XML = "SAR-INF" + File.separator + "assembly.xml";
      private static final String FS_SERVER_XML = "SAR-INF" + File.separator + "server.xml";
      private static final String FS_ENV_XML = "SAR-INF" + File.separator + "environment.xml";
      private static final String FS_CLASSES =
          "SAR-INF" + File.separator + "classes" + File.separator;
  
      /**
       * Uninstall the Sar designated installation.
       *
       * @param installation the installation
       * @throws InstallationException if an error occurs
       */
      public void uninstall( final Installation installation,
                             final File workDir )
          throws InstallationException
      {
          final FileDigest[] infos = installation.getFileDigests();
          final Checksum checksum = new CRC32();
  
          if( infos != null )
          {
              for( int i = 0; i < infos.length; i++ )
              {
                  final File file = infos[ i ].getFile();
                  final File parent = file.getParentFile();
  
                  final String message = REZ.getString( "skip-removal", file );
  
                  if( file.exists() )
                  {
                      if( file.lastModified() <= installation.getTimestamp() )
                      {
                          getLogger().debug( message );
                          continue;
                      }
  
                      checksum( file, checksum );
  
                      if( checksum.getValue() != infos[ i ].getChecksum() )
                      {
                          getLogger().debug( message );
                          continue;
                      }
  
                      file.delete();
                      if( 0 == parent.list().length )
                      {
                          parent.delete();
                      }
                  }
              }
          }
  
          try
          {
              FileUtil.deleteDirectory( workDir );
          }
          catch( final IOException ioe )
          {
              final String message =
                  REZ.getString( "nodelete-workdir.error",
                                 workDir,
                                 ioe.getMessage() );
              getLogger().warn( message, ioe );
          }
      }
  
      /**
       * Install the Sar designated by url.
       *
       * @param url the url of instalation
       * @throws InstallationException if an error occurs
       */
      public Installation install( final URL url,
                                   final File workDir )
          throws InstallationException
      {
          lock();
          try
          {
              final String notice = REZ.getString( "installing-sar", url );
              getLogger().info( notice );
  
              final File file = getFileFor( url );
              if( file.isDirectory() )
              {
                  final String message =
                      REZ.getString( "deprecated-sar-format", url );
                  System.err.println( message );
                  getLogger().warn( message );
                  return installDeprecated( file );
              }
  
              //Get Zipfile representing .sar file
              final ZipFile zipFile = new ZipFile( file );
              if( isDeprecated( zipFile ) )
              {
                  final String message =
                      REZ.getString( "deprecated-sar-format", url );
                  System.err.println( message );
                  getLogger().warn( message );
                  return installDeprecated( url, file, zipFile );
              }
              else
              {
                  return install( url, file, zipFile, workDir );
              }
          }
          catch( final IOException ioe )
          {
              final String message = REZ.getString( "bad-zip-file", url );
              throw new InstallationException( message, ioe );
          }
          finally
          {
              unlock();
          }
      }
  
      /**
       * Utility method to compute the checksum for a given file.
       * @param file the computed file.
       * @param checksum the checksum algorithm.
       */
      private void checksum( final File file, final Checksum checksum )
      {
          checksum.reset();
  
          InputStream input = null;
          try
          {
              input = new CheckedInputStream( new FileInputStream( file ), checksum );
              IOUtil.toByteArray( input );
          }
          catch( final IOException ioe )
          {
              final String message = REZ.getString( "checksum-failure", file );
              getLogger().warn( message );
          }
          finally
          {
              IOUtil.shutdownStream( input );
          }
      }
  
      /**
       * Check if zipfile represents the deprecated sar format or
       * whether it conforms to new format of using "SAR-INF/".
       *
       * @param zipFile the zipfile
       * @return true if old format, else false
       */
      private boolean isDeprecated( final ZipFile zipFile )
          throws InstallationException
      {
          boolean oldStyle = false;
          boolean newStyle = false;
  
          final Enumeration entries = zipFile.entries();
          while( entries.hasMoreElements() )
          {
              final ZipEntry entry = (ZipEntry)entries.nextElement();
              final String name = fixName( entry.getName() );
  
              if( name.startsWith( OLD_BLOCKS ) ||
                  name.startsWith( OLD_LIB ) ||
                  name.equals( "conf/assembly.xml" ) ||
                  name.equals( "conf/config.xml" ) ||
                  name.equals( "conf/server.xml" ) )
              {
                  oldStyle = true;
              }
  
              if( name.startsWith( SAR_INF ) )
              {
                  newStyle = true;
              }
          }
  
          if( oldStyle && newStyle )
          {
              final String message = REZ.getString( "mixed-sar" );
              throw new InstallationException( message );
          }
          else if( !oldStyle && !newStyle )
          {
              final String message = REZ.getString( "invalid-sar" );
              throw new InstallationException( message );
          }
          else
          {
              return oldStyle;
          }
      }
  
      /**
       * Utility method to lock repository to disallow other installers to access it.
       * Currently a no-op.
       */
      private void lock()
      {
      }
  
      /**
       * Utility method to unlock repository to allow other installers to access it.
       * Currently a no-op.
       */
      private void unlock()
      {
      }
  
      /**
       * Install a new style sar.
       *
       * @param url the url designator of sar
       * @param file the file of sar
       * @param zipFile the ZipFile representing sar
       * @param baseWorkDir the base directory in which to extract jars,
       *        libraries and other temporary files.
       * @return the Installation object
       */
      private Installation install( final URL url,
                                    final File file,
                                    final ZipFile zipFile,
                                    final File baseWorkDir )
          throws InstallationException
      {
          final File directory = getDestinationFor( file );
  
          //Question: Should we be making sure that
          //this directory is created?
          directory.mkdirs();
  
          final ArrayList digests = new ArrayList();
          final ArrayList jars = new ArrayList();
  
          final File workDir =
              getRelativeWorkDir( baseWorkDir, file );
  
          expandZipFile( zipFile, directory, workDir, jars, digests, url );
  
          //Retrieve name of environment file
          //need to check existence to support backwards compatability
          File envFile = new File( directory, FS_ENV_XML );
          if( !envFile.exists() )
          {
              final String message =
                  REZ.getString( "deprecated-environment-xml", url );
              System.err.println( message );
              getLogger().warn( message );
              envFile = new File( directory, FS_SERVER_XML );
          }
  
          //Prepare and create Installation
          final String[] classPath =
              (String[])jars.toArray( new String[ jars.size() ] );
  
          final String assembly = getURLAsString( new File( directory, FS_ASSEMBLY_XML ) );
          final String config = getURLAsString( new File( directory, FS_CONFIG_XML ) );
          final String environment = getURLAsString( envFile );
          final FileDigest[] fileDigests = (FileDigest[])digests.toArray( new FileDigest[ 0 ] );
          final long timestamp = System.currentTimeMillis();
  
          return new Installation( file, directory, workDir,
                                   config, assembly, environment,
                                   classPath, fileDigests, timestamp );
      }
  
      /**
       * Expand the specified Zip file.
       *
       * @param zipFile the zip file
       * @param directory the directory where to extract non-jar,
       *        non-classes files
       * @param workDir the directory to extract classes/jar files
       * @param classpath the list to add classpath entries to
       * @param digests the list to add file digests to
       * @param url the url of deployment (for error reporting purposes)
       * @throws InstallationException if an error occurs extracting files
       */
      private void expandZipFile( final ZipFile zipFile,
                                  final File directory,
                                  final File workDir,
                                  final ArrayList classpath,
                                  final ArrayList digests,
                                  final URL url )
          throws InstallationException
      {
          final Enumeration entries = zipFile.entries();
          while( entries.hasMoreElements() )
          {
              final ZipEntry entry = (ZipEntry)entries.nextElement();
              final String name = fixName( entry.getName() );
  
              if( name.startsWith( META_INF ) )
              {
                  continue;
              }
  
              if( handleDirs( entry, name, directory ) )
              {
                  continue;
              }
  
              if( handleClasses( zipFile,
                                 entry,
                                 name,
                                 workDir,
                                 classpath ) )
              {
                  continue;
              }
  
              if( handleJars( zipFile, entry, name, workDir, classpath ) )
              {
                  continue;
              }
  
              //Expand the file if necesasry and issue a warning
              //if there is a file in the way
              final File destination = new File( directory, name );
              handleFile( zipFile, entry, destination, digests, url );
          }
      }
  
      /**
       * Handle the extraction of normal resources
       * from zip file/
       */
      private void handleFile( final ZipFile zipFile,
                               final ZipEntry entry,
                               final File destination,
                               final ArrayList digests,
                               final URL url )
          throws InstallationException
      {
          if( !destination.exists() )
          {
              expandFile( zipFile, entry, destination );
              calculateDigest( entry, destination, digests );
          }
          else
          {
              final String message =
                  REZ.getString( "file-in-the-way",
                                 url,
                                 entry.getName(),
                                 destination );
              getLogger().warn( message );
          }
      }
  
      /**
       * Handle extraction of jars.
       *
       * @param zipFile the zipFIle to exrtact from
       * @param entry the entry to extract
       * @param name the normalized name of entry
       * @param workDir the working directory to extract to
       * @param jars the classpath list
       * @return true if handled, false otherwise
       */
      private boolean handleJars( final ZipFile zipFile,
                                  final ZipEntry entry,
                                  final String name,
                                  final File workDir,
                                  final ArrayList jars )
          throws InstallationException
      {
          if( name.startsWith( LIB ) &&
              name.endsWith( ".jar" ) &&
              LIB.length() == name.lastIndexOf( "/" ) )
          {
              final File jar = new File( workDir, name );
              jars.add( getURLAsString( jar ) );
  
              final File file = new File( workDir, name );
              expandFile( zipFile, entry, file );
              return true;
          }
          else
          {
              return false;
          }
      }
  
      /**
       * Handle extraction of jars.
       *
       * @param zipFile the zipFIle to exrtact from
       * @param entry the entry to extract
       * @param name the normalized name of entry
       * @param workDir the working directory to extract to
       * @param jars the classpath list
       * @return true if handled, false otherwise
       */
      private boolean handleClasses( final ZipFile zipFile,
                                     final ZipEntry entry,
                                     final String name,
                                     final File workDir,
                                     final ArrayList jars )
          throws InstallationException
      {
          if( name.startsWith( CLASSES ) )
          {
              final File classDir = new File( workDir, FS_CLASSES );
              if( !classDir.exists() )
              {
                  jars.add( getURLAsString( classDir ) );
                  final File file = new File( workDir, name );
                  expandFile( zipFile, entry, file );
              }
              return true;
          }
          else
          {
              return false;
          }
      }
  
      /**
       * Handle expansion of dirs in the zipfile.
       *
       * @param entry the current ZipEntry
       * @param name the name of entry
       * @param directory the base directory extraacting to
       * @return true if handled, false otherwise
       */
      private boolean handleDirs( final ZipEntry entry,
                                  final String name,
                                  final File directory )
      {
          if( entry.isDirectory() )
          {
              if( !name.startsWith( SAR_INF ) )
              {
                  final File newDir =
                      new File( directory, name );
                  newDir.mkdirs();
              }
              return true;
          }
          else
          {
              return false;
          }
      }
  
      /**
       * Create working directory inside baseWorkDir
       * for specified file.
       *
       * @param baseWorkDir the base workDir for all apps
       * @param file the file representing app
       * @return the working directory for app
       */
      private File getRelativeWorkDir( final File baseWorkDir,
                                       final File file )
      {
          final String filename =
              file.getName() + "-" + System.currentTimeMillis();
          return new File( baseWorkDir, filename );
      }
  
      /**
       * Fix the specified name so that it does not start
       * with a "/" character.
       *
       * @param name the name to fix
       * @return the name stripped of initial "/" if necessary
       */
      private String fixName( final String name )
      {
          if( name.startsWith( "/" ) )
          {
              return name.substring( 1 );
          }
          else
          {
              return name;
          }
      }
  
      /**
       * Create an Installation from a Sar in deprecated format.
       *
       * @param file the file designating the sar
       * @param zipFile the ZipFile object for sar
       * @return the Installaiton
       */
      private Installation installDeprecated( final URL url,
                                              final File file,
                                              final ZipFile zipFile )
          throws InstallationException
      {
          final ArrayList digests = new ArrayList();
          final File directory = getDestinationFor( file );
  
          final Enumeration entries = zipFile.entries();
          while( entries.hasMoreElements() )
          {
              final ZipEntry entry = (ZipEntry)entries.nextElement();
              if( entry.isDirectory() ) continue;
  
              final String name = fixName( entry.getName() );
  
              //Expand the file if not in META-INF directory
              if( !name.startsWith( META_INF ) )
              {
                  final File destination = new File( directory, name );
                  if( !destination.exists() )
                  {
                      expandFile( zipFile, entry, destination );
                      calculateDigest( entry, destination, digests );
                  }
                  else
                  {
                      final String message = REZ.getString( "file-in-the-way", url, name, directory );
                      getLogger().warn( message );
                  }
              }
          }
  
          final String[] classPath = getClassPathForDirectory( directory );
          final String config = getURLAsString( new File( directory, OLD_CONFIG_XML ) );
          final String assembly = getURLAsString( new File( directory, OLD_ASSEMBLY_XML ) );
          final String server = getURLAsString( new File( directory, OLD_SERVER_XML ) );
          final FileDigest[] fileDigests = (FileDigest[])digests.toArray( new FileDigest[ 0 ] );
          final long timestamp = System.currentTimeMillis();
  
          return new Installation( file, directory, directory,
                                   config, assembly, server,
                                   classPath, fileDigests, timestamp );
      }
  
      /**
       * Create an Installation from a Sar in deprecated format.
       *
       * @param directory the directory containing extracted .sar
       * @return the Installaiton
       */
      private Installation installDeprecated( final File directory )
          throws InstallationException
      {
          final String[] classPath = getClassPathForDirectory( directory );
          final String config = getURLAsString( new File( directory, OLD_CONFIG_XML ) );
          final String assembly = getURLAsString( new File( directory, OLD_ASSEMBLY_XML ) );
          final String server = getURLAsString( new File( directory, OLD_SERVER_XML ) );
          final long timestamp = System.currentTimeMillis();
  
          return new Installation( directory, directory, directory,
                                   config, assembly, server,
                                   classPath, null, timestamp );
      }
  
      /**
       * Get File object for URL.
       * Currently it assumes that URL is a file URL but in the
       * future it will allow downloading of remote URLs thus enabling
       * a deploy from anywhere functionality.
       *
       * @param url the url of deployment
       * @return the File for deployment
       * @throws InstallationException if an error occurs
       */
      private File getFileFor( final URL url )
          throws InstallationException
      {
          if( !url.getProtocol().equals( "file" ) )
          {
              final String message = REZ.getString( "install-nonlocal", url );
              throw new InstallationException( message );
          }
  
          File file = new File( url.getFile() );
          file = file.getAbsoluteFile();
  
          if( !file.exists() )
          {
              final String message = REZ.getString( "install-nourl", file );
              throw new InstallationException( message );
          }
  
          return file;
      }
  
      /**
       * Calculate digest for specific entry.
       *
       * @param entry the entry
       * @param file the extracted file
       * @param digests the list of digests already
       *        calculated
       */
      private void calculateDigest( final ZipEntry entry,
                                    final File file,
                                    final ArrayList digests )
      {
          final long checksum = entry.getCrc();
          digests.add( new FileDigest( file, checksum ) );
      }
  
      /**
       * Expand a single zipEntry to a file.
       */
      private void expandFile( final ZipFile zipFile,
                               final ZipEntry entry,
                               final File file )
          throws InstallationException
      {
          InputStream input = null;
          OutputStream output = null;
  
          try
          {
              file.getParentFile().mkdirs();
              output = new FileOutputStream( file );
              input = zipFile.getInputStream( entry );
              IOUtil.copy( input, output );
          }
          catch( final IOException ioe )
          {
              final String message =
                  REZ.getString( "failed-to-expand",
                                 entry.getName(),
                                 file,
                                 ioe.getMessage() );
              throw new InstallationException( message, ioe );
          }
          finally
          {
              IOUtil.shutdownStream( input );
              IOUtil.shutdownStream( output );
          }
      }
  
      /**
       * Get destination that .sar should be expanded to.
       *
       * @param file the file object representing .sar archive
       * @return the destination to expand archive
       */
      private File getDestinationFor( final File file )
      {
          final String base =
              FileUtil.removeExtension( FileUtil.removePath( file.getName() ) );
  
          return ( new File( file.getParentFile(), base ) ).getAbsoluteFile();
      }
  
      /**
       * Get Classpath for application.
       *
       * @return the list of URLs in ClassPath
       */
      private String[] getClassPathForDirectory( final File directory )
      {
          final File blockDir = new File( directory, "blocks" );
          final File libDir = new File( directory, "lib" );
  
          final ArrayList urls = new ArrayList();
          getURLsAsStrings( urls, blockDir, new String[]{".bar"} );
          getURLsAsStrings( urls, libDir, new String[]{".jar", ".zip"} );
          return (String[])urls.toArray( new String[ 0 ] );
      }
  
      /**
       * Add all matching files in directory to url list.
       *
       * @param urls the url list
       * @param directory the directory to scan
       * @param extensions the list of extensions to match
       */
      private void getURLsAsStrings( final ArrayList urls, final File directory, final String[] extensions )
      {
          final ExtensionFileFilter filter = new ExtensionFileFilter( extensions );
          final File[] files = directory.listFiles( filter );
          if( null == files ) return;
          for( int i = 0; i < files.length; i++ )
          {
              urls.add( getURLAsString( files[ i ] ) );
          }
      }
  
      /**
       * Utility method to extract URL from file in safe manner.
       *
       * @param file the file
       * @return the URL representation of file
       */
      private String getURLAsString( final File file )
      {
          try
          {
              return file.toURL().toExternalForm();
          }
          catch( final MalformedURLException mue )
          {
              return null;
              //should never occur
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/installer/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  installing-sar=Installing Sar located at {0}.
  
  install-nonlocal=Specified directory is located remotely at {0}. Uncompressed remote deployment not supported.
  install-nourl=Could not find Sar at {0}.
  uninstall-failure=Failed to cleanup directory {0}
  require-sar=Current implementation requires that Server Applications be stored in .sar files. Installation specified by {0} does not represent a .sar file.
  deprecated-sar-format=Application {0} uses a deprecated packaging format.
  file-in-the-way=The file {1} can not be extracted from the Sar "{0}" into directory {2} because there is a file in the way.
  bad-zip-file=Specified url {0} does not refer to a valid Sar (or Zip) archive.
  failed-to-expand=Failed to expand entry named "{0}" to file {1}. (Reason: {2})
  mixed-sar=Sar file contains elements of new style deployment format (with SAR-INF/) and old style deployment format. This is invalid. Only one style is supported at a time.
  invalid-sar=Sar does not contain elements required to construct a valid application (such as configuration data and code archives).
  skip-removal=Skip removal for modified file {0}.
  checksum-failure=Failed to compute checksum for {0} file.
  deprecated-environment-xml=The .sar at "{0}" uses a deprecated format to refer to environment information. Environment information should not be stored in "SAR-INF/server.xml" but in "SAR-INF/environment.xml".
  
  nodelete-workdir.error=Error deleting Work Directory "{0}". (Reason: {1})
  
  
  1.1                  jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/deployer/installer/package.html
  
  Index: package.html
  ===================================================================
  <html><body>
  Installation management resources.
  </body></html>
  
  
  
  1.60      +4 -3      jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/embeddor/DefaultEmbeddor.java
  
  Index: DefaultEmbeddor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/embeddor/DefaultEmbeddor.java,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -r1.59 -r1.60
  --- DefaultEmbeddor.java	10 May 2002 12:05:58 -0000	1.59
  +++ DefaultEmbeddor.java	11 May 2002 02:05:13 -0000	1.60
  @@ -404,20 +404,20 @@
        */
       private synchronized void createComponents()
       {
  -        Object object;
           try
           {
               for( int i = 0; i < m_entrys.length; i++ )
               {
                   final String className = m_entrys[ i ].getClassName();
                   final Class clazz = Class.forName( className );
  -                object = createObject( className, clazz );
  +                final Object object = createObject( className, clazz );
                   m_entrys[ i ].setObject( object );
               }
           }
           catch( Exception e )
           {
  -            final String message = REZ.getString( "embeddor.error.createComponents.failed" );
  +            final String message =
  +                REZ.getString( "embeddor.error.createComponents.failed" );
               getLogger().fatalError( message, e );
           }
       }
  @@ -516,6 +516,7 @@
       private void shutdownComponents()
           throws Exception
       {
  +        //for( int i = m_entrys.length - 1; i >= 0; i-- )
           for( int i = 0; i < m_entrys.length; i++ )
           {
               final Object object = m_entrys[ i ].getObject();
  
  
  
  1.12      +2 -0      jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/interfaces/ClassLoaderManager.java
  
  Index: ClassLoaderManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/interfaces/ClassLoaderManager.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- ClassLoaderManager.java	10 May 2002 14:06:01 -0000	1.11
  +++ ClassLoaderManager.java	11 May 2002 02:05:13 -0000	1.12
  @@ -30,6 +30,7 @@
        * @param source the source of application. (usually the name of the .sar file
        *               or else the same as baseDirectory)
        * @param baseDirectory the base directory of application
  +     * @param workDirectory the work directory of application
        * @param classPath the list of URLs in applications deployment
        * @return the ClassLoader created
        * @throws Exception if an error occurs
  @@ -37,6 +38,7 @@
       ClassLoader createClassLoader( Configuration environment,
                                      File source,
                                      File baseDirectory,
  +                                   File workDirectory,
                                      String[] classPath )
           throws Exception;
   }
  
  
  
  1.6       +17 -3     jakarta-avalon-phoenix/src/xdocs/environment-xml-specification.xml
  
  Index: environment-xml-specification.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/xdocs/environment-xml-specification.xml,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- environment-xml-specification.xml	2 Apr 2002 18:56:21 -0000	1.5
  +++ environment-xml-specification.xml	11 May 2002 02:05:13 -0000	1.6
  @@ -39,9 +39,16 @@
   
       <policy>
         <keystore name="foo-keystore"
  -                location="file:${app.home}${/}conf${/}keystore"
  +                location="sar:/conf/keystore"
                   type="JKS" />
   
  +      <grant code-base="file:${app.home}${/}some-dir${/}*"
  +              key-store="foo-keystore" >
  +        <permission class="java.io.FilePermission"
  +                    target="${/}tmp${/}*"
  +                    action="read,write" />
  +      </grant>
  +
         <grant signed-by="Bob"
                code-base="file:${app.home}${/}SAR-INF${/}lib${/}*"
                key-store="foo-keystore" >
  @@ -55,7 +62,7 @@
   
         </source>
         <p>
  -        The format of the policy section should be self evident if the assembler
  +        The format of the policy section should be largely self evident if the assembler
           has experience with standard policy files. It should be noted that if no
           policy section is given then the Server Application runs at full permissions.
           The evaluation of properties occurs in a similar manner to standard
  @@ -63,6 +70,13 @@
           will be evaluated. These include; <code>app.home</code> and <code>app.name</code>.
         </p>
         <p>
  +        One special thing to not is that the user can use URLs of the form,
  +        "sar:/SAR-INF/lib/*". This will apply the permissions to the jars
  +        contained in the .SAR file. Note that these urls must start with
  +        "sar:/" and must use the "/" character as file separator, regardless
  +        of current operating system.
  +      </p>
  +      <p>
           The logs section can currently have two types of elements; <em>log-target</em>s
           which represent destinations for logging and <em>category</em>s. There must be a
           log-target with the name "default". Categories are hierarchial in nature, have a
  @@ -104,7 +118,7 @@
     <footer>
       <legal>
         Copyright (c) @year@ The Jakarta Apache Project All rights reserved.
  -      $Revision: 1.5 $ $Date: 2002/04/02 18:56:21 $
  +      $Revision: 1.6 $ $Date: 2002/05/11 02:05:13 $
       </legal>
     </footer>
   </document>
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: cvs commit: jakarta-avalon-phoenix/src/xdocs environment-xml-specification.xml

Posted by Peter Donald <pe...@apache.org>.
Hi,

Just in case you missed it I recently committed the following.

On Sat, 11 May 2002 12:05, donaldp@apache.org wrote:
> donaldp     02/05/10 19:05:13
>
>   Modified:    src/java/org/apache/avalon/phoenix/components/classloader
>                         DefaultClassLoaderManager.java DefaultPolicy.java
>                src/java/org/apache/avalon/phoenix/components/deployer
>                         DefaultDeployer.java Resources.properties
>                src/java/org/apache/avalon/phoenix/components/embeddor
>                         DefaultEmbeddor.java
>                src/java/org/apache/avalon/phoenix/interfaces
>                         ClassLoaderManager.java
>                src/xdocs environment-xml-specification.xml
>   Added:      
> src/java/org/apache/avalon/phoenix/components/deployer/installer
> FileDigest.java Installation.java
>                         InstallationException.java Installer.java
>                         Resources.properties package.html
>   Removed:     src/java/org/apache/avalon/phoenix/tools/installer
>                         FileDigest.java Installation.java
>                         InstallationException.java Installer.java
>                         Resources.properties package.html
>   Log:
>   Reworked Installation, deployment etc so that the Jars and classes in an
>   application are extracted to a temporary "work" directory (defaults to
> sub-dir $PHOENIX_HOME/work).
>
>   Each deployment uses a unique directory thus there will not be any
> problem with the JVM caching the Classes loaded from a URL. Each work
> directory is deleted at undeployment.
>
>   Unfortunately people who were relying on the <policy/> section may need
> to change some options in certain circumstances. If previously you were
> assigning permissions to jars based on the jars being included in the
> applicaiton directory via something like
>
>   <grant code-base="file:${app.home}${/}SAR-INF${/}lib${/}*">
>
>   This will need to be updated to use URLs of the form
>
>   <grant code-base="sar:/SAR-INF/lib/*">

-- 
Cheers,

Peter Donald


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>