001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Adam Megacz
028: */
029:
030: package javax.xml.bind;
031:
032: import java.io.File;
033: import java.io.FileInputStream;
034: import java.io.IOException;
035: import java.io.InputStream;
036: import java.net.URL;
037: import java.util.ArrayList;
038: import java.util.Enumeration;
039: import java.util.HashMap;
040: import java.util.Properties;
041: import java.util.WeakHashMap;
042: import java.util.logging.Level;
043: import java.util.logging.Logger;
044:
045: class FactoryLoader {
046: private static Logger log = Logger
047: .getLogger("javax.xml.bind.FactoryLoader");
048:
049: private static HashMap<String, FactoryLoader> _factoryLoaders = new HashMap<String, FactoryLoader>();
050:
051: private static final String JAXB_CONTEXT_FACTORY = "javax.xml.bind.context.factory";
052:
053: private String _factoryId;
054:
055: private WeakHashMap<ClassLoader, Class[]> _providerMap = new WeakHashMap<ClassLoader, Class[]>();
056:
057: public static FactoryLoader getFactoryLoader(String factoryId) {
058: FactoryLoader ret = _factoryLoaders.get(factoryId);
059:
060: if (ret == null) {
061: ret = new FactoryLoader(factoryId);
062: _factoryLoaders.put(factoryId, ret);
063: }
064:
065: return ret;
066: }
067:
068: private FactoryLoader(String factoryId) {
069: _factoryId = factoryId;
070: }
071:
072: private String classNameFromPropertiesFile(ClassLoader classLoader,
073: String fileName) {
074: InputStream is = null;
075: try {
076: is = classLoader.getResourceAsStream(fileName);
077:
078: if (is == null)
079: return null;
080:
081: Properties props = new Properties();
082: props.load(is);
083:
084: return props.getProperty(JAXB_CONTEXT_FACTORY);
085: } catch (IOException e) {
086: log.log(Level.FINER, "ignoring exception", e);
087:
088: return null;
089: } finally {
090: if (is != null) {
091: try {
092: is.close();
093: } catch (IOException e) {
094: log.log(Level.FINER, "ignoring exception", e);
095: }
096: }
097: }
098: }
099:
100: public Class getFactoryClass(ClassLoader classLoader,
101: String contextPath) throws FactoryConfigurationError {
102: String[] pkgs = contextPath.split(":");
103:
104: for (int i = 0; i < pkgs.length; i++) {
105: String pkg = pkgs[i].replaceAll("\\.",
106: escapeSeparator(File.separator));
107:
108: String fileName = pkg + File.separatorChar
109: + "jaxb.properties";
110:
111: String className = classNameFromPropertiesFile(classLoader,
112: fileName);
113:
114: if (className != null) {
115: try {
116: return classLoader.loadClass(className);
117: } catch (Exception e) {
118: throw new FactoryConfigurationError(e);
119: }
120: }
121: }
122:
123: return getFactoryClass(classLoader);
124: }
125:
126: private static String escapeSeparator(String separator) {
127: if ("\\".equals(separator))
128: return "\\" + separator;
129: else
130: return separator;
131: }
132:
133: public Class getFactoryClass(ClassLoader classLoader)
134: throws FactoryConfigurationError {
135: String className = null;
136:
137: className = System.getProperty(_factoryId);
138:
139: if (className != null && log.isLoggable(Level.FINEST)) {
140: log
141: .finest("got JAXB Context factory className from System property: "
142: + className);
143: }
144:
145: if (className == null) {
146: String fileName = System.getProperty("java.home")
147: + File.separatorChar + "lib" + File.separatorChar
148: + "jaxb.properties";
149:
150: className = classNameFromPropertiesFile(classLoader,
151: fileName);
152:
153: if (className != null && log.isLoggable(Level.FINEST)) {
154: log
155: .finest("got JAXB Context factory className from jaxb.properties: "
156: + className);
157: }
158: }
159:
160: if (className == null) {
161: Class factoryClass = getFactoryClass("META-INF/services/"
162: + _factoryId, classLoader);
163: if (factoryClass != null && log.isLoggable(Level.FINEST)) {
164: log
165: .finest("got JAXB Context factory class from META-INF/services: "
166: + factoryClass.getName());
167: }
168:
169: if (factoryClass != null)
170: return factoryClass;
171: }
172:
173: if (className != null) {
174: try {
175: return classLoader.loadClass(className);
176: } catch (Exception e) {
177: throw new FactoryConfigurationError(e);
178: }
179: }
180:
181: return null;
182: }
183:
184: public Class getFactoryClass(String name, ClassLoader loader) {
185: Class[] providers = getProviderClassList(name, loader);
186:
187: for (int i = 0; i < providers.length; i++) {
188: Class factoryClass;
189:
190: factoryClass = providers[i];
191:
192: if (factoryClass != null)
193: return factoryClass;
194: }
195:
196: return null;
197: }
198:
199: private Class[] getProviderClassList(String service,
200: ClassLoader loader) {
201: Class[] providers = _providerMap.get(loader);
202:
203: if (providers != null)
204: return providers;
205:
206: ArrayList<Class> list = new ArrayList<Class>();
207:
208: try {
209: Enumeration e = loader.getResources(service);
210:
211: while (e.hasMoreElements()) {
212: URL url = (URL) e.nextElement();
213:
214: Class provider = loadProviderClass(url, loader);
215:
216: if (provider != null)
217: list.add(provider);
218: }
219: } catch (Throwable e) {
220: log.log(Level.WARNING, e.toString(), e);
221: }
222:
223: providers = new Class[list.size()];
224: list.toArray(providers);
225:
226: _providerMap.put(loader, providers);
227:
228: return providers;
229: }
230:
231: private Class loadProviderClass(URL url, ClassLoader loader) {
232: InputStream is = null;
233: try {
234: is = url.openStream();
235: int ch;
236:
237: while ((ch = is.read()) >= 0) {
238: if (Character.isWhitespace((char) ch)) {
239: } else if (ch == '#') {
240: for (; ch >= 0 && ch != '\n' && ch != '\r'; ch = is
241: .read()) {
242: }
243: } else {
244: StringBuilder sb = new StringBuilder();
245:
246: for (; ch >= 0
247: && !Character.isWhitespace((char) ch); ch = is
248: .read()) {
249: sb.append((char) ch);
250: }
251:
252: String className = sb.toString();
253:
254: return Class.forName(className, false, loader);
255: }
256: }
257: } catch (Exception e) {
258: log.log(Level.WARNING, e.toString(), e);
259: } finally {
260: try {
261: if (is != null)
262: is.close();
263: } catch (Throwable e) {
264: }
265: }
266:
267: return null;
268: }
269: }
|