001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: * Based on mnl's Java utilities.
020: *
021: * $Id: ServiceMgmt.java,v 1.2 2006/09/29 12:32:08 drmlipp Exp $
022: *
023: * $Log: ServiceMgmt.java,v $
024: * Revision 1.2 2006/09/29 12:32:08 drmlipp
025: * Consistently using WfMOpen as projct name now.
026: *
027: * Revision 1.1.1.2 2003/12/19 13:01:36 drmlipp
028: * Updated to 1.1rc1
029: *
030: * Revision 1.5 2003/11/21 14:47:32 lipp
031: * Fixed debugging output.
032: *
033: * Revision 1.4 2003/06/27 08:51:47 lipp
034: * Fixed copyright/license information.
035: *
036: * Revision 1.3 2003/03/31 16:50:27 huaiyang
037: * Logging using common-logging.
038: *
039: * Revision 1.2 2002/09/18 20:47:27 lipp
040: * Thread relative class loading and new warning message.
041: *
042: * Revision 1.1 2002/09/15 12:06:44 lipp
043: * Renamed ServiceLookup to ServiceMgmt.
044: *
045: * Revision 1.6 2002/08/17 11:11:01 lipp
046: * Added workaround for buggy classloaders (and some debug logs).
047: *
048: * Revision 1.5 2002/06/24 17:34:40 lipp
049: * Undone fix of resource path.
050: *
051: * Revision 1.4 2002/06/24 17:30:05 lipp
052: * Fixed resource path.
053: *
054: * Revision 1.3 2002/06/13 15:32:37 lipp
055: * Fixed scope.
056: *
057: * Revision 1.2 2002/06/07 12:27:07 lipp
058: * Added logger.
059: *
060: * Revision 1.1 2001/11/21 13:28:57 lipp
061: * UserPrefsService design refined.
062: *
063: */
064:
065: package de.danet.an.util;
066:
067: import java.io.BufferedReader;
068: import java.io.IOException;
069: import java.io.InputStreamReader;
070:
071: import java.util.ArrayList;
072: import java.util.Enumeration;
073: import java.util.List;
074: import java.util.Vector;
075:
076: import java.net.URL;
077:
078: /**
079: * Class with convenience functions for service related tasks.
080: */
081: public class ServiceMgmt {
082:
083: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
084: .getLog(ServiceMgmt.class);
085:
086: /**
087: * Find all service providers (factories) defined in
088: * <code>META-INF/services</code> directories of all jars in the
089: * classpath. See the JAR specification for details.
090: *
091: * @param service The class of the service, used to construct the file
092: * name as
093: * <code>META-INF/services/<i>service.getName()</i></code> and to verify
094: * the classes specified in those files
095: * (must be derived from <code>service</code>).
096: * @return A list of classes that implement <code>service</code>.
097: */
098: public static List providerClassesFromJARs(Class service) {
099: ClassLoader cl = Thread.currentThread().getContextClassLoader();
100: List res = new ArrayList();
101:
102: try {
103: String serviceDef = "META-INF/services/"
104: + service.getName();
105: if (logger.isDebugEnabled()) {
106: logger.debug("Looking up service definition as \""
107: + serviceDef + "\", using ClassLoader " + cl);
108: Debug.dumpClassLoaders(logger, cl);
109: }
110: Enumeration urls = cl.getResources(serviceDef);
111: // there are buggy classloaders that do not implement
112: // getResources properly. As a workaround, we make an
113: // additional call to getResource if getResources returns
114: // an empty result.
115: if (!urls.hasMoreElements()) {
116: Object r = cl.getResource(serviceDef);
117: if (r != null) {
118: Vector v = new Vector(1);
119: v.add(r);
120: urls = v.elements();
121: }
122: }
123: while (urls.hasMoreElements()) {
124: URL url = (URL) urls.nextElement();
125: logger.debug("Found service definition in " + url);
126: BufferedReader data = new BufferedReader(
127: new InputStreamReader(url.openStream(), "UTF-8"));
128: while (true) {
129: String line = data.readLine();
130: if (line == null) {
131: break;
132: }
133:
134: int hashIdx = line.indexOf('#');
135: if (hashIdx >= 0) {
136: line = line.substring(0, hashIdx);
137: }
138: line = line.trim();
139: if (line.length() == 0) {
140: continue;
141: }
142: try {
143: logger.debug("... trying class " + line);
144: Class c = cl.loadClass(line);
145: if (service.isAssignableFrom(c)) {
146: logger.debug("... adding class " + line);
147: res.add(c);
148: }
149: } catch (Exception e) {
150: logger.warn(
151: "Class defined as service provider "
152: + "but not loadable: "
153: + e.getMessage(), e);
154: }
155: }
156: }
157: } catch (IOException ioe) {
158: }
159:
160: return res;
161: }
162:
163: }
|