/*
* 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.runtime.core.object;
import org.mule.runtime.api.i18n.I18nMessageFactory;
import org.mule.runtime.api.lifecycle.InitialisationException;
import org.mule.runtime.api.meta.AbstractAnnotatedObject;
import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.core.api.construct.FlowConstruct;
import org.mule.runtime.core.api.construct.FlowConstructAware;
import org.mule.runtime.core.api.lifecycle.InitialisationCallback;
import org.mule.runtime.core.api.object.ObjectFactory;
import org.mule.runtime.core.util.BeanUtils;
import org.mule.runtime.core.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Creates object instances based on the class and sets any properties. This factory is also responsible for applying any object
* processors on the object before the lifecycle callbacks are called.
*/
public abstract class AbstractObjectFactory extends AbstractAnnotatedObject implements ObjectFactory, FlowConstructAware {
public static final String ATTRIBUTE_OBJECT_CLASS_NAME = "objectClassName";
public static final String ATTRIBUTE_OBJECT_CLASS = "objectClass";
protected String objectClassName;
protected Class<?> objectClass;
protected Map properties = null;
protected List<InitialisationCallback> initialisationCallbacks = new ArrayList<InitialisationCallback>();
protected FlowConstruct flowConstruct;
protected boolean disposed = false;
protected transient Logger logger = LoggerFactory.getLogger(getClass());
/**
* For Spring only
*/
public AbstractObjectFactory() {
// nop
}
public AbstractObjectFactory(String objectClassName) {
this(objectClassName, null);
}
public AbstractObjectFactory(String objectClassName, Map properties) {
super();
this.objectClassName = objectClassName;
this.properties = properties;
setupObjectClassFromObjectClassName();
}
public AbstractObjectFactory(Class<?> objectClass) {
this(objectClass, null);
}
public AbstractObjectFactory(Class<?> objectClass, Map properties) {
super();
this.objectClassName = objectClass.getName();
this.objectClass = objectClass;
this.properties = properties;
}
protected Class<?> setupObjectClassFromObjectClassName() {
try {
Class<?> klass = ClassUtils.getClass(objectClassName);
objectClass = klass;
return klass;
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(e);
}
}
public void setFlowConstruct(FlowConstruct flowConstruct) {
this.flowConstruct = flowConstruct;
}
public void initialise() throws InitialisationException {
if ((objectClassName == null) || (objectClass == null)) {
throw new InitialisationException(I18nMessageFactory.createStaticMessage("Object factory has not been initialized."), this);
}
disposed = false;
}
public void dispose() {
disposed = true;
// Don't reset the component config state i.e. objectClass since service objects can be recycled
}
/**
* Creates an initialized object instance based on the class and sets any properties. This method handles all injection of
* properties for the resulting object
*
* @param muleContext the current {@link org.mule.runtime.core.api.MuleContext} instance. This can be used for performing
* registry lookups applying processors to newly created objects or even firing custom notifications
* @throws Exception Can throw any type of exception while creating a new object
*/
public Object getInstance(MuleContext muleContext) throws Exception {
if (objectClass == null || disposed) {
throw new InitialisationException(I18nMessageFactory.createStaticMessage("Object factory has not been initialized."), this);
}
Object object = ClassUtils.instanciateClass(objectClass);
if (properties != null) {
BeanUtils.populateWithoutFail(object, properties, true);
}
if (object instanceof FlowConstructAware) {
((FlowConstructAware) object).setFlowConstruct(flowConstruct);
}
if (isAutoWireObject()) {
muleContext.getRegistry().applyProcessors(object);
}
fireInitialisationCallbacks(object);
return object;
}
protected void fireInitialisationCallbacks(Object component) throws InitialisationException {
for (InitialisationCallback callback : initialisationCallbacks) {
callback.initialise(component);
}
}
public Class<?> getObjectClass() {
return objectClass;
}
public void setObjectClass(Class<?> objectClass) {
this.objectClass = objectClass;
this.objectClassName = objectClass.getName();
}
protected String getObjectClassName() {
return objectClassName;
}
public void setObjectClassName(String objectClassName) {
this.objectClassName = objectClassName;
setupObjectClassFromObjectClassName();
}
protected Map getProperties() {
return properties;
}
public void setProperties(Map properties) {
this.properties = properties;
}
public void addObjectInitialisationCallback(InitialisationCallback callback) {
initialisationCallbacks.add(callback);
}
public boolean isSingleton() {
return false;
}
public boolean isExternallyManagedLifecycle() {
return false;
}
public boolean isAutoWireObject() {
return true;
}
}