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;
9
10 import org.codehaus.aspectwerkz.aspect.AspectContainer;
11 import org.codehaus.aspectwerkz.definition.AspectDefinition;
12 import org.codehaus.aspectwerkz.definition.StartupManager;
13 import org.codehaus.aspectwerkz.exception.DefinitionException;
14
15 import java.io.ObjectInputStream;
16 import java.io.Serializable;
17 import java.util.HashMap;
18 import java.util.Map;
19
20 /***
21 * Contains information about and for classes that has been defined as cross-cutting.
22 *
23 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
24 */
25 public final class CrossCuttingInfo implements Serializable {
26 /***
27 * An empty <code>Object</code> array.
28 */
29 public static final Object[] EMPTY_OBJECT_ARRAY = new Object[] {};
30
31 /***
32 * The name for the cross-cuttable class.
33 */
34 private String m_name;
35
36 /***
37 * The cross-cuttable class.
38 */
39 private Class m_aspectClass;
40
41 /***
42 * The container.
43 */
44 private transient AspectContainer m_container = null;
45
46 /***
47 * Holds the deployment model.
48 */
49 private int m_deploymentModel;
50
51 /***
52 * Holds the parameters passed to the aspect.
53 */
54 private Map m_parameters = new HashMap();
55
56 /***
57 * Holds the metadata.
58 */
59 private Map m_metaData = new HashMap();
60
61 /***
62 * The UUID for the system.
63 */
64 private String m_uuid;
65
66 /***
67 * A reference to the AspectWerkz system housing this cross-cuttable class.
68 */
69 private transient AspectSystem m_system;
70
71 /***
72 * The aspect definition.
73 */
74 private transient AspectDefinition m_aspectDefinition;
75
76 /***
77 * Creates a new cross-cutting info instance.
78 *
79 * @param uuid
80 * @param aspectClass
81 * @param deploymentModel
82 * @param aspectDef
83 * @param parameters
84 */
85 public CrossCuttingInfo(final String uuid,
86 final Class aspectClass,
87 final String name,
88 final int deploymentModel,
89 final AspectDefinition aspectDef,
90 final Map parameters) {
91 m_uuid = uuid;
92 m_aspectClass = aspectClass;
93 m_name = name;
94 m_deploymentModel = deploymentModel;
95 m_aspectDefinition = aspectDef;
96 m_parameters = parameters;
97 }
98
99 /***
100 * Copy constructor - creates a clone of the cross-cutting info. Creates a new instance of the cross-cutting class
101 * it holds.
102 *
103 * @return a clone of the cross-cutting info
104 */
105 public static CrossCuttingInfo newInstance(final CrossCuttingInfo prototype) {
106 try {
107 return new CrossCuttingInfo(
108 prototype.m_uuid,
109 prototype.m_aspectClass,
110 prototype.m_name,
111 prototype.m_deploymentModel,
112 prototype.m_aspectDefinition,
113 prototype.m_parameters);
114 } catch (Exception e) {
115 throw new RuntimeException("could not clone cross-cutting info ["
116 + prototype.getName()
117 + "]: "
118 + e.toString());
119 }
120 }
121
122 /***
123 * Returns the AspectWerkz system housing this cross-cuttable class.
124 *
125 * @return the system
126 */
127 public AspectSystem getSystem() {
128 if (m_system == null) {
129 m_system = SystemLoader.getSystem(getAspectClass());
130 m_system.initialize();
131 }
132 return m_system;
133 }
134
135 /***
136 * Returns the UUID for the system.
137 *
138 * @return the UUID for the system
139 */
140 public String getUuid() {
141 return m_uuid;
142 }
143
144 /***
145 * Returns the name of the aspect.
146 *
147 * @return the name of the aspect
148 */
149 public String getName() {
150 return m_name;
151 }
152
153 /***
154 * Returns the deployment model.
155 *
156 * @return the deployment model
157 */
158 public int getDeploymentModel() {
159 return m_deploymentModel;
160 }
161
162 /***
163 * Changes the deployment model.
164 *
165 * @param deploymentModel the new deployment model
166 */
167 public void setDeploymentModel(final int deploymentModel) {
168 m_deploymentModel = deploymentModel;
169 }
170
171 /***
172 * Returns the cross-cuttable class.
173 *
174 * @return the cross-cuttable class
175 */
176 public Class getAspectClass() {
177 return m_aspectClass;
178 }
179
180 /***
181 * Sets the container.
182 *
183 * @param container the container
184 */
185 public void setContainer(final AspectContainer container) {
186 m_container = container;
187 }
188
189 /***
190 * Returns the container.
191 *
192 * @return the container
193 */
194 public AspectContainer getContainer() {
195 return m_container;
196 }
197
198 /***
199 * Returns the aspect definition.
200 * <p/>
201 * Will return null after deserialization.
202 *
203 * @return the aspect definition
204 */
205 public AspectDefinition getAspectDefinition() {
206 return m_aspectDefinition;
207 }
208
209 /***
210 * Sets a parameter.
211 *
212 * @param name the name of the parameter
213 * @param value the value of the parameter
214 */
215 public void setParameter(final String name, final String value) {
216 m_parameters.put(name, value);
217 }
218
219 /***
220 * Returns the value of a parameter.
221 *
222 * @param name the name of the parameter
223 * @return the value of the parameter or null if not found
224 */
225 public String getParameter(final String name) {
226 return (String) m_parameters.get(name);
227 }
228
229 /***
230 * Adds metadata.
231 *
232 * @param key the key
233 * @param value the value
234 */
235 public void addMetaData(final Object key, final Object value) {
236 m_metaData.put(key, value);
237 }
238
239 /***
240 * Returns the metadata for a specific key.
241 *
242 * @param key the key
243 * @return the value
244 */
245 public Object getMetaData(final Object key) {
246 return m_metaData.get(key);
247 }
248
249 /***
250 * Returns the target instance for the mixin of given name which is defined from within this aspect (mixin can have
251 * different deployment model from aspect)
252 *
253 * @param mixinImpl miximImplementation aka "this" when called from within the mixin impl
254 * @return the target instance or null if not compliant deployment model
255 */
256 public Object getMixinTargetInstance(final Object mixinImpl) {
257 return getMixinTargetInstance(mixinImpl.getClass().getName(), mixinImpl);
258 }
259
260 /***
261 * Returns the target class for the mixin of given name which is defined from within this aspect (mixin can have
262 * different deployment model from aspect)
263 *
264 * @param mixinImpl miximImplementation aka "this" when called from within the mixin impl
265 * @return the target class or null if not compliant deployment model
266 */
267 public Class getMixinTargetClass(final Object mixinImpl) {
268 return getMixinTargetClass(mixinImpl.getClass().getName(), mixinImpl);
269 }
270
271 /***
272 * Returns the target instance for the mixin of given name which is defined from within this aspect (mixin can have
273 * different deployment model from aspect)
274 *
275 * @param mixinName of the mixin
276 * @param mixinImpl miximImplementation aka "this" when called from within the mixin impl
277 * @return the target instance or null if not compliant deployment model
278 */
279 public Object getMixinTargetInstance(final String mixinName, final Object mixinImpl) {
280 return m_container.getIntroductionContainer(mixinName).getTargetInstance(mixinImpl);
281 }
282
283 /***
284 * Returns the target class for the mixin of given name which is defined from within this aspect (mixin can have
285 * different deployment model from aspect)
286 *
287 * @param mixinName of the mixin
288 * @param mixinImpl miximImplementation aka "this" when called from within the mixin impl
289 * @return the target class or null if not compliant deployment model
290 */
291 public Class getMixinTargetClass(final String mixinName, final Object mixinImpl) {
292 return m_container.getIntroductionContainer(mixinName).getTargetClass(mixinImpl);
293 }
294
295 /***
296 * Return true if the CrossCuttingInfo has not yet the AspectContainer set, that means this is the prototype init
297 * time
298 */
299 public boolean isPrototype() {
300 return (m_container == null);
301 }
302
303 /***
304 * Provides custom deserialization.
305 *
306 * @param stream the object input stream containing the serialized object
307 * @throws Exception in case of failure
308 */
309 private void readObject(final ObjectInputStream stream) throws Exception {
310 ObjectInputStream.GetField fields = stream.readFields();
311 m_uuid = (String) fields.get("m_uuid", null);
312 m_name = (String) fields.get("m_name", null);
313 m_aspectClass = (Class) fields.get("m_aspectClass", null);
314 m_deploymentModel = fields.get("m_deploymentModel", DeploymentModel.PER_JVM);
315 m_parameters = (Map) fields.get("m_parameters", new HashMap());
316 m_metaData = (Map) fields.get("m_metaData", new HashMap());
317 m_container = StartupManager.createAspectContainer(this);
318 m_system = SystemLoader.getSystem(m_aspectClass);
319 m_system.initialize();
320 }
321 }