001: // Copyright 2004, 2005 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.hivemind.impl;
016:
017: import java.io.IOException;
018: import java.net.URL;
019: import java.util.ArrayList;
020: import java.util.Enumeration;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.hivemind.ApplicationRuntimeException;
027: import org.apache.hivemind.ClassResolver;
028: import org.apache.hivemind.ErrorHandler;
029: import org.apache.hivemind.HiveMind;
030: import org.apache.hivemind.ModuleDescriptorProvider;
031: import org.apache.hivemind.Resource;
032: import org.apache.hivemind.parse.ModuleDescriptor;
033: import org.apache.hivemind.parse.SubModuleDescriptor;
034: import org.apache.hivemind.parse.XmlResourceProcessor;
035: import org.apache.hivemind.util.URLResource;
036:
037: /**
038: * Implementation of the {@link ModuleDescriptorProvider} interface which uses the
039: * {@link org.apache.hivemind.parse.DescriptorParser} to provide module descriptors defined in XML.
040: * The module descriptors are loaded from files or resources on the classpath.
041: *
042: * @author Knut Wannheden
043: * @since 1.1
044: */
045: public class XmlModuleDescriptorProvider implements
046: ModuleDescriptorProvider {
047: private static final Log LOG = LogFactory
048: .getLog(XmlModuleDescriptorProvider.class);
049:
050: /**
051: * The default path, within a JAR or the classpath, to the XML HiveMind module deployment
052: * descriptor: <code>META-INF/hivemodule.xml</code>. Use this constant with the
053: * {@link #XmlModuleDescriptorProvider(ClassResolver, String)} constructor.
054: */
055: public static final String HIVE_MODULE_XML = "META-INF/hivemodule.xml";
056:
057: /**
058: * Set of all specified resources processed by this ModuleDescriptorProvider. Descriptors of
059: * sub-modules are not included.
060: */
061: private List _resources = new ArrayList();
062:
063: /**
064: * List of parsed {@link ModuleDescriptor} instances. Also includes referenced sub-modules.
065: */
066: private List _moduleDescriptors = new ArrayList();
067:
068: private ClassResolver _resolver;
069:
070: private ErrorHandler _errorHandler;
071:
072: /**
073: * Parser instance used by all parsing of module descriptors.
074: */
075: private XmlResourceProcessor _processor;
076:
077: /**
078: * Convenience constructor. Equivalent to using
079: * {@link #XmlModuleDescriptorProvider(ClassResolver, String)}with {@link #HIVE_MODULE_XML} as
080: * the second argument.
081: */
082: public XmlModuleDescriptorProvider(ClassResolver resolver) {
083: this (resolver, HIVE_MODULE_XML);
084: }
085:
086: /**
087: * Loads all XML module descriptors found on the classpath (using the given
088: * {@link org.apache.hivemind.ClassResolver}. Only module descriptors matching the specified
089: * path are loaded. Use the {@link XmlModuleDescriptorProvider#HIVE_MODULE_XML} constant to load
090: * all descriptors in the default location.
091: */
092: public XmlModuleDescriptorProvider(ClassResolver resolver,
093: String resourcePath) {
094: _resolver = resolver;
095: _resources.addAll(getDescriptorResources(resourcePath,
096: _resolver));
097: }
098:
099: /**
100: * Constructs an XmlModuleDescriptorProvider only loading the ModuleDescriptor identified by the
101: * given {@link org.apache.hivemind.Resource}.
102: */
103: public XmlModuleDescriptorProvider(ClassResolver resolver,
104: Resource resource) {
105: _resolver = resolver;
106: _resources.add(resource);
107: }
108:
109: /**
110: * Constructs an XmlModuleDescriptorProvider loading all ModuleDescriptor identified by the
111: * given List of {@link org.apache.hivemind.Resource} objects.
112: */
113: public XmlModuleDescriptorProvider(ClassResolver resolver,
114: List resources) {
115: _resolver = resolver;
116: _resources.addAll(resources);
117: }
118:
119: private List getDescriptorResources(String resourcePath,
120: ClassResolver resolver) {
121: if (LOG.isDebugEnabled())
122: LOG.debug("Processing modules visible to " + resolver);
123:
124: List descriptors = new ArrayList();
125:
126: ClassLoader loader = resolver.getClassLoader();
127: Enumeration e = null;
128:
129: try {
130: e = loader.getResources(resourcePath);
131: } catch (IOException ex) {
132: throw new ApplicationRuntimeException(ImplMessages
133: .unableToFindModules(resolver, ex), ex);
134: }
135:
136: while (e.hasMoreElements()) {
137: URL descriptorURL = (URL) e.nextElement();
138:
139: descriptors.add(new URLResource(descriptorURL));
140: }
141:
142: return descriptors;
143: }
144:
145: public List getModuleDescriptors(ErrorHandler handler) {
146: _errorHandler = handler;
147:
148: _processor = getResourceProcessor(_resolver, handler);
149:
150: for (Iterator i = _resources.iterator(); i.hasNext();) {
151: Resource resource = (Resource) i.next();
152:
153: processResource(resource);
154: }
155:
156: _processor = null;
157:
158: _errorHandler = null;
159:
160: return _moduleDescriptors;
161: }
162:
163: private void processResource(Resource resource) {
164: try {
165: ModuleDescriptor md = _processor.processResource(resource);
166:
167: _moduleDescriptors.add(md);
168:
169: // After parsing a module, parse any additional modules identified
170: // within the module (using the <sub-module> element) recursively.
171: processSubModules(md);
172: } catch (RuntimeException ex) {
173: _errorHandler.error(LOG, ex.getMessage(), HiveMind
174: .getLocation(ex), ex);
175: }
176: }
177:
178: private void processSubModules(ModuleDescriptor moduleDescriptor) {
179: List subModules = moduleDescriptor.getSubModules();
180:
181: if (subModules == null)
182: return;
183:
184: for (Iterator i = subModules.iterator(); i.hasNext();) {
185: SubModuleDescriptor smd = (SubModuleDescriptor) i.next();
186:
187: Resource descriptorResource = smd.getDescriptor();
188:
189: if (descriptorResource.getResourceURL() == null) {
190: _errorHandler.error(LOG, ImplMessages
191: .subModuleDoesNotExist(descriptorResource), smd
192: .getLocation(), null);
193: continue;
194: }
195:
196: processResource(smd.getDescriptor());
197: }
198: }
199:
200: protected XmlResourceProcessor getResourceProcessor(
201: ClassResolver resolver, ErrorHandler handler) {
202: return new XmlResourceProcessor(resolver, handler);
203: }
204: }
|