001: /*
002: * $Id: SimpleRegistryBootstrap.java 11231 2008-03-06 21:17:37Z rossmason $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010: package org.mule.config.bootstrap;
011:
012: import org.mule.api.MuleContext;
013: import org.mule.api.MuleException;
014: import org.mule.api.context.MuleContextAware;
015: import org.mule.api.lifecycle.Initialisable;
016: import org.mule.api.lifecycle.InitialisationException;
017: import org.mule.api.lifecycle.LifecycleTransitionResult;
018: import org.mule.api.registry.ObjectProcessor;
019: import org.mule.api.registry.Registry;
020: import org.mule.api.transformer.DiscoverableTransformer;
021: import org.mule.api.transformer.Transformer;
022: import org.mule.api.transformer.TransformerException;
023: import org.mule.config.i18n.CoreMessages;
024: import org.mule.util.ClassUtils;
025: import org.mule.util.PropertiesUtils;
026:
027: import java.lang.reflect.InvocationTargetException;
028: import java.net.URL;
029: import java.util.Enumeration;
030: import java.util.Iterator;
031: import java.util.Map;
032: import java.util.Properties;
033:
034: /**
035: * This object will load objects defined in a file called <code>registry-bootstrap.properties</code> into the local registry.
036: * This allows modules and transports to make certain objects available by default. The most common use case is for a
037: * module or transport to load stateless transformers into the registry.
038: * For this file to be located it must be present in the modules META-INF directory under
039: * <code>META-INF/services/org/mule/config/</code>
040: * <p/>
041: * The format of this file is a simple key / value pair. i.e.
042: * <code>
043: * myobject=org.foo.MyObject
044: * </code>
045: * <p/>
046: * Will register an instance of MyObject with a key of 'myobject'. If you don't care about the object name and want to
047: * ensure that the ojbect gets a unique name you can use -
048: * <code>
049: * object.1=org.foo.MyObject
050: * object.2=org.bar.MyObject
051: * </code>
052: * <p/>
053: * or
054: * <code>
055: * myFoo=org.foo.MyObject
056: * myBar=org.bar.MyObject
057: * </code>
058: * <p/>
059: * <p/>
060: * Loading transformers has a slightly different notation since you can define the 'returnClass' and 'name'of
061: * the transformer as parameters i.e.
062: * <p/>
063: * <code>
064: * transformer.1=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=byte[]
065: * transformer.2=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=java.lang.String, name=JMSMessageToString
066: * transformer.3=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=java.util.Hashtable)
067: * </code>
068: * <p/>
069: * Note that the key used for transformers must be 'transformer.x' where 'x' is a sequential number. The transformer name will be
070: * automatically generated as JMSMessageToXXX where XXX is the return class name i.e. JMSMessageToString unless a 'name'
071: * parameter is specified. If no 'returnClass' is specified the defualt in the transformer will be used.
072: * <p/>
073: * Note that all objects defined have to have a default constructor. They can implement injection interfaces such as
074: * {@link org.mule.api.context.MuleContextAware} and lifecylce interfaces such as {@link org.mule.api.lifecycle.Initialisable}.
075: */
076: public class SimpleRegistryBootstrap implements Initialisable,
077: MuleContextAware {
078: public static final String SERVICE_PATH = "META-INF/services/org/mule/config/";
079:
080: public static final String REGISTRY_PROPERTIES = "registry-bootstrap.properties";
081:
082: public String TRANSFORMER_PREFIX = "transformer.";
083: public String OBJECT_PREFIX = "object.";
084:
085: protected MuleContext context;
086:
087: /** {@inheritDoc} */
088: public void setMuleContext(MuleContext context) {
089: this .context = context;
090: }
091:
092: /** {@inheritDoc} */
093: public LifecycleTransitionResult initialise()
094: throws InitialisationException {
095: Enumeration e = ClassUtils.getResources(SERVICE_PATH
096: + REGISTRY_PROPERTIES, getClass());
097: while (e.hasMoreElements()) {
098: try {
099: URL url = (URL) e.nextElement();
100: Properties p = new Properties();
101: p.load(url.openStream());
102: process(p);
103: } catch (Exception e1) {
104: throw new InitialisationException(e1, this );
105: }
106: }
107: return LifecycleTransitionResult.OK;
108: }
109:
110: protected void process(Properties props)
111: throws NoSuchMethodException, IllegalAccessException,
112: MuleException, InvocationTargetException,
113: ClassNotFoundException, InstantiationException {
114: registerTransformers(props, context.getRegistry());
115: registerUnnamedObjects(props, context.getRegistry());
116: //this must be called last as it clears the properties map
117: registerObjects(props, context.getRegistry());
118:
119: }
120:
121: private void registerTransformers(Properties props,
122: Registry registry) throws MuleException,
123: IllegalAccessException, NoSuchMethodException,
124: InvocationTargetException, InstantiationException,
125: ClassNotFoundException {
126: int i = 1;
127: String transString = props.getProperty(TRANSFORMER_PREFIX + i);
128: String name = null;
129: String returnClassString = null;
130:
131: while (transString != null) {
132: Class returnClass = null;
133: int x = transString.indexOf(",");
134: if (x > -1) {
135: Properties p = PropertiesUtils.getPropertiesFromString(
136: transString.substring(i + 1), ',');
137: name = p.getProperty("name", null);
138: returnClassString = p.getProperty("returnClass", null);
139: }
140:
141: if (returnClassString != null) {
142: if (returnClassString.equals("byte[]")) {
143: returnClass = byte[].class;
144: } else {
145: returnClass = ClassUtils.loadClass(
146: returnClassString, getClass());
147: }
148: }
149: String transClass = (x == -1 ? transString : transString
150: .substring(0, x));
151: Transformer trans = (Transformer) ClassUtils
152: .instanciateClass(transClass, ClassUtils.NO_ARGS);
153: if (!(trans instanceof DiscoverableTransformer)) {
154: throw new TransformerException(CoreMessages
155: .transformerNotImplementDiscoverable(trans));
156: }
157: if (returnClass != null) {
158: trans.setReturnClass(returnClass);
159: }
160: if (name != null) {
161: trans.setName(name);
162: } else {
163: //This will generate a default name for the transformer
164: name = trans.getName();
165: //We then prefix the name to ensure there is less chance of conflict if the user registers
166: // the transformer with the same name
167: trans.setName("_" + name);
168: }
169: registry.registerTransformer(trans);
170: props.remove(TRANSFORMER_PREFIX + i++);
171: name = null;
172: returnClass = null;
173: transString = props.getProperty(TRANSFORMER_PREFIX + i);
174: }
175: }
176:
177: private void registerObjects(Properties props, Registry registry)
178: throws MuleException, IllegalAccessException,
179: NoSuchMethodException, InvocationTargetException,
180: InstantiationException, ClassNotFoundException {
181: //Note that caling the other register methods first will have removed any processed entries
182: for (Iterator iterator = props.entrySet().iterator(); iterator
183: .hasNext();) {
184: Map.Entry entry = (Map.Entry) iterator.next();
185: Object object = ClassUtils.instanciateClass(entry
186: .getValue().toString(), ClassUtils.NO_ARGS);
187: String key = entry.getKey().toString();
188: Class meta = Object.class;
189: if (object instanceof ObjectProcessor) {
190: meta = ObjectProcessor.class;
191: }
192: registry.registerObject(key, object, meta);
193: }
194: props.clear();
195: }
196:
197: private void registerUnnamedObjects(Properties props,
198: Registry registry) throws MuleException,
199: IllegalAccessException, NoSuchMethodException,
200: InvocationTargetException, InstantiationException,
201: ClassNotFoundException {
202: int i = 1;
203: String objectString = props.getProperty(OBJECT_PREFIX + i);
204: while (objectString != null) {
205:
206: Object o = ClassUtils.instanciateClass(objectString,
207: ClassUtils.NO_ARGS);
208: Class meta = Object.class;
209: if (o instanceof ObjectProcessor) {
210: meta = ObjectProcessor.class;
211: }
212: registry.registerObject(OBJECT_PREFIX + i + "#"
213: + o.hashCode(), o, meta);
214: props.remove(OBJECT_PREFIX + i++);
215: objectString = props.getProperty(OBJECT_PREFIX + i);
216: }
217: }
218: }
|