You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by da...@apache.org on 2003/01/08 13:31:05 UTC

cvs commit: jakarta-james/src/java/org/apache/james/transport JamesSpoolManager.java MailetLoader.java MatchLoader.java

danny       2003/01/08 04:31:05

  Modified:    src/java/org/apache/james/transport JamesSpoolManager.java
                        MailetLoader.java MatchLoader.java
  Log:
  Mailet Classloader changes. First efforts..
  Mailet and matcher classes and their dependancies can now be loaded
  from ~/apps/james/SAR-INF/classes
  and jars in ~/apps/james/SAR-INF/lib/
  
  Revision  Changes    Path
  1.24      +92 -143   jakarta-james/src/java/org/apache/james/transport/JamesSpoolManager.java
  
  Index: JamesSpoolManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/src/java/org/apache/james/transport/JamesSpoolManager.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- JamesSpoolManager.java	7 Jan 2003 11:57:25 -0000	1.23
  +++ JamesSpoolManager.java	8 Jan 2003 12:31:05 -0000	1.24
  @@ -6,12 +6,9 @@
    * the LICENSE file.
    */
   package org.apache.james.transport;
  -
   import java.util.HashMap;
   import java.util.Iterator;
  -
   import javax.mail.MessagingException;
  -
   import org.apache.avalon.cornerstone.services.threads.ThreadManager;
   import org.apache.avalon.excalibur.thread.ThreadPool;
   import org.apache.avalon.framework.activity.Disposable;
  @@ -24,6 +21,9 @@
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.james.core.MailImpl;
   import org.apache.james.services.MailStore;
  @@ -33,7 +33,6 @@
   import org.apache.mailet.MailetException;
   import org.apache.mailet.Matcher;
   import org.apache.mailet.SpoolRepository;
  -
   /**
    * Manages the mail spool.  This class is responsible for retrieving
    * messages from the spool, directing messages to the appropriate
  @@ -47,57 +46,45 @@
    */
   public class JamesSpoolManager
       extends AbstractLogEnabled
  -    implements Composable, Configurable, Initializable,
  -               Runnable, Disposable, Component {
  -
  +    implements Composable, Configurable, Initializable, Runnable, Disposable, Component, Contextualizable {
  +    private Context context;
       /**
        * Whether 'deep debugging' is turned on.
        */
       private final static boolean DEEP_DEBUG = false;
  -
       /**
        * System component manager
        */
       private DefaultComponentManager compMgr;
  -
       /**
        * The configuration object used by this spool manager.
        */
       private Configuration conf;
  -
       private SpoolRepository spool;
  -
       private MailetContext mailetContext;
  -
       /**
        * The map of processor names to processors
        */
       private HashMap processors;
  -
       /**
        * The number of threads used to move mail through the spool.
        */
       private int numThreads;
  -
       /**
        * The ThreadPool containing the spool threads.
        */
       private ThreadPool workerPool;
  -
       /**
        * The ThreadManager from which the thread pool is obtained.
        */
       private ThreadManager threadManager;
  -
       /**
        * @see org.apache.avalon.framework.component.Composable#compose(ComponentManager)
        */
  -    public void compose(ComponentManager comp)
  -        throws ComponentException {
  -        threadManager = (ThreadManager)comp.lookup( ThreadManager.ROLE );
  +    public void compose(ComponentManager comp) throws ComponentException {
  +        threadManager = (ThreadManager) comp.lookup(ThreadManager.ROLE);
           compMgr = new DefaultComponentManager(comp);
       }
  -
       /**
        * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
        */
  @@ -105,55 +92,48 @@
           this.conf = conf;
           numThreads = conf.getChild("threads").getValueAsInteger(1);
       }
  -
       /**
        * @see org.apache.avalon.framework.activity.Initializable#initialize()
        */
       public void initialize() throws Exception {
  -
           getLogger().info("JamesSpoolManager init...");
  -        workerPool = threadManager.getThreadPool( "default" );
  -        MailStore mailstore
  -            = (MailStore) compMgr.lookup("org.apache.james.services.MailStore");
  +        workerPool = threadManager.getThreadPool("default");
  +        MailStore mailstore = (MailStore) compMgr.lookup("org.apache.james.services.MailStore");
           spool = mailstore.getInboundSpool();
  -        if (null == spool)
  -        {
  -            String exceptionMessage = "The mailstore's inbound spool is null.  The mailstore is misconfigured";
  +        if (null == spool) {
  +            String exceptionMessage =
  +                "The mailstore's inbound spool is null.  The mailstore is misconfigured";
               if (getLogger().isErrorEnabled()) {
  -                getLogger().error( exceptionMessage );
  +                getLogger().error(exceptionMessage);
               }
               throw new ConfigurationException(exceptionMessage);
           }
           if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
               getLogger().debug("Got spool");
           }
  -
  -        mailetContext
  -            = (MailetContext) compMgr.lookup("org.apache.mailet.MailetContext");
  +        mailetContext = (MailetContext) compMgr.lookup("org.apache.mailet.MailetContext");
           MailetLoader mailetLoader = new MailetLoader();
           MatchLoader matchLoader = new MatchLoader();
           try {
  +            mailetLoader.setLogger(getLogger());
  +            matchLoader.setLogger(getLogger());
  +            mailetLoader.contextualize(context);
  +            matchLoader.contextualize(context);
               mailetLoader.configure(conf.getChild("mailetpackages"));
               matchLoader.configure(conf.getChild("matcherpackages"));
               compMgr.put(Resources.MAILET_LOADER, mailetLoader);
               compMgr.put(Resources.MATCH_LOADER, matchLoader);
           } catch (ConfigurationException ce) {
  -            final String message =
  -                "Unable to configure mailet/matcher Loaders: "
  -                + ce.getMessage();
  -
  +            final String message = "Unable to configure mailet/matcher Loaders: " + ce.getMessage();
               if (getLogger().isErrorEnabled()) {
  -                getLogger().error( message, ce );
  +                getLogger().error(message, ce);
               }
  -            throw new RuntimeException( message );
  +            throw new RuntimeException(message);
           }
  -
           //A processor is a Collection of
           processors = new HashMap();
  -
  -        final Configuration[] processorConfs = conf.getChildren( "processor" );
  -        for ( int i = 0; i < processorConfs.length; i++ )
  -        {
  +        final Configuration[] processorConfs = conf.getChildren("processor");
  +        for (int i = 0; i < processorConfs.length; i++) {
               Configuration processorConf = processorConfs[i];
               String processorName = processorConf.getAttribute("name");
               try {
  @@ -162,51 +142,41 @@
                   processor.setSpool(spool);
                   processor.initialize();
                   processors.put(processorName, processor);
  -
                   // If this is the root processor, add the PostmasterAlias
                   //  mailet silently to the top
                   if (processorName.equals("root")) {
  -                    Matcher matcher = matchLoader.getMatcher("All",
  -                                                             mailetContext);
  -                    Mailet mailet = mailetLoader.getMailet("PostmasterAlias",
  -                                                           mailetContext, null);
  +                    Matcher matcher = matchLoader.getMatcher("All", mailetContext);
  +                    Mailet mailet = mailetLoader.getMailet("PostmasterAlias", mailetContext, null);
                       processor.add(matcher, mailet);
                   }
  -
  -                final Configuration[] mailetConfs
  -                    = processorConf.getChildren( "mailet" );
  +                final Configuration[] mailetConfs = processorConf.getChildren("mailet");
                   // Loop through the mailet configuration, load
                   // all of the matcher and mailets, and add
                   // them to the processor.
  -                for ( int j = 0; j < mailetConfs.length; j++ )
  -                {
  +                for (int j = 0; j < mailetConfs.length; j++) {
                       Configuration c = mailetConfs[j];
                       String mailetClassName = c.getAttribute("class");
                       String matcherName = c.getAttribute("match");
                       Mailet mailet = null;
                       Matcher matcher = null;
                       try {
  -                        matcher = matchLoader.getMatcher(matcherName,
  -                                                         mailetContext);
  +                        matcher = matchLoader.getMatcher(matcherName, mailetContext);
                           //The matcher itself should log that it's been inited.
                           if (getLogger().isInfoEnabled()) {
                               StringBuffer infoBuffer =
  -                                new StringBuffer(64)
  -                                        .append("Matcher ")
  -                                        .append(matcherName)
  -                                        .append(" instantiated.");
  +                                new StringBuffer(64).append("Matcher ").append(matcherName).append(
  +                                    " instantiated.");
                               getLogger().info(infoBuffer.toString());
                           }
                       } catch (MessagingException ex) {
                           // **** Do better job printing out exception
                           if (getLogger().isErrorEnabled()) {
                               StringBuffer errorBuffer =
  -                                new StringBuffer(256)
  -                                        .append("Unable to init matcher ")
  -                                        .append(matcherName)
  -                                        .append(": ")
  -                                        .append(ex.toString());
  -                            getLogger().error( errorBuffer.toString(), ex );
  +                                new StringBuffer(256).append("Unable to init matcher ").append(
  +                                    matcherName).append(
  +                                    ": ").append(
  +                                    ex.toString());
  +                            getLogger().error(errorBuffer.toString(), ex);
                           }
                           System.err.println("Unable to init matcher " + matcherName);
                           System.err.println("Check spool manager logs for more details.");
  @@ -215,26 +185,23 @@
                           throw ex;
                       }
                       try {
  -                        mailet = mailetLoader.getMailet(mailetClassName,
  -                                                        mailetContext, c);
  +                        mailet = mailetLoader.getMailet(mailetClassName, mailetContext, c);
                           if (getLogger().isInfoEnabled()) {
                               StringBuffer infoBuffer =
  -                                new StringBuffer(64)
  -                                        .append("Mailet ")
  -                                        .append(mailetClassName)
  -                                        .append(" instantiated.");
  +                                new StringBuffer(64).append("Mailet ").append(
  +                                    mailetClassName).append(
  +                                    " instantiated.");
                               getLogger().info(infoBuffer.toString());
                           }
                       } catch (MessagingException ex) {
                           // **** Do better job printing out exception
                           if (getLogger().isErrorEnabled()) {
                               StringBuffer errorBuffer =
  -                                new StringBuffer(256)
  -                                        .append("Unable to init mailet ")
  -                                        .append(mailetClassName)
  -                                        .append(": ")
  -                                        .append(ex.toString());
  -                            getLogger().error( errorBuffer.toString(), ex );
  +                                new StringBuffer(256).append("Unable to init mailet ").append(
  +                                    mailetClassName).append(
  +                                    ": ").append(
  +                                    ex.toString());
  +                            getLogger().error(errorBuffer.toString(), ex);
                           }
                           System.err.println("Unable to init mailet " + mailetClassName);
                           System.err.println("Check spool manager logs for more details.");
  @@ -245,61 +212,49 @@
                       //Add this pair to the processor
                       processor.add(matcher, mailet);
                   }
  -
                   // Close the processor matcher/mailet lists.
                   //
                   // Please note that this is critical to the proper operation
                   // of the LinearProcessor code.  The processor will not be
                   // able to service mails until this call is made.
                   processor.closeProcessorLists();
  -
                   if (getLogger().isInfoEnabled()) {
                       StringBuffer infoBuffer =
  -                        new StringBuffer(64)
  -                                .append("Processor ")
  -                                .append(processorName)
  -                                .append(" instantiated.");
  +                        new StringBuffer(64).append("Processor ").append(processorName).append(
  +                            " instantiated.");
                       getLogger().info(infoBuffer.toString());
                   }
               } catch (Exception ex) {
                   if (getLogger().isErrorEnabled()) {
                       StringBuffer errorBuffer =
  -                       new StringBuffer(256)
  -                               .append("Unable to init processor ")
  -                               .append(processorName)
  -                               .append(": ")
  -                               .append(ex.toString());
  -                    getLogger().error( errorBuffer.toString(), ex );
  +                        new StringBuffer(256).append("Unable to init processor ").append(
  +                            processorName).append(
  +                            ": ").append(
  +                            ex.toString());
  +                    getLogger().error(errorBuffer.toString(), ex);
                   }
                   throw ex;
               }
           }
           if (getLogger().isInfoEnabled()) {
               StringBuffer infoBuffer =
  -                new StringBuffer(64)
  -                    .append("Spooler Manager uses ")
  -                    .append(numThreads)
  -                    .append(" Thread(s)");
  +                new StringBuffer(64).append("Spooler Manager uses ").append(numThreads).append(
  +                    " Thread(s)");
               getLogger().info(infoBuffer.toString());
           }
  -        for ( int i = 0 ; i < numThreads ; i++ )
  +        for (int i = 0; i < numThreads; i++)
               workerPool.execute(this);
       }
  -
       /**
        * This routinely checks the message spool for messages, and processes
        * them as necessary
        */
       public void run() {
  -
  -        if (getLogger().isInfoEnabled())
  -        {
  -            getLogger().info("Run JamesSpoolManager: "
  -                             + Thread.currentThread().getName());
  +        if (getLogger().isInfoEnabled()) {
  +            getLogger().info("Run JamesSpoolManager: " + Thread.currentThread().getName());
               getLogger().info("Spool=" + spool.getClass().getName());
           }
  -
  -        while(true) {
  +        while (true) {
               try {
                   String key = spool.accept();
                   Mail mail = spool.retrieve(key);
  @@ -311,29 +266,26 @@
                   }
                   if (getLogger().isDebugEnabled()) {
                       StringBuffer debugBuffer =
  -                        new StringBuffer(64)
  -                                .append("==== Begin processing mail ")
  -                                .append(mail.getName())
  -                                .append("====");
  +                        new StringBuffer(64).append("==== Begin processing mail ").append(
  +                            mail.getName()).append(
  +                            "====");
                       getLogger().debug(debugBuffer.toString());
                   }
                   process(mail);
                   // Only remove an email from the spool is processing is
                   // complete, or if it has no recipients
  -                if ((Mail.GHOST.equals(mail.getState())) ||
  -                    (mail.getRecipients() == null) ||
  -                    (mail.getRecipients().size() == 0)) {
  +                if ((Mail.GHOST.equals(mail.getState()))
  +                    || (mail.getRecipients() == null)
  +                    || (mail.getRecipients().size() == 0)) {
                       spool.remove(key);
                       if (getLogger().isDebugEnabled()) {
                           StringBuffer debugBuffer =
  -                            new StringBuffer(64)
  -                                    .append("==== Removed from spool mail ")
  -                                    .append(mail.getName())
  -                                    .append("====");
  +                            new StringBuffer(64).append("==== Removed from spool mail ").append(
  +                                mail.getName()).append(
  +                                "====");
                           getLogger().debug(debugBuffer.toString());
                       }
  -                }
  -                else {
  +                } else {
                       // spool.remove() has a side-effect!  It unlocks the
                       // message so that other threads can work on it!  If
                       // we don't remove it, we must unlock it!
  @@ -343,13 +295,11 @@
               } catch (Exception e) {
                   e.printStackTrace();
                   if (getLogger().isErrorEnabled()) {
  -                    getLogger().error("Exception in JamesSpoolManager.run "
  -                                      + e.getMessage());
  +                    getLogger().error("Exception in JamesSpoolManager.run " + e.getMessage());
                   }
               }
           }
       }
  -
       /**
        * Process this mail message by the appropriate processor as designated
        * in the state of the Mail object.
  @@ -364,8 +314,7 @@
                   return;
               }
               try {
  -                LinearProcessor processor
  -                    = (LinearProcessor)processors.get(processorName);
  +                LinearProcessor processor = (LinearProcessor) processors.get(processorName);
                   if (processor == null) {
                       StringBuffer exceptionMessageBuffer =
                           new StringBuffer(128)
  @@ -380,21 +329,17 @@
                   StringBuffer logMessageBuffer = null;
                   if (getLogger().isDebugEnabled()) {
                       logMessageBuffer =
  -                        new StringBuffer(64)
  -                                .append("Processing ")
  -                                .append(mail.getName())
  -                                .append(" through ")
  -                                .append(processorName);
  +                        new StringBuffer(64).append("Processing ").append(mail.getName()).append(
  +                            " through ").append(
  +                            processorName);
                       getLogger().debug(logMessageBuffer.toString());
                   }
                   processor.service(mail);
                   if (getLogger().isDebugEnabled()) {
                       logMessageBuffer =
  -                        new StringBuffer(128)
  -                                .append("Processed")
  -                                .append(mail.getName())
  -                                .append(" through ")
  -                                .append(processorName);
  +                        new StringBuffer(128).append("Processed").append(mail.getName()).append(
  +                            " through ").append(
  +                            processorName);
                       getLogger().debug(logMessageBuffer.toString());
                       getLogger().debug("Result was " + mail.getState());
                   }
  @@ -402,11 +347,10 @@
               } catch (Exception e) {
                   // This is a strange error situation that shouldn't ordinarily
                   // happen
  -                StringBuffer exceptionBuffer = 
  -                    new StringBuffer(64)
  -                            .append("Exception in processor <")
  -                            .append(processorName)
  -                            .append(">");
  +                StringBuffer exceptionBuffer =
  +                    new StringBuffer(64).append("Exception in processor <").append(
  +                        processorName).append(
  +                        ">");
                   getLogger().error(exceptionBuffer.toString(), e);
                   if (processorName.equals(Mail.ERROR)) {
                       // We got an error on the error processor...
  @@ -422,16 +366,15 @@
               if (getLogger().isErrorEnabled()) {
                   StringBuffer logMessageBuffer =
                       new StringBuffer(128)
  -                            .append("An error occurred processing ")
  -                            .append(mail.getName())
  -                            .append(" through ")
  -                            .append(processorName);
  +                        .append("An error occurred processing ")
  +                        .append(mail.getName())
  +                        .append(" through ")
  +                        .append(processorName);
                   getLogger().error(logMessageBuffer.toString());
                   getLogger().error("Result was " + mail.getState());
               }
           }
       }
  -
       /**
        * The dispose operation is called at the end of a components lifecycle.
        * Instances of this class use this method to release and destroy any
  @@ -446,13 +389,19 @@
           getLogger().info("JamesSpoolManager dispose...");
           Iterator it = processors.keySet().iterator();
           while (it.hasNext()) {
  -            String processorName = (String)it.next();
  +            String processorName = (String) it.next();
               if (getLogger().isDebugEnabled()) {
                   getLogger().debug("Processor " + processorName);
               }
  -            LinearProcessor processor = (LinearProcessor)processors.get(processorName);
  +            LinearProcessor processor = (LinearProcessor) processors.get(processorName);
               processor.dispose();
               processors.remove(processor);
           }
  +    }
  +    /**
  +     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context)
  +     */
  +    public void contextualize(Context context) {
  +        this.context = context;
       }
   }
  
  
  
  1.8       +66 -24    jakarta-james/src/java/org/apache/james/transport/MailetLoader.java
  
  Index: MailetLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/src/java/org/apache/james/transport/MailetLoader.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- MailetLoader.java	2 Oct 2002 06:12:03 -0000	1.7
  +++ MailetLoader.java	8 Jan 2003 12:31:05 -0000	1.8
  @@ -6,41 +6,48 @@
    * the LICENSE file.
    */
   package org.apache.james.transport;
  -
  +import java.io.File;
  +import java.io.IOException;
  +import java.net.MalformedURLException;
  +import java.net.URL;
  +import java.net.URLClassLoader;
  +import java.util.Vector;
  +import javax.mail.MessagingException;
   import org.apache.avalon.framework.component.Component;
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
  +import org.apache.avalon.framework.logger.Logger;
  +import org.apache.avalon.phoenix.BlockContext;
   import org.apache.james.core.MailetConfigImpl;
   import org.apache.mailet.Mailet;
   import org.apache.mailet.MailetContext;
   import org.apache.mailet.MailetException;
  -
  -import javax.mail.MessagingException;
  -import java.util.Vector;
  -
   /**
    * Loads Mailets for use inside James.
    *
    * @author Serge Knystautas <se...@lokitech.com>
    * @author Federico Barbieri <sc...@systemy.it>
    */
  -public class MailetLoader implements Component, Configurable {
  -
  +public class MailetLoader implements Component, Configurable, Contextualizable {
  +    private ClassLoader theClassLoader = null;
  +    private String baseDirectory = null;
  +    private Logger logger;
       /**
        * The list of packages that may contain Mailets
        */
       private Vector mailetPackages;
  -
       /**
        * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
        */
       public void configure(Configuration conf) throws ConfigurationException {
           mailetPackages = new Vector();
           mailetPackages.addElement("");
  -        final Configuration[] pkgConfs = conf.getChildren( "mailetpackage" );
  -        for ( int i = 0; i < pkgConfs.length; i++ )
  -        {
  +        final Configuration[] pkgConfs = conf.getChildren("mailetpackage");
  +        for (int i = 0; i < pkgConfs.length; i++) {
               Configuration c = pkgConfs[i];
               String packageName = c.getValue();
               if (!packageName.endsWith(".")) {
  @@ -48,8 +55,34 @@
               }
               mailetPackages.addElement(packageName);
           }
  +        File base = new File(baseDirectory + "/SAR-INF/lib");
  +        String[] flist = base.list();
  +        Vector jarlist = new Vector();
  +        URL[] classPath = null;
  +        try {
  +            jarlist.add(new URL("file://" + baseDirectory + "/SAR-INF/classes/"));
  +        } catch (MalformedURLException e) {
  +            logger.error(
  +                "cant add "
  +                    + "file://"
  +                    + baseDirectory
  +                    + "/SAR-INF/classes/ to mailet classloader");
  +        }
  +        if (flist != null) {
  +            for (int i = 0; i < flist.length; i++) {
  +                try {
  +                    if (flist[i].indexOf("jar") == flist[i].length() - 3) {
  +                        jarlist.add(new URL("file://" + flist[i]));
  +                        logger.debug("added " + flist[i] + " to Mailet Classloader");
  +                    }
  +                } catch (MalformedURLException e) {
  +                    logger.error("cant add " + "file://" + flist[i] + " to mailet classloader");
  +                }
  +            }
  +        }
  +        classPath = (URL[]) jarlist.toArray(new URL[jarlist.size()]);
  +        theClassLoader = new URLClassLoader(classPath, this.getClass().getClassLoader());
       }
  -
       /**
        * Get a new Mailet with the specified name acting
        * in the specified context.
  @@ -63,18 +96,15 @@
           throws MessagingException {
           try {
               for (int i = 0; i < mailetPackages.size(); i++) {
  -                String className = (String)mailetPackages.elementAt(i) + mailetName;
  -                ClassLoader theClassLoader = null;
  +                String className = (String) mailetPackages.elementAt(i) + mailetName;
                   try {
                       MailetConfigImpl configImpl = new MailetConfigImpl();
                       configImpl.setMailetName(mailetName);
                       configImpl.setConfiguration(configuration);
                       configImpl.setMailetContext(context);
  -
                       if (theClassLoader == null) {
                           theClassLoader = this.getClass().getClassLoader();
                       }
  -
                       Mailet mailet = (Mailet) theClassLoader.loadClass(className).newInstance();
                       mailet.init(configImpl);
                       return mailet;
  @@ -84,20 +114,32 @@
               }
               StringBuffer exceptionBuffer =
                   new StringBuffer(128)
  -                        .append("Requested mailet not found: ")
  -                        .append(mailetName)
  -                        .append(".  looked in ")
  -                        .append(mailetPackages.toString());
  +                    .append("Requested mailet not found: ")
  +                    .append(mailetName)
  +                    .append(".  looked in ")
  +                    .append(mailetPackages.toString());
               throw new ClassNotFoundException(exceptionBuffer.toString());
           } catch (MessagingException me) {
               throw me;
           } catch (Exception e) {
               StringBuffer exceptionBuffer =
  -                new StringBuffer(128)
  -                        .append("Could not load mailet (")
  -                        .append(mailetName)
  -                        .append(")");
  +                new StringBuffer(128).append("Could not load mailet (").append(mailetName).append(
  +                    ")");
               throw new MailetException(exceptionBuffer.toString(), e);
           }
  +    }
  +    /**
  +         * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context)
  +         */
  +    public void contextualize(final Context context) throws ContextException {
  +        try {
  +            baseDirectory = ((BlockContext) context).getBaseDirectory().getCanonicalPath();
  +        } catch (IOException e) {
  +            logger.error("cant get base directory for mailet loader");
  +            throw new ContextException("cant contextualise loader " + e.getMessage(), e);
  +        }
  +    }
  +    public void setLogger(Logger logger) {
  +        this.logger = logger;
       }
   }
  
  
  
  1.9       +68 -29    jakarta-james/src/java/org/apache/james/transport/MatchLoader.java
  
  Index: MatchLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/src/java/org/apache/james/transport/MatchLoader.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- MatchLoader.java	2 Oct 2002 06:12:03 -0000	1.8
  +++ MatchLoader.java	8 Jan 2003 12:31:05 -0000	1.9
  @@ -6,41 +6,49 @@
    * the LICENSE file.
    */
   package org.apache.james.transport;
  -
  +import java.io.File;
  +import java.io.IOException;
  +import java.net.MalformedURLException;
  +import java.net.URL;
  +import java.net.URLClassLoader;
  +import java.util.Vector;
  +import javax.mail.MessagingException;
   import org.apache.avalon.framework.component.Component;
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
  +import org.apache.avalon.framework.logger.AbstractLogEnabled;
  +import org.apache.avalon.framework.logger.Logger;
  +import org.apache.avalon.phoenix.BlockContext;
   import org.apache.james.core.MatcherConfigImpl;
   import org.apache.mailet.MailetContext;
   import org.apache.mailet.MailetException;
   import org.apache.mailet.Matcher;
  -
  -import javax.mail.MessagingException;
  -import java.util.Vector;
  -
   /**
    * Loads Matchers for use inside James.
    *
    * @author Serge Knystautas <se...@lokitech.com>
    * @author Federico Barbieri <sc...@systemy.it>
    */
  -public class MatchLoader implements Component, Configurable {
  -
  +public class MatchLoader implements Component, Configurable, Contextualizable {
       /**
        * The list of packages that may contain Mailets
        */
       private Vector matcherPackages;
  -
  +    private ClassLoader theClassLoader = null;
  +    private String baseDirectory = null;
  +    private Logger logger;
       /**
        * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
        */
       public void configure(Configuration conf) throws ConfigurationException {
           matcherPackages = new Vector();
           matcherPackages.addElement("");
  -        final Configuration[] pkgConfs = conf.getChildren( "matcherpackage" );
  -        for ( int i = 0; i < pkgConfs.length; i++ )
  -        {
  +        final Configuration[] pkgConfs = conf.getChildren("matcherpackage");
  +        for (int i = 0; i < pkgConfs.length; i++) {
               Configuration c = pkgConfs[i];
               String packageName = c.getValue();
               if (!packageName.endsWith(".")) {
  @@ -48,8 +56,34 @@
               }
               matcherPackages.addElement(packageName);
           }
  +        File base = new File(baseDirectory + "/SAR-INF/lib");
  +        String[] flist = base.list();
  +        Vector jarlist = new Vector();
  +        URL[] classPath = null;
  +        try {
  +            jarlist.add(new URL("file://" + baseDirectory + "/SAR-INF/lib/classes/"));
  +        } catch (MalformedURLException e) {
  +            logger.error(
  +                "cant add "
  +                    + "file://"
  +                    + baseDirectory
  +                    + "/SAR-INF/classes/ to matcher classloader");
  +        }
  +        if (flist != null) {
  +            for (int i = 0; i < flist.length; i++) {
  +                try {
  +                    if (flist[i].indexOf("jar") == flist[i].length() - 3) {
  +                        jarlist.add(new URL("file://" + flist[i]));
  +                        logger.debug("added " + flist[i] + " to Matcher Classloader");
  +                    }
  +                } catch (MalformedURLException e) {
  +                    logger.error("cant add " + "file://" + flist[i] + " to matcher classloader");
  +                }
  +            }
  +        }
  +        classPath = (URL[]) jarlist.toArray(new URL[jarlist.size()]);
  +        theClassLoader = new URLClassLoader(classPath, this.getClass().getClassLoader());
       }
  -
       /**
        * Get a new Matcher with the specified name acting
        * in the specified context.
  @@ -59,8 +93,7 @@
        *                matcher
        * @throws MessagingException if an error occurs
        */
  -    public Matcher getMatcher(String matchName, MailetContext context)
  -        throws MessagingException {
  +    public Matcher getMatcher(String matchName, MailetContext context) throws MessagingException {
           try {
               String condition = (String) null;
               int i = matchName.indexOf('=');
  @@ -68,19 +101,13 @@
                   condition = matchName.substring(i + 1);
                   matchName = matchName.substring(0, i);
               }
  -            ClassLoader theClassLoader = null;
               for (i = 0; i < matcherPackages.size(); i++) {
  -                String className = (String)matcherPackages.elementAt(i) + matchName;
  +                String className = (String) matcherPackages.elementAt(i) + matchName;
                   try {
                       MatcherConfigImpl configImpl = new MatcherConfigImpl();
                       configImpl.setMatcherName(matchName);
                       configImpl.setCondition(condition);
                       configImpl.setMailetContext(context);
  -
  -                    if (theClassLoader == null) {
  -                        theClassLoader = this.getClass().getClassLoader();
  -                    }
  -
                       Matcher matcher = (Matcher) theClassLoader.loadClass(className).newInstance();
                       matcher.init(configImpl);
                       return matcher;
  @@ -90,20 +117,32 @@
               }
               StringBuffer exceptionBuffer =
                   new StringBuffer(128)
  -                        .append("Requested matcher not found: ")
  -                        .append(matchName)
  -                        .append(".  looked in ")
  -                        .append(matcherPackages.toString());
  +                    .append("Requested matcher not found: ")
  +                    .append(matchName)
  +                    .append(".  looked in ")
  +                    .append(matcherPackages.toString());
               throw new ClassNotFoundException(exceptionBuffer.toString());
           } catch (MessagingException me) {
               throw me;
           } catch (Exception e) {
               StringBuffer exceptionBuffer =
  -                new StringBuffer(128)
  -                        .append("Could not load matcher (")
  -                        .append(matchName)
  -                        .append(")");
  +                new StringBuffer(128).append("Could not load matcher (").append(matchName).append(
  +                    ")");
               throw new MailetException(exceptionBuffer.toString(), e);
           }
  +    }
  +    /**
  +     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context)
  +     */
  +    public void contextualize(final Context context) throws ContextException {
  +        try {
  +            baseDirectory = ((BlockContext) context).getBaseDirectory().getCanonicalPath();
  +        } catch (IOException e) {
  +            logger.error("cant get base directory for matcher loader");
  +            throw new ContextException("cant contextualise loader " + e.getMessage(), e);
  +        }
  +    }
  +    public void setLogger(Logger logger) {
  +        this.logger = logger;
       }
   }
  
  
  

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


RE: cvs commit: jakarta-james/src/java/org/apache/james/transport JamesSpoolManager.java MailetLoader.java MatchLoader.java

Posted by Danny Angus <da...@apache.org>.
Hi,

This commit marks the first step towards the mailet deployment/classloading
goals set out on the wiki.
Unfortunately formatting changes got caught up with the code changes, sorry.

It doesn't achieve much more than prove that I have my head round the
lifecycle of mailets and matchers. I've run some tests on it, and it
_appears_ to work as advertised and without breaking anything.

In a nutshell you can now put mailets and matchers and their dependancies
into ~/apps/james/SAR-INF/classes or in jars in ~/apps/james/SAR-INF/lib.

I don't know if it would be a desirable addition to 2.2 or not, from the POV
of stability, but I know its something folks've wanted for quite a while.

Next step is to seperate the mailet classloader from James to hide non API
classes not explicitly installed for mailets. I know I'll have to make an
exception for the current db-access mailets until we do something to make
them compliant.

d.

> danny       2003/01/08 04:31:05
>
>   Modified:    src/java/org/apache/james/transport JamesSpoolManager.java
>                         MailetLoader.java MatchLoader.java
>   Log:
>   Mailet Classloader changes. First efforts..
>   Mailet and matcher classes and their dependancies can now be loaded
>   from ~/apps/james/SAR-INF/classes
>   and jars in ~/apps/james/SAR-INF/lib/


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