All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.milyn.javabean.factory.BasicFactoryDefinitionParser Maven / Gradle / Ivy

The newest version!
/*
 * Milyn - Copyright (C) 2006 - 2010
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License (version 2.1) as published by the Free Software
 *  Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  See the GNU Lesser General Public License for more details:
 *  http://www.gnu.org/licenses/lgpl.txt
 */
package org.milyn.javabean.factory;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.milyn.container.ExecutionContext;
import org.milyn.util.ClassUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * The BasicFactoryDefinitionParser supports two kinds of
 * factory definitions:
 * 
    *
  1. some.package.SomeFactory#createObject
    * This defines that the 'createObject' of the class 'some.package.SomeFactory' * should be called for creating the target object. *
  2. some.package.SomeFactorySingleton#getFactoryMethod.createObject
    * This defines that the 'getFactoryMethod' of the class 'some.package.SomeFactorySingleton' * should be called to retrieve the factory object on which the 'createObject' should * be called for creating the target object.
    * The factory retrieval method should never return null. This * will result in a {@link NullPointerException}. *
* * * * @author [email protected] * */ @Alias("basic") public class BasicFactoryDefinitionParser extends AbstractCachingFactoryDefinitionParser { @Override protected Factory createFactory(String factoryDefinition) { String[] defParts = StringUtils.split(factoryDefinition, '#'); if (defParts.length == 2) { String className = defParts[0]; String methodDef = defParts[1]; try { String[] methodParts = StringUtils.split(methodDef, '.'); if (methodParts.length == 1) { return createStaticMethodFactory(factoryDefinition, className, methodDef); } else if (methodParts.length == 2) { String staticGetInstanceMethodDef = methodParts[0]; String factoryMethodDef = methodParts[1]; return createFactoryInstanceFactory(factoryDefinition, className, staticGetInstanceMethodDef, factoryMethodDef); } else { throw createInvalidDefinitionException(factoryDefinition); } } catch (InvalidFactoryDefinitionException e) { throw e; } catch (Exception e) { throw new FactoryException("The factory could not be created from the definition '"+ factoryDefinition +"'.", e); } } else { throw createInvalidDefinitionException(factoryDefinition); } } /** * Creates a StaticMethodFactory object. * * @param factoryDefinition * @param className * @param methodDef * @return * @throws ClassNotFoundException * @throws SecurityException * @throws NoSuchMethodException */ private Factory createStaticMethodFactory(String factoryDefinition, String className, String methodDef) throws ClassNotFoundException, SecurityException, NoSuchMethodException { Class factoryClass = ClassUtil.forName(className, this.getClass()); Method factoryMethod = factoryClass.getMethod(methodDef); if(!Modifier.isStatic(factoryMethod.getModifiers())) { throw new NoSuchMethodException("No static method with the name '"+ methodDef +"' can be found on the class '" + className + "' while processing the factory definition '"+ factoryDefinition +"'."); } return new StaticMethodFactory(factoryDefinition, factoryMethod); } /** * Creates a FactoryInstanceFactory object. * * @param factoryDefinition * @param className * @param staticGetInstanceMethodDef * @param factoryMethodDef * @return * @throws ClassNotFoundException * @throws SecurityException * @throws NoSuchMethodException */ private Factory createFactoryInstanceFactory(String factoryDefinition, String className, String staticGetInstanceMethodDef, String factoryMethodDef) throws ClassNotFoundException, SecurityException, NoSuchMethodException{ Class factoryClass = ClassUtil.forName(className, this.getClass()); Method getInstanceMethod = factoryClass.getMethod(staticGetInstanceMethodDef); Class factoryType = getInstanceMethod.getReturnType(); Method factoryMethod = factoryType.getMethod(factoryMethodDef); if(!Modifier.isStatic(getInstanceMethod.getModifiers())) { throw new NoSuchMethodException("No static method with the name '"+ staticGetInstanceMethodDef +"' can be found on the class '" + className + "'."); } return new FactoryInstanceFactory(factoryDefinition, getInstanceMethod, factoryMethod); } private InvalidFactoryDefinitionException createInvalidDefinitionException(String factoryDefinition) { return new InvalidFactoryDefinitionException("The factory definition '" + factoryDefinition +"' " + "isn't valid. The definition is 'some.package.SomeFactory#createObject' or " + "'some.package.SomeFactorySingleton#getFactoryMethod.createObject'"); } private static String toClassDefinition(Method method) { return method.getDeclaringClass().getName() + "#" + method.getName() + "()"; } /** * The StaticMethodFactory uses a static factory method create the target objects. */ private static class StaticMethodFactory implements Factory { private final String factoryDefinition; private final Method factoryMethod; public StaticMethodFactory(String factoryDefinition, Method factoryMethod) { this.factoryDefinition = factoryDefinition; this.factoryMethod = factoryMethod; } public Object create(ExecutionContext executionContext) { try { return factoryMethod.invoke(null); } catch (IllegalAccessException e) { throw new FactoryException("Could not invoke the static factory method '" + toClassDefinition(factoryMethod)+ "' defined by the factory definition '"+ factoryDefinition +"'"); } catch (InvocationTargetException e) { throw new FactoryException("Could not invoke the static factory method '" + toClassDefinition(factoryMethod)+ "' defined by the factory definition '"+ factoryDefinition +"'"); } } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); builder.append("factoryDefinition", factoryDefinition) .append("factoryMethod", factoryMethod); return builder.toString(); } } /** * The FactoryInstanceFactory uses a static method to retrieve the factory object and * then calls the factory method on the factory object to create the target objects. */ private static class FactoryInstanceFactory implements Factory { private final String factoryDefinition; private final Method getInstanceMethod; private final Method factoryMethod; public FactoryInstanceFactory(String factoryDefinition, Method getInstanceMethod, Method factoryMethod) { this.factoryDefinition = factoryDefinition; this.getInstanceMethod = getInstanceMethod; this.factoryMethod = factoryMethod; } public Object create(ExecutionContext executionContext) { Object factoryObj; try { factoryObj = getInstanceMethod.invoke(null); } catch (IllegalAccessException e) { throw new FactoryException("Could not invoke the static method '" + toClassDefinition(getInstanceMethod)+ "' to retrieve the factory defined by the factory definition '"+ factoryDefinition +"'"); } catch (InvocationTargetException e) { throw new FactoryException("Could not invoke the static method '" + toClassDefinition(getInstanceMethod)+ "' to retrieve the factory defined by the factory definition '"+ factoryDefinition +"'"); } if(factoryObj == null){ throw new NullPointerException("The static method '" + toClassDefinition(getInstanceMethod)+ "' returned null, which is not allowed" ); } try { return factoryMethod.invoke(factoryObj); } catch (IllegalAccessException e) { throw new FactoryException("Could not invoke the method '" + toClassDefinition(factoryMethod)+ "' on the factory object '"+ factoryObj +"'. This factory is defined by the factory definition '"+ factoryDefinition +"'"); } catch (InvocationTargetException e) { throw new FactoryException("Could not invoke the method '" + toClassDefinition(factoryMethod)+ "' on the factory object '"+ factoryObj +"'. This factory is defined by the factory definition '"+ factoryDefinition +"'"); } } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); builder.append("factoryDefinition", factoryDefinition) .append("factoryMethod", factoryMethod); return builder.toString(); } } }