Package org.mule.config.bootstrap

Source Code of org.mule.config.bootstrap.SimpleRegistryBootstrap

/*
* $Id: SimpleRegistryBootstrap.java 20321 2010-11-24 15:21:24Z dfeist $
* --------------------------------------------------------------------------------------
* Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
*
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.config.bootstrap;

import org.mule.api.MuleContext;
import org.mule.api.context.MuleContextAware;
import org.mule.api.lifecycle.Initialisable;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.registry.MuleRegistry;
import org.mule.api.registry.ObjectProcessor;
import org.mule.api.registry.RegistrationException;
import org.mule.api.registry.Registry;
import org.mule.api.transformer.DiscoverableTransformer;
import org.mule.api.transformer.Transformer;
import org.mule.api.util.StreamCloser;
import org.mule.config.i18n.CoreMessages;
import org.mule.transformer.types.DataTypeFactory;
import org.mule.util.ClassUtils;
import org.mule.util.ExceptionUtils;
import org.mule.util.PropertiesUtils;
import org.mule.util.UUID;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* This object will load objects defined in a file called <code>registry-bootstrap.properties</code> into the local registry.
* This allows modules and transports to make certain objects available by default.  The most common use case is for a
* module or transport to load stateless transformers into the registry.
* For this file to be located it must be present in the modules META-INF directory under
* <pre>META-INF/services/org/mule/config/</pre>
* <p/>
* The format of this file is a simple key / value pair. i.e.
* <pre>
* myobject=org.foo.MyObject
* </pre>
* Will register an instance of MyObject with a key of 'myobject'. If you don't care about the object name and want to
* ensure that the ojbect gets a unique name you can use -
* <pre>
* object.1=org.foo.MyObject
* object.2=org.bar.MyObject
* </pre>
* or
* <pre>
* myFoo=org.foo.MyObject
* myBar=org.bar.MyObject
* </pre>
* Loading transformers has a slightly different notation since you can define the 'returnClass' with optional mime type, and 'name'of
* the transformer as parameters i.e.
* <pre>
* transformer.1=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=byte[]
* transformer.2=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=java.lang.String:text/xml, name=JMSMessageToString
* transformer.3=org.mule.transport.jms.transformers.JMSMessageToObject,returnClass=java.util.Hashtable)
* </pre>
* Note that the key used for transformers must be 'transformer.x' where 'x' is a sequential number.  The transformer name will be
* automatically generated as JMSMessageToXXX where XXX is the return class name i.e. JMSMessageToString unless a 'name'
* parameter is specified. If no 'returnClass' is specified the default in the transformer will be used.
* <p/>
* Note that all objects defined have to have a default constructor. They can implement injection interfaces such as
* {@link org.mule.api.context.MuleContextAware} and lifecycle interfaces such as {@link org.mule.api.lifecycle.Initialisable}.
*/
public class SimpleRegistryBootstrap implements Initialisable, MuleContextAware
{
    public static final String SERVICE_PATH = "META-INF/services/org/mule/config/";

    public static final String REGISTRY_PROPERTIES = "registry-bootstrap.properties";

    public String TRANSFORMER_KEY = ".transformer.";
    public String OBJECT_KEY = ".object.";

    protected final transient Log logger = LogFactory.getLog(getClass());

    protected MuleContext context;

    /** {@inheritDoc} */
    public void setMuleContext(MuleContext context)
    {
        this.context = context;
    }

    /** {@inheritDoc} */
    public void initialise() throws InitialisationException
    {
        Enumeration<?> e = ClassUtils.getResources(SERVICE_PATH + REGISTRY_PROPERTIES, getClass());
        List<Properties> bootstraps = new LinkedList<Properties>();

        // load ALL of the bootstrap files first
        while (e.hasMoreElements())
        {
            try
            {
                URL url = (URL) e.nextElement();
                if (logger.isDebugEnabled())
                {
                    logger.debug("Reading bootstrap file: " + url.toString());
                }
                Properties p = new Properties();
                p.load(url.openStream());
                bootstraps.add(p);
            }
            catch (Exception e1)
            {
                throw new InitialisationException(e1, this);
            }
        }

        // ... and only then merge and process them
        int objectCounter = 1;
        int transformerCounter = 1;
        Properties transformers = new Properties();
        Properties namedObjects = new Properties();
        Properties unnamedObjects = new Properties();

        for (Properties bootstrap : bootstraps)
        {
            for (Map.Entry entry : bootstrap.entrySet())
            {
                final String key = (String) entry.getKey();
                if (key.contains(OBJECT_KEY))
                {
                    String newKey = key.substring(0, key.lastIndexOf(".")) + objectCounter++;
                    unnamedObjects.put(newKey, entry.getValue());
                }
                else if (key.contains(TRANSFORMER_KEY))
                {
                    String newKey = key.substring(0, key.lastIndexOf(".")) + transformerCounter++;
                    transformers.put(newKey, entry.getValue());
                }
                else
                {
                    // we allow arbitrary keys in the registry-bootstrap.properties but since we're
                    // aggregating multiple files here we must make sure that the keys are unique
//                    if (accumulatedProps.getProperty(key) != null)
//                    {
//                        throw new IllegalStateException(
//                                "more than one registry-bootstrap.properties file contains a key " + key);
//                    }
//                    else
                    {
                        namedObjects.put(key, entry.getValue());
                    }
                }
            }
        }

        try
        {
            registerUnnamedObjects(unnamedObjects, context.getRegistry());
            registerTransformers(transformers, context.getRegistry());
            registerObjects(namedObjects, context.getRegistry());
        }
        catch (Exception e1)
        {
            throw new InitialisationException(e1, this);
        }
    }

    private void registerTransformers(Properties props, MuleRegistry registry) throws Exception
    {
        String transString;
        String name = null;
        String returnClassString;
        boolean optional = false;

        for (Map.Entry<Object, Object> entry : props.entrySet())
        {
            transString = (String)entry.getValue();
            // reset
            Class<?> returnClass = null;
            returnClassString = null;
            int x = transString.indexOf(",");
            if (x > -1)
            {
                Properties p = PropertiesUtils.getPropertiesFromString(transString.substring(x + 1), ',');
                name = p.getProperty("name", null);
                returnClassString = p.getProperty("returnClass", null);
                optional = p.containsKey("optional");
            }

            final String transClass = (x == -1 ? transString : transString.substring(0, x));
            try
            {
                String mime = null;
                if (returnClassString != null)
                {
                    int i = returnClassString.indexOf(":");
                    if(i > -1)
                    {
                        mime = returnClassString.substring(i + 1);
                        returnClassString = returnClassString.substring(0, i);
                    }
                    if (returnClassString.equals("byte[]"))
                    {
                        returnClass = byte[].class;
                    }
                    else
                    {
                        returnClass = ClassUtils.loadClass(returnClassString, getClass());
                    }
                }
                Transformer trans = (Transformer) ClassUtils.instanciateClass(transClass);
                if (!(trans instanceof DiscoverableTransformer))
                {
                    throw new RegistrationException(CoreMessages.transformerNotImplementDiscoverable(trans));
                }
                if (returnClass != null)
                {
                    trans.setReturnDataType(DataTypeFactory.create(returnClass, mime));
                }
                if (name != null)
                {
                    trans.setName(name);
                }
                else
                {
                    //This will generate a default name for the transformer
                    name = trans.getName();
                    //We then prefix the name to ensure there is less chance of conflict if the user registers
                    // the transformer with the same name
                    trans.setName("_" + name);
                }
                registry.registerTransformer(trans);
            }
            catch (InvocationTargetException itex)
            {
                Throwable cause = ExceptionUtils.getCause(itex);
                if (cause instanceof NoClassDefFoundError && optional)
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("Ignoring optional transformer: " + transClass);
                    }
                }
                else
                {
                    throw new Exception(cause);
                }
            }
            catch (NoClassDefFoundError ncdfe)
            {
                if (optional)
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("Ignoring optional transformer: " + transClass);
                    }
                }
                else
                {
                    throw ncdfe;
                }
            }
            catch (ClassNotFoundException cnfe)
            {
                if (optional)
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("Ignoring optional transformer: " + transClass);
                    }
                }
                else
                {
                    throw cnfe;
                }
            }

            name = null;
            returnClass = null;
        }
    }

    private void registerObjects(Properties props, Registry registry) throws Exception
    {
        for (Map.Entry<Object, Object> entry : props.entrySet())
        {
            registerObject((String)entry.getKey(), (String)entry.getValue(), registry);
        }
        props.clear();
    }

    private void registerUnnamedObjects(Properties props, Registry registry) throws Exception
    {
        for (Map.Entry<Object, Object> entry : props.entrySet())
        {
            final String key = String.format("%s#%s", entry.getKey(), UUID.getUUID());
            registerObject(key, (String) entry.getValue(), registry);
        }
        props.clear();
    }

    private void registerObject(String key, String value, Registry registry) throws Exception
    {
        boolean optional = false;
        String className = null;

        try
        {
            int x = value.indexOf(",");
            if (x > -1)
            {
                Properties p = PropertiesUtils.getPropertiesFromString(value.substring(x + 1), ',');
                optional = p.containsKey("optional");
                className = value.substring(0, x);
            }
            else
            {
                className = value;
            }
            Object o = ClassUtils.instanciateClass(className);
            Class<?> meta = Object.class;

            if (o instanceof ObjectProcessor)
            {
                meta = ObjectProcessor.class;
            }
            else if (o instanceof StreamCloser)
            {
                meta = StreamCloser.class;
            }
            else if (o instanceof BootstrapObjectFactory)
            {
                o = ((BootstrapObjectFactory)o).create();
            }
            registry.registerObject(key, o, meta);
        }
        catch (InvocationTargetException itex)
        {
            Throwable cause = ExceptionUtils.getCause(itex);
            if (cause instanceof NoClassDefFoundError && optional)
            {
                if (logger.isDebugEnabled())
                {
                    logger.debug("Ignoring optional object: " + className);
                }
            }
            else
            {
                throw new Exception(cause);
            }
        }
        catch (NoClassDefFoundError ncdfe)
        {
            if (optional)
            {
                if (logger.isDebugEnabled())
                {
                    logger.debug("Ignoring optional object: " + className);
                }
            }
            else
            {
                throw ncdfe;
            }
        }
        catch (ClassNotFoundException cnfe)
        {
            if (optional)
            {
                if (logger.isDebugEnabled())
                {
                    logger.debug("Ignoring optional object: " + className);
                }
            }
            else
            {
                throw cnfe;
            }
        }
    }
}
TOP

Related Classes of org.mule.config.bootstrap.SimpleRegistryBootstrap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.