001: /* ====================================================================
002: The Jicarilla Software License
003:
004: Copyright (c) 2003 Leo Simons.
005: All rights reserved.
006:
007: Permission is hereby granted, free of charge, to any person obtaining
008: a copy of this software and associated documentation files (the
009: "Software"), to deal in the Software without restriction, including
010: without limitation the rights to use, copy, modify, merge, publish,
011: distribute, sublicense, and/or sell copies of the Software, and to
012: permit persons to whom the Software is furnished to do so, subject to
013: the following conditions:
014:
015: The above copyright notice and this permission notice shall be
016: included in all copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
021: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
022: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
023: TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
024: SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
025: ==================================================================== */
026: package org.jicarilla.container;
027:
028: import org.jicarilla.container.adapters.AdapterBasedKeyAwareAdapter;
029: import org.jicarilla.container.adapters.ResolverBasedAdapter;
030: import org.jicarilla.container.adapters.ResolverBasedKeyAwareAdapter;
031: import org.jicarilla.container.adapters.SingletonAdapter;
032: import org.jicarilla.container.factories.ManualFactory;
033: import org.jicarilla.container.util.PolicyUtil;
034: import org.jicarilla.lang.Assert;
035: import org.jicarilla.lang.Selector;
036:
037: import java.util.HashMap;
038: import java.util.Map;
039:
040: /**
041: * <p>A rather complex implementation of the {@link Resolver} interface that
042: * is backed by another {@link Resolver}, and can be used to override some of
043: * the container's autowiring policy.</p>
044: *
045: * <p>You will normally not want to create instances of this class directly.
046: * Rather, feed {@link org.jicarilla.container.builder.CustomComponent}s to
047: * a {@link org.jicarilla.container.builder.Builder} instance and let the
048: * builder worry about that.</p>
049: *
050: * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
051: * @version $Id: DefaultCustomizableResolver.java,v 1.2 2004/03/23 15:59:52 lsimons Exp $
052: */
053: public class DefaultCustomizableResolver implements
054: CustomizableResolver {
055: // ----------------------------------------------------------------------
056: // Properties
057: // ----------------------------------------------------------------------
058: protected Resolver m_delegate;
059: protected Container m_overrides;
060: protected int m_getCallCount;
061: protected Map m_getCallOverrides;
062:
063: protected Map m_instanceToAdapterMap;
064:
065: // ----------------------------------------------------------------------
066: // Constructors
067: // ----------------------------------------------------------------------
068: public DefaultCustomizableResolver(Resolver delegate) {
069: this (delegate, new DefaultKeyRelayingContainer());
070: }
071:
072: public DefaultCustomizableResolver(Resolver delegate,
073: Container overrides) {
074: this (delegate, overrides, new HashMap());
075: }
076:
077: public DefaultCustomizableResolver(Resolver delegate,
078: Container overrides, Map getCallOverrides) {
079: Assert.assertNotNull("delegate argument may not be null",
080: delegate);
081: Assert.assertNotNull("overrides argument may not be null",
082: overrides);
083: Assert.assertNotNull(
084: "getCallOverrides argument may not be null",
085: getCallOverrides);
086:
087: m_delegate = delegate;
088: m_overrides = overrides;
089: m_getCallOverrides = getCallOverrides;
090:
091: m_getCallCount = -1;
092:
093: m_instanceToAdapterMap = new HashMap();
094: }
095:
096: // ----------------------------------------------------------------------
097: // Interface: Resolver
098: // ----------------------------------------------------------------------
099: public Object get(Object key) throws ResolutionException,
100: JicarillaIllegalAccessException,
101: JicarillaInvocationTargetException,
102: JicarillaInstantiationException,
103: JicarillaClassNotFoundException, InitializationException,
104: JicarillaException {
105: m_getCallCount++;
106: final Integer count = new Integer(m_getCallCount);
107:
108: Object instance = null;
109: Object adapter = null;
110:
111: if (m_getCallOverrides.containsKey(count)) {
112: Adapter a = (Adapter) m_getCallOverrides.get(count);
113: instance = a.getInstance();
114: adapter = new AdapterBasedKeyAwareAdapter(a);
115: } else if (m_overrides.getResolver().contains(key)) {
116: instance = m_overrides.getResolver().get(key);
117: adapter = new ResolverBasedKeyAwareAdapter(m_overrides
118: .getResolver());
119: } else {
120: instance = m_delegate.get(key);
121: adapter = new ResolverBasedKeyAwareAdapter(m_delegate);
122: }
123:
124: m_instanceToAdapterMap.put(instance, adapter);
125:
126: return instance;
127: }
128:
129: public Object[] getAll(Object key)
130: throws JicarillaIllegalAccessException,
131: JicarillaInvocationTargetException,
132: JicarillaInstantiationException,
133: JicarillaClassNotFoundException, InitializationException,
134: JicarillaException {
135: if (m_overrides.getResolver().contains(key)) {
136: Object instance = m_overrides.getResolver().get(key);
137: KeyAwareAdapter adapter = new ResolverBasedKeyAwareAdapter(
138: m_overrides.getResolver());
139: m_instanceToAdapterMap.put(instance, adapter);
140:
141: return new Object[] { instance };
142: } else {
143: Object[] instances = m_delegate.getAll(key);
144: KeyAwareAdapter adapter = new ResolverBasedKeyAwareAdapter(
145: m_delegate);
146: for (int i = 0; i < instances.length; i++) {
147: Object instance = instances[i];
148: m_instanceToAdapterMap.put(instance, adapter);
149: }
150:
151: return instances;
152: }
153: }
154:
155: public boolean contains(Object key) {
156: return m_overrides.getResolver().contains(key)
157: || m_delegate.contains(key);
158: }
159:
160: public void releaseInstance(Object instance) throws Exception {
161: if (instance == null)
162: return;
163:
164: final Object adapter = m_instanceToAdapterMap.remove(instance);
165: if (adapter != null) {
166: final KeyAwareAdapter keyAdapter = (KeyAwareAdapter) adapter;
167: keyAdapter.releaseInstance(instance);
168: }
169: }
170:
171: // ----------------------------------------------------------------------
172: // Interface: Customizable Resolver
173: // ----------------------------------------------------------------------
174: public CustomizableResolver overrideKey(Object key, Object instance) {
175: final Selector selector = PolicyUtil
176: .getSelectorForCriterion(key);
177: overrideKey(selector, instance);
178:
179: return this ;
180: }
181:
182: public CustomizableResolver overrideKey(Selector selector,
183: Object instance) {
184: Assert.assertNotNull("selector argument may not be null",
185: selector);
186: Assert.assertNotNull("instance argument may not be null",
187: instance);
188:
189: m_overrides.registerAdapter(selector, new SingletonAdapter(
190: new ManualFactory(instance)));
191:
192: return this ;
193: }
194:
195: /**
196: *
197: * @param callNumber index starts at 0
198: * @param instance
199: */
200: public CustomizableResolver overrideCall(int callNumber,
201: Object instance) {
202: callNumberOverride(callNumber, new SingletonAdapter(
203: new ManualFactory(instance)));
204:
205: return this ;
206: }
207:
208: public CustomizableResolver redirectKey(Object oldKey, Object newKey) {
209: Assert.assertNotNull("oldKey argument may not be null", oldKey);
210: Assert.assertNotNull("newKey argument may not be null", newKey);
211:
212: m_overrides.registerAdapter(oldKey, new ResolverBasedAdapter(
213: m_delegate, newKey));
214:
215: return this ;
216: }
217:
218: public CustomizableResolver redirectCall(int callNumber,
219: Object newKey) {
220: callNumberOverride(1, new ResolverBasedAdapter(m_delegate,
221: newKey));
222:
223: return this ;
224: }
225:
226: // ----------------------------------------------------------------------
227: // Helper Methods
228: // ----------------------------------------------------------------------
229: protected void callNumberOverride(int callNumber, Adapter adapter) {
230: Assert.assertTrue("callNumber must be 0 or greater",
231: callNumber >= 0);
232:
233: m_getCallOverrides.put(new Integer(callNumber), adapter);
234: }
235: }
|