/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.codehaus.aspectwerkz.definition;
import org.codehaus.aspectwerkz.AspectSystem;
import org.codehaus.aspectwerkz.ContextClassLoader;
import org.codehaus.aspectwerkz.CrossCuttingInfo;
import org.codehaus.aspectwerkz.DeploymentModel;
import org.codehaus.aspectwerkz.SystemLoader;
import org.codehaus.aspectwerkz.aspect.AspectContainer;
import org.codehaus.aspectwerkz.aspect.CFlowSystemAspect;
import org.codehaus.aspectwerkz.aspect.AdviceType;
import org.codehaus.aspectwerkz.aspect.management.AspectManager;
import org.codehaus.aspectwerkz.aspect.management.Pointcut;
import org.codehaus.aspectwerkz.aspect.management.PointcutManager;
import org.codehaus.aspectwerkz.exception.DefinitionException;
import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
import org.codehaus.aspectwerkz.expression.ExpressionInfo;
import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Manages the startup procedure, walks through the definition and instantiates the
* aspects/advices/introduction/pointcuts. <p/>Reads the definition, either as a class of as an XML file. <p/>To use
* your XML definition file pass <code>-Daspectwerkz.definition.file=PathToFile</code> as parameter to the JVM. <p/>If
* the above given parameter is not specified, the <code>StartupManager</code> tries locate a file called
* <code>aspectwerkz.xml</code> in the classpath and if this fails the last attempt is to use the
* <code>ASPECTWERKZ_HOME/config/aspectwerkz.xml</code> file (if there is one).
*
* @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a>
* @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
*/
public class StartupManager {
/**
* The default aspect container class.
*/
public static final String DEFAULT_ASPECT_CONTAINER = "org.codehaus.aspectwerkz.aspect.DefaultAspectContainerStrategy";
/**
* Private constructor to prevent instantiability.
*/
private StartupManager() {
}
/**
* Loads the system definition.
*
* @param aspectManager the aspectManager for the system
* @param definition the definition for the system
*/
public static void initializeSystem(final AspectManager aspectManager, final SystemDefinition definition) {
// note: initialization check is maintained by AspectRegistry due to a lazy policy
registerAspects(aspectManager, definition);
registerPointcuts(aspectManager, definition);
registerCflowPointcuts(aspectManager, definition);
}
/**
* ReLoads the system definition.
*
* @param loader the class loader
* @param definition the definition for the system
*/
public static void reinitializeSystem(final ClassLoader loader, final SystemDefinition definition) {
AspectSystem aspectSystem = SystemLoader.getSystem(loader);
AspectManager aspectManager = aspectSystem.getAspectManager(definition.getUuid());
// TODO better runtime part sync with def part for RW/RuW/HotDeploy
// when altering existing pc, those needs to be updated manaually (see EWorldUtil)
registerPointcuts(aspectManager, definition);
registerCflowPointcuts(aspectManager, definition);
return;
}
/**
* Creates a new aspect container.
*
* @param crossCuttingInfo the cross-cutting info for the aspect
*/
public static AspectContainer createAspectContainer(final CrossCuttingInfo crossCuttingInfo) {
String containerClassName = "";
try {
Class klass;
containerClassName = crossCuttingInfo.getAspectDefinition().getContainerClassName();
if ((containerClassName == null)
|| crossCuttingInfo.getAspectClass().getName().equals(CFlowSystemAspect.CLASS_NAME)) {
klass = ContextClassLoader.loadClass(DEFAULT_ASPECT_CONTAINER);
} else {
klass = ContextClassLoader.loadClass(containerClassName);
}
Constructor constructor = klass.getConstructor(new Class[] {
CrossCuttingInfo.class
});
return (AspectContainer) constructor.newInstance(new Object[] {
crossCuttingInfo
});
} catch (InvocationTargetException e) {
throw new DefinitionException(e.getTargetException().toString());
} catch (NoSuchMethodException e) {
throw new DefinitionException("aspect container does not have a valid constructor ["
+ containerClassName
+ "] (one that takes a CrossCuttingInfo instance as its only parameter): "
+ e.toString());
} catch (Throwable e) {
StringBuffer cause = new StringBuffer();
cause.append("could not create aspect container using the implementation specified [");
cause.append(containerClassName);
cause.append("] due to: ");
cause.append(e.toString());
e.printStackTrace();
throw new DefinitionException(cause.toString());
}
}
/**
* Creates and registers the aspects defined.
*
* @param aspectManager the aspectManager for the system
* @param definition the definition
*/
private static void registerAspects(final AspectManager aspectManager, final SystemDefinition definition) {
try {
for (Iterator it = definition.getAspectDefinitions().iterator(); it.hasNext();) {
AspectDefinition aspectDef = (AspectDefinition) it.next();
registerAspect(aspectManager, aspectDef, definition.getParameters(aspectDef.getName()));
}
} catch (NullPointerException e) {
throw new DefinitionException("aspects not properly defined");
} catch (Exception e) {
throw new WrappedRuntimeException(e);
}
}
/**
* Registers and creates a new aspect container for the aspect.
*
* @param aspectManager the aspectManager for the system
* @param aspectDef the aspect definition
*/
private static void registerAspect(
final AspectManager aspectManager,
final AspectDefinition aspectDef,
final Map parameters) {
try {
String aspectClassName = aspectDef.getClassName();
// load the aspect class
final Class aspectClass;
try {
aspectClass = aspectManager.m_system.getDefiningClassLoader().loadClass(aspectClassName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(aspectClassName + " could not be found on classpath: " + e.toString());
}
int deploymentModel;
if ((aspectDef.getDeploymentModel() == null) || aspectDef.getDeploymentModel().equals("")) {
deploymentModel = DeploymentModel.PER_JVM;
} else {
deploymentModel = DeploymentModel.getDeploymentModelAsInt(aspectDef.getDeploymentModel());
}
//TODO: we could set the WHOLE AspectManager that defines the Aspect instead
final CrossCuttingInfo crossCuttingInfoPrototype = new CrossCuttingInfo(
aspectManager.getUuid(),
aspectClass,
aspectDef.getName(),
deploymentModel,
aspectDef,
parameters);
final AspectContainer container = createAspectContainer(crossCuttingInfoPrototype);
crossCuttingInfoPrototype.setContainer(container);
PointcutManager pointcutManager = new PointcutManager(aspectDef.getName(), deploymentModel);
aspectManager.register(container, pointcutManager);
} catch (Exception e) {
throw new WrappedRuntimeException(e);
}
}
/**
* Creates and registers the aspects defined.
*
* @param aspectManager the aspectManager for the system
* @param definition the AspectWerkz definition
*/
private static void registerPointcuts(final AspectManager aspectManager, final SystemDefinition definition) {
for (Iterator it = definition.getAspectDefinitions().iterator(); it.hasNext();) {
AspectDefinition aspectDef = (AspectDefinition) it.next();
if (aspectDef.getName().equals(CFlowSystemAspect.CLASS_NAME)) {
continue;
}
PointcutManager pointcutManager = aspectManager.getPointcutManager(aspectDef.getName());
for (Iterator it2 = aspectDef.getAroundAdvices().iterator(); it2.hasNext();) {
AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
Pointcut pointcut = pointcutManager.getPointcut(adviceDef.getExpressionInfo().getExpressionAsString());
if (pointcut == null) {
pointcut = new Pointcut(aspectManager, adviceDef.getExpressionInfo());
pointcutManager.addPointcut(pointcut);
}
pointcut.addAroundAdvice(aspectDef.getName() + '/' + adviceDef.getName());
}
for (Iterator it2 = aspectDef.getBeforeAdvices().iterator(); it2.hasNext();) {
AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
Pointcut pointcut = pointcutManager.getPointcut(adviceDef.getExpressionInfo().getExpressionAsString());
if (pointcut == null) {
pointcut = new Pointcut(aspectManager, adviceDef.getExpressionInfo());
pointcutManager.addPointcut(pointcut);
}
pointcut.addBeforeAdvice(aspectDef.getName() + '/' + adviceDef.getName());
}
for (Iterator it2 = aspectDef.getAfterAdvices().iterator(); it2.hasNext();) {
AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
Pointcut pointcut = pointcutManager.getPointcut(adviceDef.getExpressionInfo().getExpressionAsString());
if (pointcut == null) {
pointcut = new Pointcut(aspectManager, adviceDef.getExpressionInfo());
pointcutManager.addPointcut(pointcut);
}
if (adviceDef.getType().equals(AdviceType.AFTER) ||
adviceDef.getType().equals(AdviceType.AFTER_FINALLY)) {
pointcut.addAfterFinallyAdvices(aspectDef.getName() + '/' + adviceDef.getName());
}
if (adviceDef.getType().equals(AdviceType.AFTER_RETURNING)) {
pointcut.addAfterReturningAdvices(aspectDef.getName() + '/' + adviceDef.getName());
}
if (adviceDef.getType().equals(AdviceType.AFTER_THROWING)) {
pointcut.addAfterThrowingAdvices(aspectDef.getName() + '/' + adviceDef.getName());
}
}
}
}
/**
* Registers the cflow pointcuts.
*
* @param aspectManager the aspectManager for the system
* @param definition the AspectWerkz definition
*/
private static void registerCflowPointcuts(final AspectManager aspectManager, final SystemDefinition definition) {
// get all aspects to be able to get all poincuts defined
for (Iterator it1 = definition.getAspectDefinitions().iterator(); it1.hasNext();) {
AspectDefinition aspectDef = (AspectDefinition) it1.next();
PointcutManager pointcutManager = aspectManager.getPointcutManager(aspectDef.getName());
List cflowPointcuts = pointcutManager.getCflowPointcuts();
for (Iterator it2 = cflowPointcuts.iterator(); it2.hasNext();) {
Pointcut cflowPointcut = (Pointcut) it2.next();
ExpressionInfo expressionInfo = cflowPointcut.getExpressionInfo();
// register the cflow advices in the system and create the cflow system
// pointcutManager
// (if it does not already exist)
if (!aspectManager.hasAspect(CFlowSystemAspect.NAME)) {
AspectDefinition cflowAspectDef = new AspectDefinition(
CFlowSystemAspect.NAME,
CFlowSystemAspect.CLASS_NAME,
aspectManager.getUuid());
PointcutDefinition pointcutDef = new PointcutDefinition(expressionInfo.getExpressionAsString());
cflowAspectDef.setDeploymentModel(CFlowSystemAspect.DEPLOYMENT_MODEL);
cflowAspectDef.addPointcut(pointcutDef);
try {
AdviceDefinition beforeAdviceDefinition = new AdviceDefinition(
CFlowSystemAspect.PRE_ADVICE,
AdviceType.BEFORE,
null,
cflowAspectDef.getName(),
cflowAspectDef.getClassName(),
expressionInfo,
CFlowSystemAspect.class.getDeclaredMethod(CFlowSystemAspect.PRE_ADVICE, new Class[] {
JoinPoint.class
}),
CFlowSystemAspect.PRE_ADVICE_INDEX,
cflowAspectDef);
cflowAspectDef.addBeforeAdvice(beforeAdviceDefinition);
AdviceDefinition afterAdviceDefinition = new AdviceDefinition(
CFlowSystemAspect.POST_ADVICE,
AdviceType.AFTER_FINALLY,
null,
cflowAspectDef.getName(),
cflowAspectDef.getClassName(),
expressionInfo,
CFlowSystemAspect.class.getDeclaredMethod(CFlowSystemAspect.POST_ADVICE, new Class[] {
JoinPoint.class
}),
CFlowSystemAspect.POST_ADVICE_INDEX,
cflowAspectDef);
cflowAspectDef.addAfterAdvice(afterAdviceDefinition);
} catch (NoSuchMethodException e) {
; // TODO: why ignore exception? ALEX??
}
definition.addAspect(cflowAspectDef);
registerAspect(aspectManager, cflowAspectDef, new HashMap());
}
cflowPointcut.addBeforeAdvice(CFlowSystemAspect.NAME + '/' + CFlowSystemAspect.PRE_ADVICE);
cflowPointcut.addAfterFinallyAdvices(CFlowSystemAspect.NAME + '/' + CFlowSystemAspect.POST_ADVICE);
}
}
}
}