1 /*************************************************************************************** 2 * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. * 3 * http://aspectwerkz.codehaus.org * 4 * ---------------------------------------------------------------------------------- * 5 * The software in this package is published under the terms of the LGPL license * 6 * a copy of which has been included with this distribution in the license.txt file. * 7 **************************************************************************************/ 8 package org.codehaus.aspectwerkz.aspect; 9 10 import java.lang.reflect.InvocationTargetException; 11 import java.util.WeakHashMap; 12 import java.util.Map; 13 14 import org.codehaus.aspectwerkz.exception.DefinitionException; 15 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException; 16 import org.codehaus.aspectwerkz.DeploymentModel; 17 18 /*** 19 * Abstract base class for the mixin factory implementations. 20 * 21 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a> 22 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> 23 */ 24 public class DefaultMixinFactory extends AbstractMixinFactory { 25 26 private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; 27 28 private Object m_perJVM = null; 29 30 private Map m_perClassMixins = new WeakHashMap(); 31 32 private Map m_perInstanceMixins = new WeakHashMap(); 33 34 /*** 35 * Creates a new default mixin factory. 36 * 37 * @param mixinClass 38 * @param deploymentModel 39 */ 40 public DefaultMixinFactory(final Class mixinClass, final DeploymentModel deploymentModel) { 41 super(mixinClass, deploymentModel); 42 } 43 44 /*** 45 * Creates a new perJVM mixin instance. 46 * 47 * @return the mixin instance 48 */ 49 public Object mixinOf() { 50 if (m_perJVM != null) { 51 return m_perJVM; 52 } 53 synchronized (this) { 54 final Object mixin; 55 if (m_deploymentModel == DeploymentModel.PER_JVM) { 56 try { 57 mixin = m_defaultConstructor.newInstance(EMPTY_OBJECT_ARRAY); 58 } catch (InvocationTargetException e) { 59 throw new WrappedRuntimeException(e.getTargetException()); 60 } catch (Exception e) { 61 throw new WrappedRuntimeException(e); 62 } 63 } else { 64 throw new DefinitionException( 65 "Mixins.mixinOf() is can not be invoked for mixin deployed using as " + 66 m_deploymentModel 67 ); 68 } 69 m_perJVM = mixin; 70 } 71 return m_perJVM; 72 } 73 74 /*** 75 * Creates a new perClass mixin instance. 76 * 77 * @param klass 78 * @return the mixin instance 79 */ 80 public Object mixinOf(final Class klass) { 81 if (m_perClassMixins.containsKey(klass)) { 82 return m_perClassMixins.get(klass); 83 } 84 synchronized (m_perClassMixins) { 85 if (!m_perClassMixins.containsKey(klass)) { 86 final Object mixin; 87 if (m_deploymentModel == DeploymentModel.PER_CLASS) { 88 try { 89 if (m_perClassConstructor != null) { 90 mixin = m_perClassConstructor.newInstance(new Object[]{klass}); 91 } else if (m_defaultConstructor != null) { 92 mixin = m_defaultConstructor.newInstance(new Object[]{}); 93 } else { 94 throw new DefinitionException( 95 "no valid constructor found for mixin [" + m_mixinClass.getName() + "]" 96 ); 97 } 98 } catch (InvocationTargetException e) { 99 throw new WrappedRuntimeException(e.getTargetException()); 100 } catch (Exception e) { 101 throw new WrappedRuntimeException(e); 102 } 103 } else { 104 throw new DefinitionException( 105 "Mixins.mixinOf(Class) is can not be invoked for mixin deployed using as " + 106 m_deploymentModel 107 ); 108 } 109 m_perClassMixins.put(klass, mixin); 110 } 111 return m_perClassMixins.get(klass); 112 } 113 } 114 115 /*** 116 * Creates a new perInstance mixin instance. 117 * 118 * @param instance 119 * @return the mixin instance 120 */ 121 public Object mixinOf(final Object instance) { 122 if (m_perInstanceMixins.containsKey(instance)) { 123 return m_perInstanceMixins.get(instance); 124 } 125 synchronized (m_perInstanceMixins) { 126 if (!m_perInstanceMixins.containsKey(instance)) { 127 final Object mixin; 128 if (m_deploymentModel == DeploymentModel.PER_INSTANCE) { 129 try { 130 if (m_perInstanceConstructor != null) { 131 mixin = m_perInstanceConstructor.newInstance(new Object[]{instance}); 132 } else if (m_defaultConstructor != null) { 133 mixin = m_defaultConstructor.newInstance(new Object[]{}); 134 } else { 135 throw new DefinitionException( 136 "no valid constructor found for mixin [" + m_mixinClass.getName() + "]" 137 ); 138 } 139 } catch (InvocationTargetException e) { 140 throw new WrappedRuntimeException(e.getTargetException()); 141 } catch (Exception e) { 142 throw new WrappedRuntimeException(e); 143 } 144 } else { 145 throw new DefinitionException( 146 "Mixins.mixinOf(Object) is can not be invoked for mixin deployed using as " + 147 m_deploymentModel 148 ); 149 } 150 m_perInstanceMixins.put(instance, mixin); 151 } 152 return m_perInstanceMixins.get(instance); 153 } 154 } 155 }