001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.configuration;
023:
024: import java.util.ArrayList;
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.HashSet;
028: import java.util.List;
029: import java.util.Map;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.jbpm.JbpmException;
034: import org.jbpm.util.ClassLoaderUtil;
035:
036: public class ObjectFactoryImpl implements ObjectFactory {
037:
038: private static final long serialVersionUID = 1L;
039:
040: ClassLoader classLoader = ClassLoaderUtil.getClassLoader();
041: List objectInfos = null;
042: Map namedObjectInfos = null;
043: Map singletons = new HashMap();
044: Map objects = new HashMap();
045: Collection objectsUnderConstruction = new HashSet();
046:
047: public ObjectFactoryImpl() {
048: objectInfos = new ArrayList();
049: namedObjectInfos = new HashMap();
050: }
051:
052: public ObjectFactoryImpl(Map namedObjectInfos, List objectInfos) {
053: this .namedObjectInfos = namedObjectInfos;
054: this .objectInfos = objectInfos;
055: }
056:
057: public void addObjectInfo(ObjectInfo objectInfo) {
058: if (objectInfo.hasName()) {
059: log.debug("adding object info '" + objectInfo.getName()
060: + "'");
061: Object removed = namedObjectInfos.put(objectInfo.getName(),
062: objectInfo);
063: if (removed != null) {
064: objectInfos.remove(removed);
065: }
066: }
067: objectInfos.add(objectInfo);
068: }
069:
070: /**
071: * create a new object of the given name.
072: * Before creation starts, the non-singlton objects will be cleared
073: * from the registry. The singletons will remain in the registry.
074: */
075: public synchronized Object createObject(String name) {
076: ObjectInfo objectInfo = (ObjectInfo) namedObjectInfos.get(name);
077: if (objectInfo == null) {
078: throw new ConfigurationException(
079: "name '"
080: + name
081: + "' is not defined in the configuration. configured names: "
082: + namedObjectInfos.keySet());
083: }
084: return createObject(objectInfo);
085: }
086:
087: public synchronized boolean hasObject(String name) {
088: return namedObjectInfos.containsKey(name);
089: }
090:
091: /**
092: * create a new object for the given index.
093: * Before creation starts, the non-singlton objects will be cleared
094: * from the registry. The singletons will remain in the registry.
095: */
096: public Object createObject(int index) {
097: if ((index < 0) || (index >= objectInfos.size())) {
098: throw new ConfigurationException(
099: "index '"
100: + index
101: + "' is not defined in the configuration. range [0.."
102: + (objectInfos.size() - 1) + "]");
103: }
104: return createObject((ObjectInfo) objectInfos.get(index));
105: }
106:
107: /**
108: * create a new object for the given {@link ObjectInfo}.
109: * Before creation starts, the non-singlton objects will be cleared
110: * from the registry. The singletons will remain in the registry.
111: */
112: public Object createObject(ObjectInfo objectInfo) {
113: clearRegistry();
114: return getObject(objectInfo);
115: }
116:
117: void clearRegistry() {
118: objects.clear();
119: objectsUnderConstruction.clear();
120: }
121:
122: /**
123: * create an object of the given name.
124: * If the object was created before, that object is returned from
125: * the registry.
126: */
127: Object getObject(String name) {
128: Object object = null;
129: ObjectInfo objectInfo = (ObjectInfo) namedObjectInfos.get(name);
130: if (objectInfo != null) {
131: object = getObject(objectInfo);
132: } else {
133: log.warn("no info for object '" + name
134: + "'. defined objects: "
135: + namedObjectInfos.keySet().toString());
136: }
137: return object;
138: }
139:
140: /**
141: * create an object for the given {@link ObjectInfo}.
142: * If the object was created before, that object is returned from
143: * the registry.
144: */
145: Object getObject(ObjectInfo objectInfo) {
146: Object object = null;
147:
148: Object registryKey = getRegistryKey(objectInfo);
149: if (isInRegistry(registryKey)) {
150: object = findInRegistry(registryKey);
151:
152: } else {
153: if (registryKey != null) {
154: if (objectsUnderConstruction.contains(registryKey)) {
155: throw new JbpmException(
156: "circular object dependency on bean '"
157: + registryKey + "'");
158: }
159: objectsUnderConstruction.add(registryKey);
160: try {
161: object = objectInfo.createObject(this );
162: } finally {
163: objectsUnderConstruction.remove(registryKey);
164: }
165:
166: putInRegistry(objectInfo, object, registryKey);
167:
168: } else {
169: object = objectInfo.createObject(this );
170: }
171: }
172: return object;
173: }
174:
175: Class loadClass(String className) {
176: try {
177: return classLoader.loadClass(className);
178: } catch (ClassNotFoundException e) {
179: throw new JbpmException("couldn't load class '" + className
180: + "'", e);
181: }
182: }
183:
184: Object getRegistryKey(ObjectInfo objectInfo) {
185: Object key = null;
186: if (objectInfo.hasName()) {
187: key = objectInfo.getName();
188: }
189: return key;
190: }
191:
192: boolean isInRegistry(Object registryKey) {
193: return ((registryKey != null) && ((objects
194: .containsKey(registryKey)) || (singletons
195: .containsKey(registryKey))));
196: }
197:
198: void putInRegistry(ObjectInfo objectInfo, Object object,
199: Object registryKey) {
200: if (objectInfo.isSingleton()) {
201: singletons.put(registryKey, object);
202: } else {
203: objects.put(registryKey, object);
204: }
205: }
206:
207: Object findInRegistry(Object registryKey) {
208: Object object = null;
209: if (registryKey != null) {
210: object = objects.get(registryKey);
211: if (object == null)
212: object = singletons.get(registryKey);
213: }
214: return object;
215: }
216:
217: private static Log log = LogFactory.getLog(ObjectFactoryImpl.class);
218: }
|