KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > loading > LoaderRepositoryFactory


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mx.loading;
23
24 import java.io.Serializable JavaDoc;
25 import java.lang.reflect.Constructor JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import javax.management.InstanceNotFoundException JavaDoc;
28 import javax.management.JMException JavaDoc;
29 import javax.management.MalformedObjectNameException JavaDoc;
30 import javax.management.MBeanServer JavaDoc;
31 import javax.management.ObjectInstance JavaDoc;
32 import javax.management.ObjectName JavaDoc;
33
34 import org.jboss.logging.Logger;
35 import org.jboss.mx.server.ServerConstants;
36
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.NodeList JavaDoc;
39 import org.w3c.dom.Node JavaDoc;
40
41 /** A factory for LoaderRepository instances. This is used to obtain repository
42  * instances for scoped class loading.
43  *
44  * @author <a HREF="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
45  * @author Scott.Stark@jboss.org
46  * @version $Revision: 37459 $
47  */

48 public class LoaderRepositoryFactory
49 {
50    /** The JMX name of the parent LoaderRepository */
51    public static ObjectName JavaDoc DEFAULT_LOADER_REPOSITORY;
52    private static Logger log = Logger.getLogger(LoaderRepositoryFactory.class);
53    /** A HashMap<ObjectName, Integer> for the active references to LoaderRepositorys */
54    private static HashMap JavaDoc referenceCountMap = new HashMap JavaDoc();
55
56    static
57    {
58       try
59       {
60          // Initialize the default LoaderRepository name
61
DEFAULT_LOADER_REPOSITORY = new ObjectName JavaDoc(ServerConstants.DEFAULT_LOADER_NAME);
62       }
63       catch(Exception JavaDoc e)
64       {
65          log.error("Failed to init DEFAULT_LOADER_REPOSITORY name", e);
66       }
67    }
68
69    /** A class that represents the configuration of the a LoaderRepository.
70     * This defines the JMX ObjectName, the LoaderRepository implementation
71     * class, the repository config parser and a string representation of
72     * the repository config.
73     */

74    public static class LoaderRepositoryConfig implements Serializable JavaDoc
75    {
76       static final long serialVersionUID = 4226952985429700362L;
77       
78       /** The ObjectName of the loader repository for this deployment */
79       public ObjectName JavaDoc repositoryName = DEFAULT_LOADER_REPOSITORY;
80       public String JavaDoc repositoryClassName;
81       public String JavaDoc configParserClassName;
82       public String JavaDoc repositoryConfig;
83
84       public String JavaDoc toString()
85       {
86          StringBuffer JavaDoc tmp = new StringBuffer JavaDoc("LoaderRepositoryConfig(");
87          tmp.append("repositoryName: ");
88          tmp.append(repositoryName);
89          tmp.append(", repositoryClassName: ");
90          tmp.append(repositoryClassName);
91          tmp.append(", configParserClassName: ");
92          tmp.append(configParserClassName);
93          tmp.append(", repositoryConfig: ");
94          tmp.append(repositoryConfig);
95          tmp.append(")");
96          return tmp.toString();
97       }
98    }
99
100    /** The interface representing a LoaderRepository configuration parser. A
101     * LoaderRepositoryConfigParser knows how to take a string representation of
102     * a config and map that onto a LoaderRepository implementation.
103     */

104    static public interface LoaderRepositoryConfigParser
105    {
106       public void configure(LoaderRepository repository, String JavaDoc config)
107          throws Exception JavaDoc;
108    }
109
110    /** Given a loader-repository element fragment like:
111       <loader-repository loaderRepositoryClass='...'>
112          jboss.test.cts:loader=cts-cmp2v2.ear
113          <loader-repository-config configParserClass='...'>
114             ...
115          </loader-repository-config>
116       </loader-repository>
117     create a LoaderRepositoryConfig representation.
118     @param config the xml loader-repository element
119     @return a LoaderRepositoryConfig representation of the config
120     */

121    public static LoaderRepositoryConfig parseRepositoryConfig(Element JavaDoc config)
122       throws MalformedObjectNameException JavaDoc
123    {
124       LoaderRepositoryConfig repositoryConfig = new LoaderRepositoryConfig();
125       repositoryConfig.repositoryClassName = config.getAttribute("loaderRepositoryClass");
126       if( repositoryConfig.repositoryClassName.length() == 0 )
127          repositoryConfig.repositoryClassName = ServerConstants.DEFAULT_SCOPED_REPOSITORY_CLASS;
128
129       // Get the object name of the repository
130
NodeList JavaDoc children = config.getChildNodes();
131       int count = children.getLength();
132       if( count > 0 )
133       {
134          for(int n = 0; n < count; n ++)
135          {
136             Node JavaDoc node = children.item(n);
137             int type = node.getNodeType();
138             // Get the ObjectName string
139
if( type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE )
140             {
141                String JavaDoc objectName = node.getNodeValue().trim();
142                repositoryConfig.repositoryName = new ObjectName JavaDoc(objectName);
143                break;
144             }
145          }
146
147          // Next load any repository config
148
children = config.getElementsByTagName("loader-repository-config");
149          count = children.getLength();
150          if( count > 0 )
151          {
152             Element JavaDoc loaderRepositoryConfig = (Element JavaDoc) children.item(0);
153             children = loaderRepositoryConfig.getChildNodes();
154             count = children.getLength();
155             repositoryConfig.configParserClassName = loaderRepositoryConfig.getAttribute("configParserClass");
156             if( repositoryConfig.configParserClassName.length() == 0 )
157                repositoryConfig.configParserClassName = ServerConstants.DEFAULT_SCOPED_REPOSITORY_PARSER_CLASS;
158             StringBuffer JavaDoc configData = new StringBuffer JavaDoc();
159             for(int n = 0; n < count; n ++)
160             {
161                Node JavaDoc node = children.item(n);
162                int type = node.getNodeType();
163                if( type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE )
164                {
165                   configData.append(node.getNodeValue());
166                }
167             }
168             repositoryConfig.repositoryConfig = configData.toString().trim();
169          }
170       }
171       return repositoryConfig;
172    }
173
174    /** Create a LoaderRepository instance of type repositoryClassName and
175     * register it under repositoryName if there is not already an instance
176     * registered.
177     *
178     * @param server the MBeanServer to register with
179     * @param repositoryClassName the class which implements LoaderRepository
180     * @param repositoryName the JMX name to register under
181     * @throws JMException thrown on any failure to create or register the repository
182     */

183    public static synchronized void createLoaderRepository(MBeanServer JavaDoc server,
184       String JavaDoc repositoryClassName,
185       ObjectName JavaDoc repositoryName) throws JMException JavaDoc
186    {
187       LoaderRepositoryConfig config = new LoaderRepositoryConfig();
188       config.repositoryClassName = repositoryClassName;
189       config.repositoryName = repositoryName;
190       createLoaderRepository(server, config);
191    }
192    /** Create and configure a LoaderRepository instance using the given config
193     * if there is not already an instance registered.
194     *
195     * @param server the MBeanServer to register with
196     * @param config the configuration information which will be used to create
197     * register and configure the LoaderRepository instance.
198     * @throws JMException thrown on any failure to create or register the repository
199     */

200    public static synchronized void createLoaderRepository(MBeanServer JavaDoc server,
201       LoaderRepositoryConfig config) throws JMException JavaDoc
202    {
203       if( config == null )
204          config = new LoaderRepositoryConfig();
205       String JavaDoc repositoryClassName = config.repositoryClassName;
206       ObjectName JavaDoc repositoryName = config.repositoryName;
207
208       try
209       {
210          ObjectInstance JavaDoc oi = server.getObjectInstance(repositoryName);
211          if ( (repositoryClassName != null) &&
212                !oi.getClassName().equals(repositoryClassName) )
213          {
214             throw new JMException JavaDoc("Inconsistent LoaderRepository class specification in repository: " + repositoryName);
215          } // end of if ()
216
}
217       catch (InstanceNotFoundException JavaDoc e)
218       {
219          //we are the first, make the repository.
220
if( repositoryClassName == null )
221             repositoryClassName = ServerConstants.DEFAULT_SCOPED_REPOSITORY_CLASS;
222
223          ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
224          LoaderRepository repository = null;
225          try
226          {
227             // Create the repository loader
228
Class JavaDoc repositoryClass = loader.loadClass(repositoryClassName);
229             Class JavaDoc[] ctorSig = {MBeanServer JavaDoc.class, ObjectName JavaDoc.class};
230             Constructor JavaDoc ctor = repositoryClass.getConstructor(ctorSig);
231             Object JavaDoc[] args = {server, DEFAULT_LOADER_REPOSITORY};
232             repository = (LoaderRepository) ctor.newInstance(args);
233             server.registerMBean(repository, repositoryName);
234          }
235          catch(Exception JavaDoc e2)
236          {
237             log.debug("Failed to create loader repository: ", e2);
238             throw new JMException JavaDoc("Failed to create loader repository:" + e2);
239          }
240
241          try
242          {
243             // Configure the repository
244
if( config.configParserClassName != null && config.repositoryConfig != null )
245             {
246                Class JavaDoc parserClass = loader.loadClass(config.configParserClassName);
247                LoaderRepositoryConfigParser parser = (LoaderRepositoryConfigParser)
248                   parserClass.newInstance();
249                parser.configure(repository, config.repositoryConfig);
250             }
251          }
252          catch(Exception JavaDoc e2)
253          {
254             log.debug("Failed to configure loader repository: ", e2);
255             throw new JMException JavaDoc("Failed to configure loader repository: "+e2);
256          }
257       } // end of try-catch
258

259       Integer JavaDoc activeCount = (Integer JavaDoc) referenceCountMap.get(repositoryName);
260       if( activeCount == null )
261          activeCount = new Integer JavaDoc(1);
262       else
263          activeCount = new Integer JavaDoc(activeCount.intValue() + 1);
264       referenceCountMap.put(repositoryName, activeCount);
265    }
266
267    public static synchronized void destroyLoaderRepository(MBeanServer JavaDoc server,
268       ObjectName JavaDoc repositoryName)
269    {
270       if( repositoryName.equals(DEFAULT_LOADER_REPOSITORY) == false )
271       {
272          try
273          {
274             Integer JavaDoc activeCount = (Integer JavaDoc) referenceCountMap.get(repositoryName);
275             if( activeCount != null )
276             {
277                if( activeCount.intValue() == 1 )
278                {
279                   server.unregisterMBean(repositoryName);
280                   referenceCountMap.remove(repositoryName);
281                   log.debug("Unregistered repository: "+repositoryName);
282                }
283                else
284                {
285                   activeCount = new Integer JavaDoc(activeCount.intValue() - 1);
286                   referenceCountMap.put(repositoryName, activeCount);
287                }
288             }
289          }
290          catch(Exception JavaDoc e)
291          {
292             log.warn("Failed to unregister ear loader repository", e);
293          }
294       }
295    }
296
297    private LoaderRepositoryFactory()
298    {
299    }
300 }// LoaderRepositoryFactory
301
Popular Tags