View Javadoc

1   /*
2    * $Id: ThreadPoolFactory.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.config.pool;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleRuntimeException;
15  import org.mule.api.config.ThreadingProfile;
16  import org.mule.api.context.MuleContextAware;
17  import org.mule.config.i18n.MessageFactory;
18  import org.mule.util.ClassUtils;
19  
20  import java.util.Iterator;
21  
22  import javax.imageio.spi.ServiceRegistry;
23  
24  import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  /**
30   * Uses a standard JDK's
31   * <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">SPI discovery</a>
32   * mechanism to locate implementations.
33   */
34  public abstract class ThreadPoolFactory implements MuleContextAware
35  {
36      // keep it private, subclasses will have their own loggers, thus avoiding contention on this static one
37      private static final Log logger = LogFactory.getLog(ThreadPoolFactory.class);
38  
39      private static final String PREFERRED_CONFIG_CLASSNAME = "com.mulesoft.mule.config.Preferred";
40      private static boolean extensionsAvailable = ClassUtils.isClassOnPath(PREFERRED_CONFIG_CLASSNAME, ThreadPoolFactory.class);
41  
42      protected MuleContext muleContext;
43  
44      /**
45       * @return a discovered
46       */
47      public static ThreadPoolFactory newInstance()
48      {
49          Class preferredMarker = null;
50          if (extensionsAvailable)
51          {
52              try
53              {
54                  preferredMarker = ClassUtils.loadClass(PREFERRED_CONFIG_CLASSNAME, ThreadPoolFactory.class);
55              }
56              catch (ClassNotFoundException e)
57              {
58                  extensionsAvailable = false;
59                  if (logger.isDebugEnabled())
60                  {
61                      logger.debug("Failed to load EE extensions", e);
62                  }
63              }
64  
65          }
66  
67          /*
68             There's a public (at last!) SPI mechanism in Java 6, java.util.ServiceLoader, but
69             it's hidden in earlier versions.
70  
71             The javax.imageio.spi.ServiceRegistry, while not belonging here at first look, is
72             perfectly functional. Underneath, it wraps the sun.misc.Service class, which does the
73             lookup. The latter has been available since Java 1.3 and standardized internally at Sun.
74             Also, Sun, Bea JRockit and IBM JDK all have it readily available for use, so it's safe to
75             rely on.
76          */
77          final Iterator<ThreadPoolFactory> it = ServiceRegistry.lookupProviders(ThreadPoolFactory.class);
78          ThreadPoolFactory candidate = null;
79          while (it.hasNext())
80          {
81              ThreadPoolFactory threadPoolFactory = it.next();
82              // if found a preferred one, grab it and stop
83              if (extensionsAvailable && preferredMarker.isAssignableFrom(threadPoolFactory.getClass()))
84              {
85                  return threadPoolFactory;
86              }
87              else
88              {
89                  // only keep around the first non-preferred one we found,
90                  // in case non-preferred was found before preferred
91                  if (candidate == null)
92                  {
93                      candidate = threadPoolFactory;
94                  }
95              }
96          }
97  
98          if (candidate != null)
99          {
100             return candidate;
101         }
102 
103         throw new MuleRuntimeException(MessageFactory.createStaticMessage(
104                 "Couldn't find config via SPI mechanism. Corrupted Mule core jar?"
105         ));
106     }
107 
108     public void setMuleContext(MuleContext context)
109     {
110         this.muleContext = context;
111     }
112 
113     public abstract ThreadPoolExecutor createPool(String name, ThreadingProfile tp);
114 }