001: /*
002: * $Id: ComponentContainer.java,v 1.16 2003/12/06 23:28:44 ajzeneski Exp $
003: *
004: * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.base.container;
026:
027: import java.io.File;
028: import java.io.IOException;
029: import java.util.Iterator;
030: import java.util.LinkedList;
031: import java.util.List;
032:
033: import org.ofbiz.base.component.ComponentConfig;
034: import org.ofbiz.base.component.ComponentException;
035: import org.ofbiz.base.component.ComponentLoaderConfig;
036: import org.ofbiz.base.component.AlreadyLoadedException;
037: import org.ofbiz.base.start.Classpath;
038: import org.ofbiz.base.util.Debug;
039: import org.ofbiz.base.util.UtilValidate;
040:
041: /**
042: * ComponentContainer - StartupContainer implementation for Components
043: *
044: * Example ofbiz-container.xml configuration:
045: * <pre>
046: * <container name="component-container" class="org.ofbiz.base.component.ComponentContainer"/>
047: * </pre>
048: *
049: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
050: *@version $Revision: 1.16 $
051: * @since 3.0
052: */
053: public class ComponentContainer implements Container {
054:
055: public static final String module = ComponentContainer.class
056: .getName();
057:
058: protected static List loadedComponents = null;
059: protected Classpath classPath = null;
060:
061: /**
062: * @see org.ofbiz.base.container.Container#start(java.lang.String)
063: */
064: public boolean start(String configFileLocation)
065: throws ContainerException {
066: if (classPath == null) {
067: classPath = new Classpath(System
068: .getProperty("java.class.path"));
069: }
070:
071: // get the config for this container
072: ContainerConfig.Container cc = ContainerConfig.getContainer(
073: "component-container", configFileLocation);
074:
075: // check for an override loader config
076: String loaderConfig = null;
077: if (cc.getProperty("loader-config") != null) {
078: loaderConfig = cc.getProperty("loader-config").value;
079: }
080:
081: // load the components
082: try {
083: loadComponents(loaderConfig, true);
084: } catch (AlreadyLoadedException e) {
085: throw new ContainerException(e);
086: } catch (ComponentException e) {
087: throw new ContainerException(e);
088: }
089:
090: return true;
091: }
092:
093: public synchronized void loadComponents(String loaderConfig,
094: boolean updateClasspath) throws AlreadyLoadedException,
095: ComponentException {
096: // set the loaded list; and fail if already loaded
097: if (loadedComponents == null) {
098: loadedComponents = new LinkedList();
099: } else {
100: throw new AlreadyLoadedException(
101: "Components already loaded, cannot start");
102: }
103:
104: // get the components to load
105: List components = ComponentLoaderConfig
106: .getComponentsToLoad(loaderConfig);
107:
108: // load each component
109: if (components != null) {
110: Iterator ci = components.iterator();
111: while (ci.hasNext()) {
112: ComponentLoaderConfig.ComponentDef def = (ComponentLoaderConfig.ComponentDef) ci
113: .next();
114: if (def.type == ComponentLoaderConfig.SINGLE_COMPONENT) {
115: ComponentConfig config = null;
116: try {
117: config = ComponentConfig.getComponentConfig(
118: def.name, def.location);
119: if (UtilValidate.isEmpty(def.name)) {
120: def.name = config.getGlobalName();
121: }
122: } catch (ComponentException e) {
123: Debug.logError("Cannot load component : "
124: + def.name + " @ " + def.location
125: + " : " + e.getMessage(), module);
126: }
127: if (config == null) {
128: Debug.logError("Cannot load component : "
129: + def.name + " @ " + def.location,
130: module);
131: } else {
132: loadComponent(config);
133: }
134: } else if (def.type == ComponentLoaderConfig.COMPONENT_DIRECTORY) {
135: loadComponentDirectory(def.location);
136: }
137: }
138: }
139:
140: // set the new classloader/classpath on the current thread
141: if (updateClasspath) {
142: System.setProperty("java.class.path", classPath.toString());
143: ClassLoader cl = classPath.getClassLoader();
144: Thread.currentThread().setContextClassLoader(cl);
145: }
146:
147: Debug.logInfo("All components loaded", module);
148: }
149:
150: private void loadComponentDirectory(String directoryName) {
151: Debug.logInfo("Auto-Loading component directory : ["
152: + directoryName + "]", module);
153: File parentPath = new File(directoryName);
154: if (!parentPath.exists() || !parentPath.isDirectory()) {
155: Debug.logError("Auto-Load Component directory not found : "
156: + directoryName, module);
157: } else {
158: String subs[] = parentPath.list();
159: for (int i = 0; i < subs.length; i++) {
160: try {
161: File componentPath = new File(parentPath
162: .getCanonicalPath()
163: + "/" + subs[i]);
164: if (componentPath.isDirectory()
165: && !subs[i].equals("CVS")) {
166: // make sure we have a component configuraton file
167: String componentLocation = componentPath
168: .getCanonicalPath();
169: File configFile = new File(componentLocation
170: + "/ofbiz-component.xml");
171: if (configFile.exists()) {
172: ComponentConfig config = null;
173: try {
174: // pass null for the name, will default to the internal component name
175: config = ComponentConfig
176: .getComponentConfig(null,
177: componentLocation);
178: } catch (ComponentException e) {
179: Debug.logError(e,
180: "Cannot load component : "
181: + componentPath
182: .getName()
183: + " @ "
184: + componentLocation
185: + " : "
186: + e.getMessage(),
187: module);
188: }
189: if (config == null) {
190: Debug.logError(
191: "Cannot load component : "
192: + componentPath
193: .getName()
194: + " @ "
195: + componentLocation,
196: module);
197: } else {
198: loadComponent(config);
199: }
200: }
201: }
202: } catch (IOException ioe) {
203: Debug.logError(ioe, module);
204: }
205: }
206: }
207: }
208:
209: private void loadComponent(ComponentConfig config) {
210: Debug.logInfo("Loading component : ["
211: + config.getComponentName() + "]", module);
212: List classpathInfos = config.getClasspathInfos();
213: String configRoot = config.getRootLocation();
214: configRoot = configRoot.replace('\\', '/');
215: // set the root to have a trailing slash
216: if (!configRoot.endsWith("/")) {
217: configRoot = configRoot + "/";
218: }
219: if (classpathInfos != null) {
220: Iterator cpi = classpathInfos.iterator();
221: while (cpi.hasNext()) {
222: ComponentConfig.ClasspathInfo cp = (ComponentConfig.ClasspathInfo) cpi
223: .next();
224: String location = cp.location.replace('\\', '/');
225: // set the location to not have a leading slash
226: if (location.startsWith("/")) {
227: location = location.substring(1);
228: }
229: if ("dir".equals(cp.type)) {
230: classPath.addComponent(configRoot + location);
231: } else if ("jar".equals(cp.type)) {
232: String dirLoc = location;
233: if (dirLoc.endsWith("/*")) {
234: // strip off the slash splat
235: dirLoc = location.substring(0, location
236: .length() - 2);
237: }
238: File path = new File(configRoot + dirLoc);
239: if (path.exists()) {
240: if (path.isDirectory()) {
241: // load all .jar and .zip files in this directory
242: File files[] = path.listFiles();
243: for (int i = 0; i < files.length; i++) {
244: String file = files[i].getName();
245: if (file.endsWith(".jar")
246: || file.endsWith(".zip")) {
247: classPath.addComponent(files[i]);
248: }
249: }
250: } else {
251: // add a single file
252: classPath.addComponent(configRoot
253: + location);
254: }
255: } else {
256: Debug.logWarning("Location '" + configRoot
257: + dirLoc + "' does not exist", module);
258: }
259: } else {
260: Debug.logError("Classpath type '" + cp.type
261: + "' is not supported; '" + location
262: + "' not loaded", module);
263: }
264: }
265: }
266: }
267:
268: /**
269: * @see org.ofbiz.base.container.Container#stop()
270: */
271: public void stop() throws ContainerException {
272: }
273:
274: /**
275: * Static method for easy loading of components for use when the container system is not.
276: * @param updateClasspath Tells the component loader to update the classpath, and thread classloader
277: * @throws AlreadyLoadedException
278: * @throws ComponentException
279: */
280: public static synchronized void loadComponents(
281: boolean updateClasspath) throws AlreadyLoadedException,
282: ComponentException {
283: ComponentContainer cc = new ComponentContainer();
284: cc.loadComponents(null, updateClasspath);
285: cc = null;
286: }
287: }
|