View Javadoc

1   /*
2    * $Id: SimpleRegistryBootstrap.java 12370 2008-07-17 13:11:17Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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  package org.mule.config.bootstrap;
11  
12  import org.mule.api.MuleContext;
13  import org.mule.api.MuleException;
14  import org.mule.api.context.MuleContextAware;
15  import org.mule.api.lifecycle.Initialisable;
16  import org.mule.api.lifecycle.InitialisationException;
17  import org.mule.api.registry.ObjectProcessor;
18  import org.mule.api.registry.Registry;
19  import org.mule.api.transformer.DiscoverableTransformer;
20  import org.mule.api.transformer.Transformer;
21  import org.mule.api.transformer.TransformerException;
22  import org.mule.api.util.StreamCloser;
23  import org.mule.config.i18n.CoreMessages;
24  import org.mule.util.ClassUtils;
25  import org.mule.util.PropertiesUtils;
26  
27  import java.lang.reflect.InvocationTargetException;
28  import java.net.URL;
29  import java.util.Enumeration;
30  import java.util.Iterator;
31  import java.util.Map;
32  import java.util.Properties;
33  
34  /**
35   * This object will load objects defined in a file called <code>registry-bootstrap.properties</code> into the local registry.
36   * This allows modules and transports to make certain objects available by default.  The most common use case is for a
37   * module or transport to load stateless transformers into the registry.
38   * For this file to be located it must be present in the modules META-INF directory under
39   * <code>META-INF/services/org/mule/config/</code>
40   * <p/>
41   * The format of this file is a simple key / value pair. i.e.
42   * <code>
43   * myobject=org.foo.MyObject
44   * </code>
45   * <p/>
46   * Will register an instance of MyObject with a key of 'myobject'. If you don't care about the object name and want to
47   * ensure that the ojbect gets a unique name you can use -
48   * <code>
49   * object.1=org.foo.MyObject
50   * object.2=org.bar.MyObject
51   * </code>
52   * <p/>
53   * or
54   * <code>
55   * myFoo=org.foo.MyObject
56   * myBar=org.bar.MyObject
57   * </code>
58   * <p/>
59   * <p/>
60   * Loading transformers has a slightly different notation since you can define the 'returnClass' and 'name'of
61   * the transformer as parameters i.e.
62   * <p/>
63   * <code>
64   * transformer.1=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=byte[]
65   * transformer.2=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=java.lang.String, name=JMSMessageToString
66   * transformer.3=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=java.util.Hashtable)
67   * </code>
68   * <p/>
69   * Note that the key used for transformers must be 'transformer.x' where 'x' is a sequential number.  The transformer name will be
70   * automatically generated as JMSMessageToXXX where XXX is the return class name i.e. JMSMessageToString unless a 'name'
71   * parameter is specified. If no 'returnClass' is specified the defualt in the transformer will be used.
72   * <p/>
73   * Note that all objects defined have to have a default constructor. They can implement injection interfaces such as
74   * {@link org.mule.api.context.MuleContextAware} and lifecylce interfaces such as {@link org.mule.api.lifecycle.Initialisable}.
75   */
76  public class SimpleRegistryBootstrap implements Initialisable, MuleContextAware
77  {
78      public static final String SERVICE_PATH = "META-INF/services/org/mule/config/";
79  
80      public static final String REGISTRY_PROPERTIES = "registry-bootstrap.properties";
81  
82      public String TRANSFORMER_PREFIX = "transformer.";
83      public String OBJECT_PREFIX = "object.";
84  
85  
86      protected MuleContext context;
87  
88      /** {@inheritDoc} */
89      public void setMuleContext(MuleContext context)
90      {
91          this.context = context;
92      }
93  
94      /** {@inheritDoc} */
95      public void initialise() throws InitialisationException
96      {
97          Enumeration e = ClassUtils.getResources(SERVICE_PATH + REGISTRY_PROPERTIES, getClass());
98          while (e.hasMoreElements())
99          {
100             try
101             {
102                 URL url = (URL) e.nextElement();
103                 Properties p = new Properties();
104                 p.load(url.openStream());
105                 process(p);
106             }
107             catch (Exception e1)
108             {
109                 throw new InitialisationException(e1, this);
110             }
111         }
112     }
113 
114     protected void process(Properties props) throws NoSuchMethodException, IllegalAccessException, MuleException, InvocationTargetException, ClassNotFoundException, InstantiationException
115     {
116         registerTransformers(props, context.getRegistry());
117         registerUnnamedObjects(props, context.getRegistry());
118         //this must be called last as it clears the properties map
119         registerObjects(props, context.getRegistry());
120 
121     }
122 
123     private void registerTransformers(Properties props, Registry registry) throws MuleException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException, ClassNotFoundException
124     {
125         int i = 1;
126         String transString = props.getProperty(TRANSFORMER_PREFIX + i);
127         String name = null;
128         String returnClassString = null;
129 
130         while (transString != null)
131         {
132             Class returnClass = null;
133             int x = transString.indexOf(",");
134             if (x > -1)
135             {
136                 Properties p = PropertiesUtils.getPropertiesFromString(transString.substring(i + 1), ',');
137                 name = p.getProperty("name", null);
138                 returnClassString = p.getProperty("returnClass", null);
139             }
140 
141             if (returnClassString != null)
142             {
143                 if (returnClassString.equals("byte[]"))
144                 {
145                     returnClass = byte[].class;
146                 }
147                 else
148                 {
149                     returnClass = ClassUtils.loadClass(returnClassString, getClass());
150                 }
151             }
152             String transClass = (x == -1 ? transString : transString.substring(0, x));
153             Transformer trans = (Transformer) ClassUtils.instanciateClass(transClass, ClassUtils.NO_ARGS);
154             if (!(trans instanceof DiscoverableTransformer))
155             {
156                 throw new TransformerException(CoreMessages.transformerNotImplementDiscoverable(trans));
157             }
158             if (returnClass != null)
159             {
160                 trans.setReturnClass(returnClass);
161             }
162             if (name != null)
163             {
164                 trans.setName(name);
165             }
166             else
167             {
168                 //This will generate a default name for the transformer
169                 name = trans.getName();
170                 //We then prefix the name to ensure there is less chance of conflict if the user registers
171                 // the transformer with the same name
172                 trans.setName("_" + name);
173             }
174             registry.registerTransformer(trans);
175             props.remove(TRANSFORMER_PREFIX + i++);
176             name = null;
177             returnClass = null;
178             transString = props.getProperty(TRANSFORMER_PREFIX + i);
179         }
180     }
181 
182     private void registerObjects(Properties props, Registry registry) throws MuleException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException, ClassNotFoundException
183     {
184         //Note that caling the other register methods first will have removed any processed entries
185         for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();)
186         {
187             Map.Entry entry = (Map.Entry) iterator.next();
188             Object object = ClassUtils.instanciateClass(entry.getValue().toString(), ClassUtils.NO_ARGS);
189             String key = entry.getKey().toString();
190             Class meta = Object.class;
191             if(object instanceof ObjectProcessor)
192             {
193                 meta = ObjectProcessor.class;
194             }
195             registry.registerObject(key, object, meta);
196         }
197         props.clear();
198     }
199 
200     private void registerUnnamedObjects(Properties props, Registry registry) throws MuleException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException, ClassNotFoundException
201     {
202         int i = 1;
203         String objectString = props.getProperty(OBJECT_PREFIX + i);
204         while (objectString != null)
205         {
206 
207             Object o = ClassUtils.instanciateClass(objectString, ClassUtils.NO_ARGS);
208             Class meta = Object.class;
209             if(o instanceof ObjectProcessor)
210             {
211                 meta = ObjectProcessor.class;
212             }
213             else if(o instanceof StreamCloser)
214             {
215                 meta = StreamCloser.class;
216             }
217             registry.registerObject(OBJECT_PREFIX + i + "#" + o.hashCode(), o, meta);
218             props.remove(OBJECT_PREFIX + i++);
219             objectString = props.getProperty(OBJECT_PREFIX + i);
220         }
221     }
222 }