001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.aspect;
008:
009: import java.util.HashMap;
010: import java.util.Map;
011: import java.util.WeakHashMap;
012:
013: import org.codehaus.aspectwerkz.AspectContext;
014:
015: /**
016: * Abstract base class for the aspect container implementations.
017: *
018: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
019: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
020: * @TODO: allow any type of constructor, to support ctor based dependency injection
021: */
022: public abstract class AbstractAspectContainer implements
023: AspectContainer {
024:
025: public static final int ASPECT_CONSTRUCTION_TYPE_UNKNOWN = 0;
026: public static final int ASPECT_CONSTRUCTION_TYPE_DEFAULT = 1;
027: public static final int ASPECT_CONSTRUCTION_TYPE_ASPECT_CONTEXT = 2;
028: public static final Object[] EMPTY_OBJECT_ARRAY = new Object[] {};
029:
030: /**
031: * An array with the single aspect context, needed to save one array creation per invocation.
032: */
033: protected final Object[] ARRAY_WITH_SINGLE_ASPECT_CONTEXT = new Object[1];
034:
035: /**
036: * The aspect construction type.
037: */
038: protected int m_constructionType = ASPECT_CONSTRUCTION_TYPE_UNKNOWN;
039:
040: /**
041: * The aspect context prototype.
042: */
043: protected final AspectContext m_aspectContext;
044:
045: /**
046: * Holds a reference to the sole per JVM aspect instance.
047: */
048: protected Object m_perJvm;
049:
050: /**
051: * Holds references to the per class aspect instances.
052: */
053: protected final Map m_perClass = new WeakHashMap();
054:
055: /**
056: * Holds references to the per instance aspect instances.
057: */
058: protected final Map m_perInstance = new WeakHashMap();
059:
060: /**
061: * Holds references to the per thread aspect instances.
062: */
063: protected final Map m_perThread = new WeakHashMap();
064:
065: /**
066: * Maps the advice infos to the hash codes of the the matching advice method.
067: */
068: protected final Map m_adviceInfos = new HashMap();
069:
070: /**
071: * Creates a new aspect container strategy.
072: *
073: * @param aspectContext the context
074: */
075: public AbstractAspectContainer(final AspectContext aspectContext) {
076: if (aspectContext == null) {
077: throw new IllegalArgumentException(
078: "cross-cutting info can not be null");
079: }
080:
081: m_aspectContext = aspectContext;
082: ARRAY_WITH_SINGLE_ASPECT_CONTEXT[0] = m_aspectContext;
083: }
084:
085: /**
086: * Returns the context.
087: *
088: * @return the context
089: */
090: public AspectContext getContext() {
091: return m_aspectContext;
092: }
093:
094: /**
095: * asm
096: * Creates a new perJVM cross-cutting instance, if it already exists then return it.
097: *
098: * @return the cross-cutting instance
099: */
100: public Object aspectOf() {
101: if (m_perJvm == null) {
102: m_perJvm = createAspect();
103: }
104: return m_perJvm;
105: }
106:
107: /**
108: * Creates a new perClass cross-cutting instance, if it already exists then return it.
109: *
110: * @param klass
111: * @return the cross-cutting instance
112: */
113: public Object aspectOf(final Class klass) {
114: synchronized (m_perClass) {
115: if (!m_perClass.containsKey(klass)) {
116: m_perClass.put(klass, createAspect());
117: }
118: }
119: return m_perClass.get(klass);
120: }
121:
122: /**
123: * Creates a new perInstance cross-cutting instance, if it already exists then return it.
124: *
125: * @param instance
126: * @return the cross-cutting instance
127: */
128: public Object aspectOf(final Object instance) {
129: synchronized (m_perInstance) {
130: if (!m_perInstance.containsKey(instance)) {
131: m_perInstance.put(instance, createAspect());
132: }
133: }
134: return m_perInstance.get(instance);
135: }
136:
137: /**
138: * Creates a new perThread cross-cutting instance, if it already exists then return it.
139: *
140: * @param thread the thread for the aspect
141: * @return the cross-cutting instance
142: */
143: public Object aspectOf(final Thread thread) {
144: synchronized (m_perThread) {
145: if (!m_perThread.containsKey(thread)) {
146: m_perThread.put(thread, createAspect());
147: }
148: }
149: return m_perThread.get(thread);
150: }
151:
152: /**
153: * To be implemented by the concrete aspect containers. <p/>Should return a new aspect instance.
154: *
155: * @return a new aspect instance
156: */
157: protected abstract Object createAspect();
158: }
|