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.selectors.ClassSelector;
029: import org.jicarilla.container.util.ReflectionUtil;
030: import org.jicarilla.container.util.PolicyUtil;
031: import org.jicarilla.lang.Assert;
032: import org.jicarilla.lang.EquivalenceSelector;
033: import org.jicarilla.lang.Selector;
034: import org.jicarilla.lang.SelectorSwitch;
035: import org.jicarilla.lang.Switch;
036:
037: import java.util.HashMap;
038: import java.util.Map;
039:
040: /**
041: * <p>A straightforward implementation of the {@link Container} interface that
042: * is backed by a {@link Switch}. This implementation is not threadsafe, and
043: * will use a {@link SelectorSwitch} and a {@link DefaultResolver} if no
044: * alternatives are provided.</p>
045: *
046: * <p>You will normally not want to use this implementation directly, as the
047: * {@link DefaultKeyRelayingContainer} provides commonly needed additional
048: * functionality.</p>
049: *
050: * @todo weak references where appropriate
051: * @todo split container-impl into multiple jars
052: * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
053: * @version $Id: DefaultContainer.java,v 1.12 2004/03/23 14:34:48 lsimons Exp $
054: */
055: public class DefaultContainer implements Container {
056: // ----------------------------------------------------------------------
057: // Properties
058: // ----------------------------------------------------------------------
059: /** A reverse mapping that's used to implement <code>release()</code>. */
060: protected Map m_instanceToAdapterMap;
061: /** The <em>core</em> of the container that maps keys to adapters. */
062: protected Switch m_switch;
063: /** The main <em>client interface</em> into the container. */
064: protected Resolver m_resolver;
065:
066: // ----------------------------------------------------------------------
067: // Constructors
068: // ----------------------------------------------------------------------
069: /**
070: * Create a new instance using a {@link SelectorSwitch} and a
071: * {@link DefaultResolver} as the backend.
072: */
073: public DefaultContainer() {
074: this (null);
075: }
076:
077: /**
078: * Create a new instance using a {@link SelectorSwitch} and the provided
079: * resolver as the backend. Providing a resolver yourself is quite an
080: * advanced construct and may lead to improper or unexpected behaviour if
081: * the resolver does not adhere to the expected contracts. In particular,
082: * the resolver is expected to defer back to the container or its internal
083: * <code>Switch</code> for most funcitonality.
084: *
085: * @param resolver
086: */
087: public DefaultContainer(final Resolver resolver) {
088: this (resolver, null);
089: }
090:
091: /**
092: * Create a new instance using the provided resolver and switch as the
093: * backend. Providing these yourself is quite an advanced construct and may
094: * lead to improper or unexpected results if the resolver does not adhere
095: * to the specified contracts.
096: *
097: * @param resolver
098: * @param switcher
099: */
100: public DefaultContainer(final Resolver resolver,
101: final Switch switcher) {
102: setResolver(resolver);
103: setSwitch(switcher);
104: setInstanceToAdapterMap(new HashMap());
105: }
106:
107: // ----------------------------------------------------------------------
108: // Interface: Container
109: // ----------------------------------------------------------------------
110:
111: /**
112: * @see Container#registerAdapter(Selector, Adapter)
113: *
114: * @param selector
115: * @param adapter
116: * @return
117: */
118: public Container registerAdapter(final Selector selector,
119: final Adapter adapter) {
120: doAddAdapter(selector, adapter);
121: return this ;
122: }
123:
124: /**
125: * @see Container#registerAdapter(Object, Adapter)
126: *
127: * @param key
128: * @param adapter
129: * @return
130: */
131: public Container registerAdapter(final Object key,
132: final Adapter adapter) {
133: doAddAdapter(key, adapter);
134: return this ;
135: }
136:
137: /**
138: * @see Container#registerAdapter(Object, Adapter)
139: *
140: * @return
141: */
142: public Resolver getResolver() {
143: return m_resolver;
144: }
145:
146: // ----------------------------------------------------------------------
147: // Getters and Setters
148: // ----------------------------------------------------------------------
149:
150: /**
151: * Returns {@link m_instanceToAdapterMap}. Overriding is not recommended.
152: *
153: * @return {@link m_instanceToAdapterMap}
154: */
155: protected Map getInstanceToAdapterMap() {
156: return m_instanceToAdapterMap;
157: }
158:
159: /**
160: * Sets {@link m_instanceToAdapterMap}. Direct usage is not recommended.
161: *
162: * @param instanceToAdapterMap the new {@link m_instanceToAdapterMap}
163: * value.
164: */
165: protected void setInstanceToAdapterMap(
166: final Map instanceToAdapterMap) {
167: m_instanceToAdapterMap = instanceToAdapterMap;
168: }
169:
170: /**
171: * Returns {@link m_switch}. Overriding is not recommended.
172: *
173: * @return {@link m_switch}
174: */
175: protected Switch getSwitch() {
176: return m_switch;
177: }
178:
179: /**
180: * Sets {@link m_switch}. Direct usage is not recommended.
181: *
182: * @param switcher the new {@link m_switch} value, or null to set it to
183: * a new default implementation
184: */
185: protected void setSwitch(final Switch switcher) {
186: if (switcher != null)
187: m_switch = switcher;
188: else
189: m_switch = new SelectorSwitch();
190: }
191:
192: /**
193: * Sets {@link m_resolver}. Direct usage is not recommended.
194: *
195: * @param resolver the new {@link m_resolver} value, or null to set it to
196: * a new default implementation
197: */
198: protected void setResolver(final Resolver resolver) {
199: if (resolver != null)
200: m_resolver = resolver;
201: else
202: m_resolver = new DefaultResolver(
203: new DefaultResolverCallback());
204: }
205:
206: // ----------------------------------------------------------------------
207: // Helper methods
208: // ----------------------------------------------------------------------
209:
210: /**
211: * Add a new adapter. If you are providing an {@link Adapter} instance,
212: * use the public {@link #registerAdapter(Selector,Adapter)} instead.
213: *
214: * @param selector
215: * @param adapter the new adapter. The {@link m_resolver current resolver}
216: * should know how to use this adapter.
217: */
218: /*protected void doAddAdapter( final Selector selector,
219: final Object adapter )
220: {
221: Assert.assertNotNull( "selector argument may not be null", selector );
222: Assert.assertNotNull( "adapter argument may not be null", adapter );
223:
224: getSwitch().put( selector, adapter );
225: }*/
226:
227: /**
228: * Add a new adapter. If you are providing an {@link Adapter} instance,
229: * use the public {@link #registerAdapter(Object,Adapter)} instead.
230: * Implements some special handling for some key types (ie classes and some
231: * kinds of strings).
232: *
233: * @param key
234: * @param adapter the new adapter. The {@link m_resolver current resolver}
235: * should know how to use this adapter.
236: */
237: protected void doAddAdapter(final Object key, final Object adapter) {
238: Assert.assertNotNull("key argument may not be null", key);
239: Assert.assertNotNull("adapter argument may not be null",
240: adapter);
241:
242: final Selector selector = PolicyUtil
243: .getSelectorForCriterion(key);
244:
245: getSwitch().put(selector, adapter);
246: }
247:
248: // ----------------------------------------------------------------------
249: // Inner Class: DefaultResolverCallback
250: // ----------------------------------------------------------------------
251:
252: /**
253: * Straightforward implementation of {@link ResolverCallback} that defers
254: * to its parent {@link DefaultContainer} implementation for the required
255: * functionality.
256: */
257: protected class DefaultResolverCallback implements ResolverCallback {
258: /** The container to delegate to. */
259: protected final DefaultContainer m_container = DefaultContainer.this ;
260:
261: /**
262: * @see ResolverCallback#getSwitch()
263: *
264: * @return
265: */
266: public Switch getSwitch() {
267: return m_container.getSwitch();
268: }
269:
270: /**
271: * @see ResolverCallback#providedInstance(Object,Object)
272: *
273: * @param instance
274: * @param adapter
275: */
276: public void providedInstance(final Object instance,
277: final Object adapter) {
278: Assert.assertTrue(
279: "DefaultContainer can only handle adapters that "
280: + "implement the Adapter interface!",
281: adapter instanceof Adapter);
282:
283: m_container.getInstanceToAdapterMap()
284: .put(instance, adapter);
285: }
286:
287: /**
288: * @see ResolverCallback#returnedInstance(Object)
289: *
290: * @param component
291: * @throws Exception
292: */
293: public void returnedInstance(final Object component)
294: throws Exception {
295: if (component == null)
296: return;
297:
298: final Adapter adapter = (Adapter) m_container
299: .getInstanceToAdapterMap().remove(component);
300:
301: if (adapter != null)
302: adapter.releaseInstance(component);
303: }
304: }
305: }
|