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 ModuleDescriptorProvider 046 { 047 private static final Log LOG = LogFactory.getLog(XmlModuleDescriptorProvider.class); 048 049 /** 050 * The default path, within a JAR or the classpath, to the XML HiveMind module deployment 051 * descriptor: <code>META-INF/hivemodule.xml</code>. Use this constant with the 052 * {@link #XmlModuleDescriptorProvider(ClassResolver, String)} constructor. 053 */ 054 public static final String HIVE_MODULE_XML = "META-INF/hivemodule.xml"; 055 056 /** 057 * Set of all specified resources processed by this ModuleDescriptorProvider. Descriptors of 058 * sub-modules are not included. 059 */ 060 private List _resources = new ArrayList(); 061 062 /** 063 * List of parsed {@link ModuleDescriptor} instances. Also includes referenced sub-modules. 064 */ 065 private List _moduleDescriptors = new ArrayList(); 066 067 private ClassResolver _resolver; 068 069 private ErrorHandler _errorHandler; 070 071 /** 072 * Parser instance used by all parsing of module descriptors. 073 */ 074 private XmlResourceProcessor _processor; 075 076 /** 077 * Convenience constructor. Equivalent to using 078 * {@link #XmlModuleDescriptorProvider(ClassResolver, String)}with {@link #HIVE_MODULE_XML} as 079 * the second argument. 080 */ 081 public XmlModuleDescriptorProvider(ClassResolver resolver) 082 { 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, String resourcePath) 093 { 094 _resolver = resolver; 095 _resources.addAll(getDescriptorResources(resourcePath, _resolver)); 096 } 097 098 /** 099 * Constructs an XmlModuleDescriptorProvider only loading the ModuleDescriptor identified by the 100 * given {@link org.apache.hivemind.Resource}. 101 */ 102 public XmlModuleDescriptorProvider(ClassResolver resolver, Resource resource) 103 { 104 _resolver = resolver; 105 _resources.add(resource); 106 } 107 108 /** 109 * Constructs an XmlModuleDescriptorProvider loading all ModuleDescriptor identified by the 110 * given List of {@link org.apache.hivemind.Resource} objects. 111 */ 112 public XmlModuleDescriptorProvider(ClassResolver resolver, List resources) 113 { 114 _resolver = resolver; 115 _resources.addAll(resources); 116 } 117 118 private List getDescriptorResources(String resourcePath, ClassResolver resolver) 119 { 120 if (LOG.isDebugEnabled()) 121 LOG.debug("Processing modules visible to " + resolver); 122 123 List descriptors = new ArrayList(); 124 125 ClassLoader loader = resolver.getClassLoader(); 126 Enumeration e = null; 127 128 try 129 { 130 e = loader.getResources(resourcePath); 131 } 132 catch (IOException ex) 133 { 134 throw new ApplicationRuntimeException(ImplMessages.unableToFindModules(resolver, ex), 135 ex); 136 } 137 138 while (e.hasMoreElements()) 139 { 140 URL descriptorURL = (URL) e.nextElement(); 141 142 descriptors.add(new URLResource(descriptorURL)); 143 } 144 145 return descriptors; 146 } 147 148 public List getModuleDescriptors(ErrorHandler handler) 149 { 150 _errorHandler = handler; 151 152 _processor = getResourceProcessor(_resolver, handler); 153 154 for (Iterator i = _resources.iterator(); i.hasNext();) 155 { 156 Resource resource = (Resource) i.next(); 157 158 processResource(resource); 159 } 160 161 _processor = null; 162 163 _errorHandler = null; 164 165 return _moduleDescriptors; 166 } 167 168 private void processResource(Resource resource) 169 { 170 try 171 { 172 ModuleDescriptor md = _processor.processResource(resource); 173 174 _moduleDescriptors.add(md); 175 176 // After parsing a module, parse any additional modules identified 177 // within the module (using the <sub-module> element) recursively. 178 processSubModules(md); 179 } 180 catch (RuntimeException ex) 181 { 182 _errorHandler.error(LOG, ex.getMessage(), HiveMind.getLocation(ex), ex); 183 } 184 } 185 186 private void processSubModules(ModuleDescriptor moduleDescriptor) 187 { 188 List subModules = moduleDescriptor.getSubModules(); 189 190 if (subModules == null) 191 return; 192 193 for (Iterator i = subModules.iterator(); i.hasNext();) 194 { 195 SubModuleDescriptor smd = (SubModuleDescriptor) i.next(); 196 197 Resource descriptorResource = smd.getDescriptor(); 198 199 if (descriptorResource.getResourceURL() == null) 200 { 201 _errorHandler.error( 202 LOG, 203 ImplMessages.subModuleDoesNotExist(descriptorResource), 204 smd.getLocation(), 205 null); 206 continue; 207 } 208 209 processResource(smd.getDescriptor()); 210 } 211 } 212 213 protected XmlResourceProcessor getResourceProcessor(ClassResolver resolver, ErrorHandler handler) 214 { 215 return new XmlResourceProcessor(resolver, handler); 216 } 217 }