001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.interceptor.component;
006:
007: import com.opensymphony.util.ClassLoaderUtil;
008: import com.opensymphony.xwork.ObjectFactory;
009: import com.opensymphony.xwork.XworkException;
010: import org.apache.commons.logging.Log;
011: import org.apache.commons.logging.LogFactory;
012:
013: import java.io.File;
014: import java.io.Serializable;
015: import java.net.URI;
016: import java.net.URL;
017: import java.util.*;
018:
019: /**
020: * @author joew@thoughtworks.com
021: * @author $Author: rainerh $
022: * @version $Revision: 1071 $
023: * @deprecated XWork IoC has been deprecated in favor of Spring.
024: * Please refer to the Spring-WebWork integration documentation for more info.
025: */
026: public class DefaultComponentManager implements ComponentManager,
027: Serializable {
028:
029: private static final Log log = LogFactory
030: .getLog(DefaultComponentManager.class);
031:
032: Map enablers = new HashMap();
033: Map enablers2 = new HashMap();
034: private DefaultComponentManager fallback;
035: private List loadOrder = new ArrayList();
036: private Map resourceInstances = new HashMap();
037: private Map dependentResources = new HashMap();
038: private Set alreadyLoaded = new HashSet();
039: private ComponentConfiguration config;
040: private String scope;
041:
042: public Object getComponent(Class enablerType) {
043: DefaultComponentManager dcm = this ;
044:
045: // loop all the DCMs and get the one that holds this enabler
046: Class resource = null;
047:
048: while (dcm != null) {
049: resource = getPossibleResource(dcm, enablerType, true);
050:
051: if (resource != null) {
052: break;
053: }
054:
055: dcm = dcm.fallback;
056: }
057:
058: if (resource == null) {
059: // this is an unknown resource, return null;
060: return null;
061: }
062:
063: // now that we have the DCM and the resource class, we can set it up
064: try {
065: ResourceEnablerPair pair = setupAndOptionallyCreateResource(
066: dcm, resource);
067:
068: return pair.resource;
069: } catch (Exception e) {
070: String message = "Could not load resource with enabler "
071: + enablerType;
072: log.error(message, e);
073: throw new XworkException(message);
074: }
075: }
076:
077: public void setFallback(ComponentManager fallback) {
078: if (fallback instanceof DefaultComponentManager) {
079: this .fallback = (DefaultComponentManager) fallback;
080: this .config = fallback.getConfig();
081: } else {
082: throw new XworkException(
083: "Fallback must be an instance of DefaultConfigurationManager");
084: }
085: }
086:
087: public void addEnabler(Class component, Class enablerType) {
088: enablers.put(enablerType, component);
089: enablers2.put(component, enablerType);
090: }
091:
092: public void dispose() {
093: Collections.reverse(loadOrder);
094:
095: for (Iterator iterator = loadOrder.iterator(); iterator
096: .hasNext();) {
097: Object resource = iterator.next();
098:
099: if (resource instanceof Disposable) {
100: Disposable disposable = (Disposable) resource;
101: disposable.dispose();
102: }
103: }
104: }
105:
106: public void initializeObject(Object obj) {
107: loadResource(obj, obj.getClass(), this );
108:
109: // is this even needed now?
110: // if (fallback != null) {
111: // fallback.initializeObject(obj);
112: // }
113: }
114:
115: public void registerInstance(Class componentType, Object instance) {
116: if (!componentType.isInstance(instance)) {
117: throw new IllegalArgumentException("The object " + instance
118: + " is not an instance of "
119: + componentType.getName());
120: }
121:
122: loadResource(instance, componentType, this );
123: }
124:
125: public Object getComponentInstance(Class componentType) {
126: DefaultComponentManager dcm = this ;
127:
128: // loop all the DCMs and get the one that holds this enabler
129: Class enablerType = null;
130:
131: while (dcm != null) {
132: enablerType = (Class) dcm.enablers2.get(componentType);
133:
134: if (enablerType != null) {
135: break;
136: }
137:
138: dcm = dcm.fallback;
139: }
140:
141: if (enablerType == null) {
142: // this is an unknown component type, return null
143: return null;
144: }
145:
146: try {
147: ResourceEnablerPair pair = setupAndOptionallyCreateResource(
148: dcm, componentType);
149:
150: return pair.resource;
151: } catch (Exception e) {
152: String message = "Could not load resource of type "
153: + componentType;
154: log.error(message, e);
155: throw new XworkException(message);
156: }
157: }
158:
159: public ComponentConfiguration getConfig() {
160: return config;
161: }
162:
163: public void setConfig(ComponentConfiguration config) {
164: this .config = config;
165: }
166:
167: public void setScope(String scope) {
168: this .scope = scope;
169: }
170:
171: public void reset() {
172: enablers.clear();
173: enablers2.clear();
174: loadOrder.clear();
175: resourceInstances.clear();
176: alreadyLoaded.clear();
177: dependentResources.clear();
178: }
179:
180: private Map getResourceDependencies(Class resourceClass) {
181: List interfaces = new ArrayList();
182: addAllInterfaces(resourceClass, interfaces);
183:
184: Map dependencies = new HashMap();
185:
186: for (Iterator iterator = interfaces.iterator(); iterator
187: .hasNext();) {
188: Class anInterface = (Class) iterator.next();
189:
190: DefaultComponentManager dcm = this ;
191: while (dcm != null) {
192: dcm.resolveDependencies();
193: Class possibleResource = getPossibleResource(dcm,
194: anInterface, true);
195:
196: if (possibleResource != null) {
197: dependencies.put(possibleResource, dcm);
198:
199: break;
200: }
201:
202: dcm = dcm.fallback;
203: }
204: }
205:
206: return dependencies;
207: }
208:
209: private Class getPossibleResource(DefaultComponentManager dcm,
210: Class anInterface, boolean retry) {
211: for (Iterator iterator = dcm.enablers.entrySet().iterator(); iterator
212: .hasNext();) {
213: Map.Entry entry = (Map.Entry) iterator.next();
214: Class key = (Class) entry.getKey();
215: if (anInterface.equals(key)) {
216: return (Class) entry.getValue();
217: } else if (retry
218: && anInterface.getName().equals(key.getName())) {
219: // looks like we should reload!
220: log.warn("Re-configuration IoC for scope " + dcm.scope);
221: dcm.dispose();
222: config.configure(dcm, dcm.scope);
223: return getPossibleResource(dcm, anInterface, false);
224: }
225: }
226:
227: return null;
228: }
229:
230: private void addAllInterfaces(Class clazz, List allInterfaces) {
231: if (clazz == null) {
232: return;
233: }
234:
235: Class[] interfaces = clazz.getInterfaces();
236: allInterfaces.addAll(Arrays.asList(interfaces));
237: addAllInterfaces(interfaces, allInterfaces);
238: addAllInterfaces(clazz.getSuperclass(), allInterfaces);
239: }
240:
241: private void addAllInterfaces(Class[] clazzes, List allInterfaces) {
242: if (clazzes != null) {
243: for (int i = 0; i < clazzes.length; i++) {
244: addAllInterfaces(clazzes[i], allInterfaces);
245: }
246: }
247: }
248:
249: private Class loadResource(Object resource, Class clazz,
250: DefaultComponentManager dcm) {
251: boolean resourceNotLoaded = !dcm.loadOrder.contains(resource);
252:
253: if (resourceNotLoaded) {
254: Map resources = getResourceDependencies(clazz);
255:
256: for (Iterator iterator = resources.entrySet().iterator(); iterator
257: .hasNext();) {
258: Map.Entry mapEntry = (Map.Entry) iterator.next();
259: Class depResource = (Class) mapEntry.getKey();
260: DefaultComponentManager newDcm = (DefaultComponentManager) mapEntry
261: .getValue();
262:
263: try {
264: ResourceEnablerPair pair = setupAndOptionallyCreateResource(
265: newDcm, depResource);
266: setupResource(resource, pair.enabler, pair.resource);
267: } catch (Exception e) {
268: e.printStackTrace();
269:
270: if (log.isDebugEnabled()) {
271: log.debug(
272: "Error loading or setting up resource: "
273: + resources.getClass()
274: .getName(), e);
275: }
276: }
277: }
278:
279: dcm.alreadyLoaded.add(clazz);
280:
281: if (resource instanceof Initializable) {
282: Initializable initializable = (Initializable) resource;
283: initializable.init();
284: }
285:
286: if (resource instanceof ResourceAware) {
287: ResourceAware ra = (ResourceAware) resource;
288: Set dr = ra.getDependentResources();
289: HashMap times = new HashMap();
290: for (Iterator iterator = dr.iterator(); iterator
291: .hasNext();) {
292: String name = (String) iterator.next();
293: times.put(name, new Long(getLastModified(name)));
294: }
295: dcm.dependentResources.put(ra, times);
296: }
297:
298: dcm.resourceInstances.put(clazz, resource);
299: dcm.loadOrder.add(resource);
300: }
301:
302: // now return this class's enabler
303: Class enabler = (Class) dcm.enablers2.get(clazz);
304:
305: return enabler;
306: }
307:
308: private long getLastModified(String name) {
309: try {
310: URL url = ClassLoaderUtil.getResource(name, getClass());
311: File file = new File(new URI(url.toExternalForm()));
312: return file.lastModified();
313: } catch (Exception e) {
314: return 0;
315: }
316: }
317:
318: private ResourceEnablerPair setupAndOptionallyCreateResource(
319: DefaultComponentManager newDcm, Class depResource)
320: throws Exception {
321: ResourceEnablerPair pair = new ResourceEnablerPair();
322: Object newResource = newDcm.resourceInstances.get(depResource);
323:
324: if (newResource == null) {
325: newResource = ObjectFactory.getObjectFactory().buildBean(
326: depResource, null);
327: }
328:
329: pair.resource = newResource;
330:
331: Class enabler = loadResource(newResource, depResource, newDcm);
332: pair.enabler = enabler;
333:
334: return pair;
335: }
336:
337: private void setupResource(Object resource, Class enabler,
338: Object newResource) {
339: if (enabler == null) {
340: return;
341: }
342:
343: try {
344: enabler.getMethods()[0].invoke(resource,
345: new Object[] { newResource });
346: } catch (Exception e) {
347: e.printStackTrace();
348:
349: if (log.isDebugEnabled()) {
350: log.debug("Error invoking method for resource: "
351: + resource.getClass().getName(), e);
352: }
353: }
354: }
355:
356: private void resolveDependencies() {
357: for (Iterator iterator = dependentResources.entrySet()
358: .iterator(); iterator.hasNext();) {
359: Map.Entry entry = (Map.Entry) iterator.next();
360: ResourceAware ra = (ResourceAware) entry.getKey();
361: Map times = (Map) entry.getValue();
362:
363: Set dr = ra.getDependentResources();
364: for (Iterator iterator1 = dr.iterator(); iterator1
365: .hasNext();) {
366: String name = (String) iterator1.next();
367: long lastTime = ((Long) times.get(name)).longValue();
368: long lastMod = getLastModified(name);
369: if (lastTime < lastMod) {
370: // reload this DCM
371: dispose();
372: config.configure(DefaultComponentManager.this ,
373: scope);
374: break;
375: }
376: }
377: }
378: }
379:
380: class ResourceEnablerPair {
381: Class enabler;
382: Object resource;
383: }
384: }
|