org.mule.registry.MuleRegistryHelper Maven / Gradle / Ivy
/*
* $Id: MuleRegistryHelper.java 22048 2011-05-31 14:39:03Z 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.registry;
import org.mule.api.MuleContext;
import org.mule.api.MuleException;
import org.mule.api.NameableObject;
import org.mule.api.agent.Agent;
import org.mule.api.config.MuleProperties;
import org.mule.api.construct.FlowConstruct;
import org.mule.api.endpoint.EndpointBuilder;
import org.mule.api.endpoint.EndpointFactory;
import org.mule.api.endpoint.ImmutableEndpoint;
import org.mule.api.lifecycle.Disposable;
import org.mule.api.lifecycle.Initialisable;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.lifecycle.LifecycleException;
import org.mule.api.model.Model;
import org.mule.api.registry.AbstractServiceDescriptor;
import org.mule.api.registry.MuleRegistry;
import org.mule.api.registry.RegistrationException;
import org.mule.api.registry.ResolverException;
import org.mule.api.registry.ServiceDescriptor;
import org.mule.api.registry.ServiceDescriptorFactory;
import org.mule.api.registry.ServiceException;
import org.mule.api.registry.ServiceType;
import org.mule.api.registry.TransformerResolver;
import org.mule.api.service.Service;
import org.mule.api.transformer.DataType;
import org.mule.api.transformer.DiscoverableTransformer;
import org.mule.api.transformer.Transformer;
import org.mule.api.transformer.TransformerException;
import org.mule.api.transport.Connector;
import org.mule.config.i18n.CoreMessages;
import org.mule.transformer.types.SimpleDataType;
import org.mule.util.SpiUtils;
import org.mule.util.StringUtils;
import org.mule.util.UUID;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Adds lookup/register/unregister methods for Mule-specific entities to the standard
* Registry interface.
*/
public class MuleRegistryHelper implements MuleRegistry
{
protected transient Log logger = LogFactory.getLog(MuleRegistryHelper.class);
/**
* A reference to Mule's internal registry
*/
private DefaultRegistryBroker registry;
/**
* We cache transformer searches so that we only search once
*/
protected ConcurrentHashMap/**/ exactTransformerCache = new ConcurrentHashMap/**/(8);
protected ConcurrentHashMap/*Map>*/ transformerListCache = new ConcurrentHashMap/*>*/(8);
private MuleContext muleContext;
public MuleRegistryHelper(DefaultRegistryBroker registry, MuleContext muleContext)
{
this.registry = registry;
this.muleContext = muleContext;
}
/**
* {@inheritDoc}
*/
public void initialise() throws InitialisationException
{
//no-op
//This is called when the MuleContext starts up, and should only do initialisation for any state on this class, the lifecycle
//for the registries will be handled by the LifecycleManager on the registry that this class wraps
}
/**
* {@inheritDoc}
*/
public void dispose()
{
transformerListCache.clear();
exactTransformerCache.clear();
}
public void fireLifecycle(String phase) throws LifecycleException
{
if(Initialisable.PHASE_NAME.equals(phase))
{
registry.initialise();
}
else if(Disposable.PHASE_NAME.equals(phase))
{
registry.dispose();
}
else
{
registry.fireLifecycle(phase);
}
}
/**
* {@inheritDoc}
*/
public Connector lookupConnector(String name)
{
return (Connector) registry.lookupObject(name);
}
/**
* Removed this method from {@link Registry} API as it should only be used
* internally and may confuse users. The {@link EndpointFactory} should be used
* for creating endpoints.
Looks up an returns endpoints registered in the
* registry by their identifier (currently endpoint name)
NOTE:
* This method does not create new endpoint instances, but rather returns
* existing endpoint instances that have been registered. This lookup method
* should be avoided and the intelligent, role specific endpoint lookup methods
* should be used instead.
*
* @param name the idendtifer/name used to register endpoint in registry
* @return foo
*/
/*public ImmutableEndpoint lookupEndpoint(String name)
{
Object obj = registry.lookupObject(name);
if (obj instanceof ImmutableEndpoint)
{
return (ImmutableEndpoint) obj;
}
else
{
logger.debug("No endpoint with the name: "
+ name
+ "found. If "
+ name
+ " is a global endpoint you should use the EndpointFactory to create endpoint instances from global endpoints.");
return null;
}
}*/
/**
* {@inheritDoc}
*/
public EndpointBuilder lookupEndpointBuilder(String name)
{
Object o = registry.lookupObject(name);
if (o instanceof EndpointBuilder)
{
logger.debug("Global endpoint EndpointBuilder for name: " + name + " found");
return (EndpointBuilder) o;
}
else
{
logger.debug("No endpoint builder with the name: " + name + " found.");
return null;
}
}
/**
* {@inheritDoc}
*/
public EndpointFactory lookupEndpointFactory()
{
return (EndpointFactory) registry.lookupObject(MuleProperties.OBJECT_MULE_ENDPOINT_FACTORY);
}
/**
* {@inheritDoc}
*/
public Transformer lookupTransformer(String name)
{
return (Transformer) registry.lookupObject(name);
}
/**
* {@inheritDoc}
*
* @deprecated use {@link #lookupTransformer(org.mule.api.transformer.DataType, org.mule.api.transformer.DataType)} instead. This
* method should only be used internally to discover transformers, typically a user does not need ot do this
* directly
*/
@Deprecated
public Transformer lookupTransformer(Class inputType, Class outputType) throws TransformerException
{
return lookupTransformer(new SimpleDataType(inputType), new SimpleDataType(outputType));
}
/**
* {@inheritDoc}
*
* @deprecated use {@link #lookupTransformer(org.mule.api.transformer.DataType, org.mule.api.transformer.DataType)} instead. This
* method should only be used internally to discover transformers, typically a user does not need ot do this
* directly
*/
@Deprecated
public List lookupTransformers(Class input, Class output)
{
return lookupTransformers(new SimpleDataType(input), new SimpleDataType(output));
}
/**
* {@inheritDoc}
*/
public Transformer lookupTransformer(DataType source, DataType result) throws TransformerException
{
final String dataTypePairHash = getDataTypeSourceResultPairHash(source, result);
Transformer cachedTransformer = (Transformer) exactTransformerCache.get(dataTypePairHash);
if (cachedTransformer != null)
{
return cachedTransformer;
}
Transformer trans = resolveTransformer(source, result);
if (trans != null)
{
Transformer concurrentlyAddedTransformer = (Transformer) exactTransformerCache.putIfAbsent(
dataTypePairHash, trans);
if (concurrentlyAddedTransformer != null)
{
return concurrentlyAddedTransformer;
}
else
{
return trans;
}
}
else
{
throw new TransformerException(CoreMessages.noTransformerFoundForMessage(source, result));
}
}
protected Transformer resolveTransformer(DataType source, DataType result) throws TransformerException
{
List resolvers = (List) lookupObjects(TransformerResolver.class);
Collections.sort(resolvers, new TransformerResolverComparator());
for (TransformerResolver resolver : resolvers)
{
try
{
Transformer trans = resolver.resolve(source, result);
if (trans != null)
{
return trans;
}
}
catch (ResolverException e)
{
throw new TransformerException(CoreMessages.noTransformerFoundForMessage(source, result), e);
}
}
return null;
}
/**
* {@inheritDoc}
*/
public List lookupTransformers(DataType source, DataType result)
{
final String dataTypePairHash = getDataTypeSourceResultPairHash(source, result);
List results = (List) transformerListCache.get(dataTypePairHash);
if (results != null)
{
return results;
}
results = new ArrayList(2);
Collection transformers = registry.lookupObjects(Transformer.class);
for (Transformer t : transformers)
{
// The transformer must have the DiscoveryTransformer interface if we are
// going to
// find it here
if (!(t instanceof DiscoverableTransformer))
{
continue;
}
DataType dt = t.getReturnDataType();
if (result.isCompatibleWith(dt) && t.isSourceDataTypeSupported(source))
{
results.add(t);
}
}
List concurrentlyAddedTransformers = (List) transformerListCache.putIfAbsent(
dataTypePairHash, results);
if (concurrentlyAddedTransformers != null)
{
return concurrentlyAddedTransformers;
}
else
{
return results;
}
}
/**
* {@inheritDoc}
*/
public Model lookupModel(String name)
{
return (Model) registry.lookupObject(name);
}
/**
* {@inheritDoc}
*/
public Model lookupSystemModel()
{
return lookupModel(MuleProperties.OBJECT_SYSTEM_MODEL);
}
/**
* {@inheritDoc}
*/
public Collection getModels()
{
return registry.lookupObjects(Model.class);
}
/**
* {@inheritDoc}
*/
public Collection getConnectors()
{
return registry.lookupObjects(Connector.class);
}
/**
* {@inheritDoc}
*/
public Collection getAgents()
{
return registry.lookupObjects(Agent.class);
}
/**
* {@inheritDoc}
*/
public Collection getEndpoints()
{
return registry.lookupObjects(ImmutableEndpoint.class);
}
/**
* {@inheritDoc}
*/
public Collection getTransformers()
{
return registry.lookupObjects(Transformer.class);
}
/**
* {@inheritDoc}
*/
public Agent lookupAgent(String name)
{
return (Agent) registry.lookupObject(name);
}
/**
* {@inheritDoc}
*/
public Service lookupService(String name)
{
return (Service) registry.lookupObject(name);
}
/**
* {@inheritDoc}
*/
public Collection lookupServices()
{
return lookupObjects(Service.class);
}
/**
* {@inheritDoc}
*/
public Collection lookupServices(String model)
{
Collection services = lookupServices();
List modelServices = new ArrayList();
Iterator it = services.iterator();
Service service;
while (it.hasNext())
{
service = (Service) it.next();
if (model.equals(service.getModel().getName()))
{
modelServices.add(service);
}
}
return modelServices;
}
/**
* {@inheritDoc}
*/
public FlowConstruct lookupFlowConstruct(String name)
{
return (FlowConstruct) registry.lookupObject(name);
}
/**
* {@inheritDoc}
*/
public Collection lookupFlowConstructs()
{
return lookupObjects(FlowConstruct.class);
}
/**
* {@inheritDoc}
*/
public final void registerTransformer(Transformer transformer) throws MuleException
{
registry.registerObject(getName(transformer), transformer, Transformer.class);
notifyTransformerResolvers(transformer, TransformerResolver.RegistryAction.ADDED);
}
protected void notifyTransformerResolvers(Transformer t, TransformerResolver.RegistryAction action)
{
if (t instanceof DiscoverableTransformer)
{
Collection resolvers = lookupObjects(TransformerResolver.class);
for (TransformerResolver resolver : resolvers)
{
resolver.transformerChange(t, action);
}
transformerListCache.clear();
exactTransformerCache.clear();
}
}
/**
* Looks up the service descriptor from a singleton cache and creates a new one if not found.
*/
public ServiceDescriptor lookupServiceDescriptor(ServiceType type, String name, Properties overrides) throws ServiceException
{
String key = new AbstractServiceDescriptor.Key(name, overrides).getKey();
// TODO If we want these descriptors loaded form Spring we need to change the key mechanism
// and the scope, and then deal with circular reference issues.
ServiceDescriptor sd = (ServiceDescriptor) registry.lookupObject(key);
synchronized (this)
{
if (sd == null)
{
sd = createServiceDescriptor(type, name, overrides);
try
{
registry.registerObject(key, sd, ServiceDescriptor.class);
}
catch (RegistrationException e)
{
throw new ServiceException(e.getI18nMessage(), e);
}
}
}
return sd;
}
protected ServiceDescriptor createServiceDescriptor(ServiceType type, String name, Properties overrides) throws ServiceException
{
//Stripe off and use the meta-scheme if present
String scheme = name;
if (name.contains(":"))
{
scheme = name.substring(0, name.indexOf(":"));
}
Properties props = SpiUtils.findServiceDescriptor(type, scheme);
if (props == null)
{
throw new ServiceException(CoreMessages.failedToLoad(type + " " + scheme));
}
return ServiceDescriptorFactory.create(type, name, props, overrides, muleContext,
muleContext.getExecutionClassLoader());
}
/**
* {@inheritDoc}
*/
public void registerAgent(Agent agent) throws MuleException
{
registry.registerObject(getName(agent), agent, Agent.class);
}
/**
* {@inheritDoc}
*/
public void registerConnector(Connector connector) throws MuleException
{
registry.registerObject(getName(connector), connector, Connector.class);
}
/**
* {@inheritDoc}
*/
public void registerEndpoint(ImmutableEndpoint endpoint) throws MuleException
{
registry.registerObject(getName(endpoint), endpoint, ImmutableEndpoint.class);
}
/**
* {@inheritDoc}
*/
public void registerEndpointBuilder(String name, EndpointBuilder builder) throws MuleException
{
registry.registerObject(name, builder, EndpointBuilder.class);
}
/**
* {@inheritDoc}
*/
public void registerModel(Model model) throws MuleException
{
registry.registerObject(getName(model), model, Model.class);
}
/**
* {@inheritDoc}
*/
public void registerService(Service service) throws MuleException
{
registry.registerObject(getName(service), service, Service.class);
}
/**
* {@inheritDoc}
*/
public void unregisterService(String serviceName) throws MuleException
{
registry.unregisterObject(serviceName, Service.class);
}
/**
* {@inheritDoc}
*/
public void registerFlowConstruct(FlowConstruct flowConstruct) throws MuleException
{
registry.registerObject(getName(flowConstruct), flowConstruct, FlowConstruct.class);
}
/**
* {@inheritDoc}
*/
public void unregisterFlowConstruct(String flowConstructName) throws MuleException
{
registry.unregisterObject(flowConstructName, FlowConstruct.class);
}
/**
* {@inheritDoc}
*/
public void unregisterAgent(String agentName) throws MuleException
{
registry.unregisterObject(agentName, Agent.class);
}
/**
* {@inheritDoc}
*/
public void unregisterConnector(String connectorName) throws MuleException
{
registry.unregisterObject(connectorName, Connector.class);
}
/**
* {@inheritDoc}
*/
public void unregisterEndpoint(String endpointName) throws MuleException
{
registry.unregisterObject(endpointName, ImmutableEndpoint.class);
}
/**
* {@inheritDoc}
*/
public void unregisterModel(String modelName) throws MuleException
{
registry.unregisterObject(modelName, Model.class);
}
/**
* {@inheritDoc}
*/
public void unregisterTransformer(String transformerName) throws MuleException
{
Transformer transformer = lookupTransformer(transformerName);
notifyTransformerResolvers(transformer, TransformerResolver.RegistryAction.REMOVED);
registry.unregisterObject(transformerName, Transformer.class);
}
/**
* {@inheritDoc}
*/
public Object applyProcessorsAndLifecycle(Object object) throws MuleException
{
object = applyProcessors(object);
object = applyLifecycle(object);
return object;
}
/**
* {@inheritDoc}
*/
public Object applyProcessors(Object object) throws MuleException
{
return registry.getTransientRegistry().applyProcessors(object, null);
}
/**
* {@inheritDoc}
*/
public Object applyProcessors(Object object, int flags) throws MuleException
{
return registry.getTransientRegistry().applyProcessors(object, flags);
}
/**
* {@inheritDoc}
*/
public Object applyLifecycle(Object object) throws MuleException
{
return registry.getTransientRegistry().applyLifecycle(object);
}
public Object applyLifecycle(Object object, String phase) throws MuleException
{
return registry.getTransientRegistry().applyLifecycle(object, phase);
}
////////////////////////////////////////////////////////////////////////////
// Delegate to internal registry
////////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
public T lookupObject(Class type) throws RegistrationException
{
return registry.lookupObject(type);
}
@SuppressWarnings("unchecked")
public T lookupObject(String key)
{
return (T) registry.lookupObject(key);
}
/**
* {@inheritDoc}
*/
public Collection lookupObjects(Class type)
{
return registry.lookupObjects(type);
}
/**
* {@inheritDoc}
*/
public Collection lookupObjectsForLifecycle(Class type)
{
return registry.lookupObjectsForLifecycle(type);
}
@SuppressWarnings("unchecked")
public T get(String key)
{
return (T)registry.get(key);
}
public Map lookupByType(Class type)
{
return registry.lookupByType(type);
}
/**
* {@inheritDoc}
*/
public void registerObject(String key, Object value, Object metadata) throws RegistrationException
{
registry.registerObject(key, value, metadata);
}
/**
* {@inheritDoc}
*/
public void registerObject(String key, Object value) throws RegistrationException
{
registry.registerObject(key, value);
}
/**
* {@inheritDoc}
*/
public void registerObjects(Map objects) throws RegistrationException
{
registry.registerObjects(objects);
}
/**
* {@inheritDoc}
*/
public void unregisterObject(String key, Object metadata) throws RegistrationException
{
registry.unregisterObject(key, metadata);
}
/**
* {@inheritDoc}
*/
public void unregisterObject(String key) throws RegistrationException
{
registry.unregisterObject(key);
}
/**
* Returns the name for the object passed in. If the object implements {@link org.mule.api.NameableObject}, then
* {@link org.mule.api.NameableObject#getName()} will be returned, otherwise a name is generated using the class name
* and a generated UUID.
* @param obj the object to inspect
* @return the name for this object
*/
protected String getName(Object obj)
{
String name = null;
if (obj instanceof NameableObject)
{
name = ((NameableObject) obj).getName();
}
else if (obj instanceof FlowConstruct)
{
name = ((FlowConstruct) obj).getName();
}
if (StringUtils.isBlank(name))
{
name = obj.getClass().getName() + ":" + UUID.getUUID();
}
return name;
}
////////////////////////////////////////////////////////////////////////////
// Registry Metadata
////////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
public String getRegistryId()
{
return this.toString();
}
/**
* {@inheritDoc}
*/
public boolean isReadOnly()
{
return false;
}
/**
* {@inheritDoc}
*/
public boolean isRemote()
{
return false;
}
private String getDataTypeSourceResultPairHash(DataType> source, DataType> result)
{
return source.getClass().getName() + source.hashCode() + ":" + result.getClass().getName()
+ result.hashCode();
}
private class TransformerResolverComparator implements Comparator
{
public int compare(TransformerResolver transformerResolver, TransformerResolver transformerResolver1)
{
if (transformerResolver.getClass().equals(TypeBasedTransformerResolver.class))
{
return 1;
}
if (transformerResolver1.getClass().equals(TypeBasedTransformerResolver.class))
{
return -1;
}
return 0;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy