/* */ package org.jboss.aop.instrument;
/* */
/* */ import java.util.Collection;
/* */ import java.util.HashMap;
/* */ import java.util.Iterator;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */ import javassist.CannotCompileException;
/* */ import javassist.CodeConverter;
/* */ import javassist.CtClass;
/* */ import javassist.CtConstructor;
/* */ import javassist.CtField.Initializer;
/* */ import javassist.CtMember;
/* */ import javassist.CtMethod;
/* */ import javassist.CtNewMethod;
/* */ import javassist.NotFoundException;
/* */ import javassist.bytecode.MethodInfo;
/* */ import javassist.bytecode.SignatureAttribute;
/* */ import org.jboss.aop.AspectManager;
/* */ import org.jboss.aop.ClassAdvisor;
/* */ import org.jboss.aop.pointcut.Pointcut;
/* */ import org.jboss.aop.util.logging.AOPLogger;
/* */ import org.jboss.logging.Logger;
/* */
/* */ public abstract class ConstructorExecutionTransformer
/* */ implements CodeConversionObserver
/* */ {
/* 55 */ private static final Logger logger = AOPLogger.getLogger(ConstructorExecutionTransformer.class);
/* */ protected static final String CONSTRUCTOR_INFO_CLASS_NAME = "org.jboss.aop.ConstructorInfo";
/* */ protected Instrumentor instrumentor;
/* */ protected Codifier codifier;
/* */ private JoinpointClassifier classifier;
/* 63 */ private static final WrapperTransformer wrapper = new WrapperTransformer(new String[] { "wrapperStatus", "constructorsWrapped" });
/* */ protected static final int CONSTRUCTOR_STATUS = 0;
/* */ private static final int ALL_CONSTRUCTORS_STATUS = 1;
/* */
/* */ protected ConstructorExecutionTransformer(Instrumentor instrumentor)
/* */ {
/* 70 */ this.instrumentor = instrumentor;
/* 71 */ this.codifier = new Codifier();
/* 72 */ this.classifier = instrumentor.joinpointClassifier;
/* */ }
/* */
/* */ protected Instrumentor getInstrumentor()
/* */ {
/* 78 */ return this.instrumentor;
/* */ }
/* */
/* */ protected WrapperTransformer getWrapper()
/* */ {
/* 83 */ return wrapper;
/* */ }
/* */
/* */ public static String constructorFactory(String className)
/* */ {
/* 88 */ if (className.indexOf('.') >= 0) throw new RuntimeException("constructorFactory() takes a simple class name: " + className);
/* 89 */ return className + "_new_" + "$aop";
/* */ }
/* */
/* */ protected String addConstructorInfoField(int modifiers, CtClass addTo, String infoName)
/* */ throws NotFoundException, CannotCompileException
/* */ {
/* 97 */ return addConstructorInfoField(modifiers, addTo, infoName, null);
/* */ }
/* */
/* */ protected String addConstructorInfoField(int modifiers, CtClass addTo, String infoName, CtField.Initializer init)
/* */ throws NotFoundException, CannotCompileException
/* */ {
/* 107 */ if (this.instrumentor.getClassPool() != null)
/* */ {
/* */ try
/* */ {
/* 111 */ addTo.getDeclaredField(infoName);
/* 112 */ return infoName;
/* */ }
/* */ catch (NotFoundException e)
/* */ {
/* 117 */ TransformerCommon.addInfoField(this.instrumentor, "org.jboss.aop.ConstructorInfo", infoName, modifiers, addTo, addInfoAsWeakReference(), init);
/* */ }
/* */ }
/* 120 */ return infoName;
/* */ }
/* */
/* */ protected boolean addInfoAsWeakReference()
/* */ {
/* 125 */ return true;
/* */ }
/* */
/* */ public static String getConstructorInfoFieldName(String classname, int index)
/* */ {
/* 130 */ if (classname.indexOf('.') >= 0) throw new RuntimeException("Simple name should be used: " + classname);
/* 131 */ return "aop$constructorInfo_" + index;
/* */ }
/* */
/* */ protected static String constructorInfoFromWeakReference(String localName, String ctorInfoName)
/* */ {
/* 136 */ return TransformerCommon.infoFromWeakReference("org.jboss.aop.ConstructorInfo", localName, ctorInfoName);
/* */ }
/* */
/* */ public boolean transform(CtClass clazz, ClassAdvisor classAdvisor)
/* */ throws Exception
/* */ {
/* 148 */ List constructors = this.instrumentor.getConstructors(clazz);
/* 149 */ boolean wrappersGenerated = false;
/* 150 */ boolean oneOrMoreWrapped = false;
/* 151 */ int i = 0;
/* 152 */ boolean dynamicallyWrapped = false;
/* 153 */ boolean notDynamicallyWrapped = false;
/* 154 */ CtConstructor firstConstructor = null;
/* 155 */ if (!constructors.isEmpty())
/* */ {
/* 157 */ firstConstructor = (CtConstructor)constructors.get(0);
/* */ }
/* 159 */ if (constructors.size() > 0)
/* */ {
/* 161 */ for (Iterator iterator = constructors.iterator(); iterator.hasNext(); i++)
/* */ {
/* 163 */ CtConstructor constructor = (CtConstructor)iterator.next();
/* */
/* 165 */ JoinpointClassification classification = this.classifier.classifyConstructorExecution(constructor, classAdvisor);
/* */
/* 167 */ if ((classification == JoinpointClassification.NOT_INSTRUMENTED) && (!oneOrMoreWrapped))
/* */ {
/* */ continue;
/* */ }
/* */
/* 172 */ if (!wrappersGenerated)
/* */ {
/* 175 */ buildConstructorWrappers(clazz, classAdvisor);
/* 176 */ wrappersGenerated = true;
/* 177 */ wrapper.prepareForWrapping(firstConstructor, 1);
/* */ }
/* */
/* 180 */ if (classification.equals(JoinpointClassification.WRAPPED))
/* */ {
/* 182 */ if (!oneOrMoreWrapped)
/* */ {
/* 184 */ for (int j = 0; j < i; j++)
/* */ {
/* 186 */ setEmptyWrapperCodeLater((CtConstructor)constructors.get(j));
/* */ }
/* 188 */ oneOrMoreWrapped = true;
/* */ }
/* 190 */ wrap(clazz, constructor, i);
/* 191 */ dynamicallyWrapped = (dynamicallyWrapped) || (classification.equals(JoinpointClassification.DYNAMICALY_WRAPPED));
/* 192 */ notDynamicallyWrapped = (notDynamicallyWrapped) || (!classification.equals(JoinpointClassification.DYNAMICALY_WRAPPED));
/* */ } else {
/* 194 */ if (!oneOrMoreWrapped)
/* */ continue;
/* 196 */ setEmptyWrapperCodeLater(constructor);
/* */ }
/* */ }
/* */ }
/* */
/* 201 */ if (oneOrMoreWrapped)
/* */ {
/* 203 */ wrapAllConstructors(clazz, firstConstructor, null);
/* */ }
/* 205 */ if ((dynamicallyWrapped) && (!notDynamicallyWrapped))
/* */ {
/* 207 */ this.instrumentor.dynamicTransformationObserver.constructorDynamicalyWrapped();
/* */ }
/* 209 */ return wrappersGenerated;
/* */ }
/* */
/* */ private void wrapAllConstructors(CtClass clazz, CtConstructor firstConstructor, List constructors)
/* */ throws NotFoundException, CannotCompileException
/* */ {
/* 229 */ wrapper.wrap(firstConstructor, 1);
/* 230 */ if (constructors == null)
/* */ {
/* 232 */ return;
/* */ }
/* 234 */ for (Iterator i = constructors.iterator(); i.hasNext(); )
/* */ {
/* 236 */ CtConstructor constructor = (CtConstructor)i.next();
/* 237 */ if (!wrapper.isWrapped(constructor, 0))
/* */ {
/* 239 */ setEmptyWrapperCodeLater(constructor);
/* */ }
/* */ }
/* 242 */ this.instrumentor.converter.replaceNew(clazz, clazz, constructorFactory(clazz.getSimpleName()));
/* */ }
/* */
/* */ public void wrap(CtClass clazz, Collection constructorIndexes)
/* */ throws Exception
/* */ {
/* 253 */ List constructors = this.instrumentor.getConstructors(clazz);
/* */
/* 255 */ CtConstructor firstConstructor = (CtConstructor)constructors.get(0);
/* 256 */ if (wrapper.isNotPrepared(firstConstructor, 1))
/* */ {
/* 258 */ return;
/* */ }
/* */
/* 261 */ for (Iterator iterator = constructorIndexes.iterator(); iterator.hasNext(); )
/* */ {
/* 263 */ int constructorIndex = ((Integer)iterator.next()).intValue();
/* 264 */ CtConstructor constructor = (CtConstructor)constructors.get(constructorIndex);
/* 265 */ wrap(clazz, constructor, constructorIndex);
/* */ }
/* */
/* 269 */ if (!wrapper.isWrapped(firstConstructor, 1))
/* */ {
/* 271 */ wrapAllConstructors(clazz, firstConstructor, constructors);
/* */ }
/* */ }
/* */
/* */ private void wrap(CtClass clazz, CtConstructor constructor, int constructorIndex)
/* */ throws NotFoundException, Exception, CannotCompileException
/* */ {
/* 284 */ if (wrapper.isNotPrepared(constructor, 0))
/* */ {
/* 286 */ return;
/* */ }
/* */
/* 289 */ wrapper.wrap(constructor, 0);
/* */
/* 291 */ CtMethod wrapperMethod = clazz.getDeclaredMethod(constructorFactory(clazz.getSimpleName()), constructor.getParameterTypes());
/* 292 */ setTemporaryWrapperCode(constructor.getDeclaringClass(), wrapperMethod);
/* 293 */ ConstructorTransformation trans = new ConstructorTransformation(clazz, constructor, wrapperMethod, constructorIndex);
/* 294 */ createWrapper(trans);
/* */ }
/* */
/* */ public void unwrap(CtClass clazz, Collection constructorIndexes)
/* */ throws NotFoundException
/* */ {
/* 305 */ List constructors = this.instrumentor.getConstructors(clazz);
/* */
/* 307 */ if (wrapper.isNotPrepared((CtMember)constructors.get(0), 1))
/* */ {
/* 309 */ return;
/* */ }
/* 311 */ for (Iterator iterator = constructorIndexes.iterator(); iterator.hasNext(); )
/* */ {
/* 313 */ int constructorIndex = ((Integer)iterator.next()).intValue();
/* 314 */ CtConstructor constructor = (CtConstructor)constructors.get(constructorIndex);
/* 315 */ if (wrapper.isNotPrepared(constructor, 0))
/* */ {
/* */ continue;
/* */ }
/* */
/* 320 */ wrapper.unwrap(constructor, 0);
/* */
/* 323 */ setEmptyWrapperCode(constructor);
/* */ }
/* */ }
/* */
/* */ public void codeConverted()
/* */ throws CannotCompileException
/* */ {
/* 332 */ this.codifier.codifyPending();
/* */ }
/* */
/* */ public boolean replaceConstructorAccess(ClassAdvisor sourceAdvisor, CtClass source) throws NotFoundException
/* */ {
/* 337 */ if (!isAnyConstructorAdvised(source, sourceAdvisor))
/* */ {
/* 339 */ return false;
/* */ }
/* 341 */ this.instrumentor.converter.replaceNew(source, source, constructorFactory(source.getSimpleName()));
/* 342 */ return true;
/* */ }
/* */
/* */ protected void buildConstructorWrappers(CtClass clazz, ClassAdvisor advisor)
/* */ throws Exception
/* */ {
/* 349 */ this.instrumentor.setupBasics(clazz);
/* 350 */ List constructors = this.instrumentor.getConstructors(clazz);
/* */
/* 352 */ Iterator it = constructors.iterator();
/* 353 */ for (int index = 0; it.hasNext(); index++)
/* */ {
/* 356 */ CtConstructor constructor = (CtConstructor)it.next();
/* 357 */ int mod = 8;
/* 358 */ if ((constructor.getModifiers() & 0x1) != 0)
/* */ {
/* 360 */ mod |= 1;
/* */ }
/* 362 */ else if ((constructor.getModifiers() & 0x4) != 0)
/* */ {
/* 364 */ mod |= 4;
/* */ }
/* 366 */ else if ((constructor.getModifiers() & 0x2) != 0)
/* */ {
/* 368 */ mod |= 2;
/* */ }
/* */ else
/* */ {
/* 372 */ mod |= 1;
/* */ }
/* */
/* 375 */ initialiseWrapper(mod, constructor, index);
/* 376 */ generateConstructorInfoField(clazz, constructor, index);
/* */ }
/* */ }
/* */
/* */ protected void generateConstructorInfoField(CtClass clazz, CtConstructor constructor, int index) throws CannotCompileException, NotFoundException
/* */ {
/* 382 */ String name = getConstructorInfoFieldName(clazz.getSimpleName(), index);
/* 383 */ addConstructorInfoField(10, clazz, name);
/* */ }
/* */
/* */ protected void setTemporaryWrapperCode(CtClass type, CtMethod wrapperMethod)
/* */ {
/* 394 */ String code = "{ return null;}";
/* */ try
/* */ {
/* 399 */ wrapperMethod.setBody(code);
/* */ }
/* */ catch (CannotCompileException e)
/* */ {
/* 403 */ logger.error("Cannot compile " + code);
/* 404 */ throw new RuntimeException(e);
/* */ }
/* */ }
/* */
/* */ protected void setEmptyWrapperCode(CtConstructor constructor)
/* */ throws NotFoundException
/* */ {
/* 416 */ CtMethod wrapperMethod = getWrapperMethod(constructor);
/* 417 */ String code = "{ return new " + constructor.getDeclaringClass().getName() + "($$); " + "}";
/* */ try
/* */ {
/* 423 */ wrapperMethod.setBody(code);
/* */ }
/* */ catch (CannotCompileException e)
/* */ {
/* 427 */ logger.error("Cannot compile " + code);
/* 428 */ throw new RuntimeException(e);
/* */ }
/* */ }
/* */
/* */ protected void setEmptyWrapperCodeLater(CtConstructor constructor)
/* */ throws NotFoundException
/* */ {
/* 441 */ CtMethod wrapperMethod = getWrapperMethod(constructor);
/* 442 */ String code = "{ return new " + constructor.getDeclaringClass().getName() + "($$); " + "}";
/* */
/* 446 */ this.codifier.addPendingCode(wrapperMethod, code);
/* */ }
/* */
/* */ protected boolean isAnyConstructorAdvised(CtClass clazz, ClassAdvisor advisor)
/* */ throws NotFoundException
/* */ {
/* 459 */ CtConstructor[] constructors = clazz.getDeclaredConstructors();
/* 460 */ for (int i = 0; i < constructors.length; i++)
/* */ {
/* 462 */ JoinpointClassification classification = this.classifier.classifyConstructorExecution(constructors[i], advisor);
/* 463 */ if (classification.equals(JoinpointClassification.WRAPPED))
/* 464 */ return true;
/* */ }
/* 466 */ return false;
/* */ }
/* */
/* */ public static boolean isAdvisableConstructor(CtConstructor con, ClassAdvisor advisor)
/* */ throws NotFoundException
/* */ {
/* 472 */ Map pointcuts = advisor.getManager().getPointcuts();
/* 473 */ synchronized (pointcuts)
/* */ {
/* 475 */ Iterator it = pointcuts.values().iterator();
/* 476 */ while (it.hasNext())
/* */ {
/* 478 */ Pointcut pointcut = (Pointcut)it.next();
/* 479 */ if (pointcut.matchesExecution(advisor, con))
/* */ {
/* 481 */ return true;
/* */ }
/* */ }
/* */ }
/* 485 */ return false;
/* */ }
/* */
/* */ protected abstract void createWrapper(ConstructorTransformation paramConstructorTransformation) throws CannotCompileException, NotFoundException;
/* */
/* */ protected void initialiseWrapper(int mod, CtConstructor constructor, int index) throws NotFoundException, CannotCompileException {
/* 492 */ CtClass clazz = constructor.getDeclaringClass();
/* 493 */ CtClass[] exceptions = constructor.getExceptionTypes();
/* 494 */ String name = clazz.getSimpleName();
/* 495 */ CtClass type = constructor.getDeclaringClass();
/* */
/* 497 */ CtMethod wmethod = CtNewMethod.make(type, constructorFactory(name), constructor.getParameterTypes(), exceptions, null, clazz);
/* 498 */ wmethod.setModifiers(mod);
/* 499 */ setTemporaryWrapperCode(type, wmethod);
/* 500 */ clazz.addMethod(wmethod);
/* */
/* 503 */ MethodInfo constructorInfo = constructor.getMethodInfo2();
/* 504 */ SignatureAttribute attribute = (SignatureAttribute)constructorInfo.getAttribute("Signature");
/* 505 */ if (attribute != null)
/* */ {
/* 507 */ MethodInfo wrapperInfo = wmethod.getMethodInfo2();
/* 508 */ wrapperInfo.addAttribute(attribute.copy(wrapperInfo.getConstPool(), new HashMap()));
/* */ }
/* */
/* 512 */ getWrapper().prepareForWrapping(constructor, 0);
/* */ }
/* */
/* */ protected CtMethod getWrapperMethod(CtConstructor constructor) throws NotFoundException
/* */ {
/* 517 */ CtClass clazz = constructor.getDeclaringClass();
/* 518 */ return clazz.getDeclaredMethod(constructorFactory(clazz.getSimpleName()), constructor.getParameterTypes());
/* */ }
/* */
/* */ protected class ConstructorTransformation {
/* */ CtClass clazz;
/* */ CtConstructor constructor;
/* */ CtMethod wrapperMethod;
/* */ int index;
/* */
/* */ public ConstructorTransformation(CtClass clazz, CtConstructor constructor, CtMethod wrapper, int index) {
/* 532 */ this.clazz = clazz;
/* 533 */ this.constructor = constructor;
/* 534 */ this.wrapperMethod = wrapper;
/* 535 */ this.index = index;
/* */ }
/* */
/* */ public CtMethod getWrapperMethod()
/* */ {
/* 540 */ return this.wrapperMethod;
/* */ }
/* */
/* */ public void setWrapperMethod(CtMethod wrapperMethod)
/* */ {
/* 545 */ this.wrapperMethod = wrapperMethod;
/* */ }
/* */
/* */ public CtClass getClazz()
/* */ {
/* 550 */ return this.clazz;
/* */ }
/* */
/* */ public CtConstructor getConstructor()
/* */ {
/* 555 */ return this.constructor;
/* */ }
/* */
/* */ public int getIndex()
/* */ {
/* 560 */ return this.index;
/* */ }
/* */
/* */ public String getClassName()
/* */ {
/* 565 */ return this.clazz.getName();
/* */ }
/* */
/* */ public String getSimpleName()
/* */ {
/* 570 */ return this.clazz.getSimpleName();
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.aop.instrument.ConstructorExecutionTransformer
* JD-Core Version: 0.6.0
*/