001: package org.objectweb.celtix.jbi.se;
002:
003: import java.io.File;
004: import java.lang.reflect.Modifier;
005: import java.net.MalformedURLException;
006: import java.net.URL;
007: import java.net.URLClassLoader;
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.List;
011: import java.util.logging.Level;
012: import java.util.logging.Logger;
013:
014: import javax.jbi.component.ComponentContext;
015: import javax.jws.WebService;
016: import javax.xml.namespace.QName;
017: import javax.xml.parsers.DocumentBuilder;
018: import javax.xml.parsers.DocumentBuilderFactory;
019:
020: import org.w3c.dom.Document;
021: import org.w3c.dom.Element;
022: import org.w3c.dom.Node;
023: import org.w3c.dom.NodeList;
024:
025: import org.objectweb.celtix.Bus;
026: import org.objectweb.celtix.bus.jaxws.EndpointImpl;
027: import org.objectweb.celtix.jbi.ServiceConsumer;
028:
029: /**
030: * Wraps a Celtix service or client.
031: */
032: public class CeltixServiceUnit {
033:
034: private static final Logger LOG = Logger
035: .getLogger(CeltixServiceUnit.class.getName());
036:
037: private final Bus bus;
038:
039: private Object serviceImplementation;
040: private ServiceConsumer serviceConsumer;
041: private EndpointImpl endpoint;
042: private final String rootPath;
043: private final ClassLoader parentLoader;
044: private boolean isProvider;
045: private QName serviceName;
046: private String endpointName;
047:
048: public CeltixServiceUnit(Bus b, String path,
049: ComponentClassLoader parent) {
050:
051: URL url = null;
052: try {
053: url = new File(path + File.separator).toURL();
054:
055: } catch (MalformedURLException ex) {
056: LOG.log(Level.SEVERE, "failed to initialize service unit",
057: ex);
058: }
059: bus = b;
060: rootPath = path;
061: parent.addResource(url);
062: parentLoader = parent;
063: parseJbiDescriptor();
064: }
065:
066: public boolean isServiceProvider() {
067: return isProvider;
068: }
069:
070: public void stop() {
071: if (endpoint != null) {
072: endpoint.stop();
073: } else {
074: serviceConsumer.stop();
075: }
076: }
077:
078: public QName getServiceName() {
079:
080: QName ret = null;
081:
082: if (isServiceProvider()) {
083: if (serviceName == null) {
084: WebService ws = (WebService) serviceImplementation
085: .getClass().getAnnotation(WebService.class);
086: serviceName = new QName(ws.targetNamespace(), ws
087: .serviceName());
088: }
089: ret = serviceName;
090: }
091: return ret;
092: }
093:
094: public String getEndpointName() {
095: return endpointName;
096: }
097:
098: public void prepare(ComponentContext ctx) {
099:
100: try {
101: WebServiceClassFinder finder = new WebServiceClassFinder(
102: rootPath, parentLoader);
103: Collection<Class<?>> classes = finder
104: .findWebServiceClasses();
105: if (classes.size() > 0) {
106: LOG.info("publishing endpoint");
107: isProvider = true;
108: Class<?> clz = classes.iterator().next();
109: serviceImplementation = clz.newInstance();
110: endpoint = new EndpointImpl(bus, serviceImplementation,
111: null);
112: // dummy endpoint to publish on
113: endpoint.publish("http://foo/bar/baz");
114: } else {
115: LOG.info("starting consumer");
116: classes = finder.findServiceConsumerClasses();
117: Class<?> clz = classes.iterator().next();
118: LOG.fine("starting consumer: " + clz);
119: serviceConsumer = (ServiceConsumer) clz.newInstance();
120: serviceConsumer.setComponentContext(ctx);
121: new Thread(serviceConsumer).start();
122: }
123: } catch (Exception ex) {
124: if (ex.getCause() != null) {
125: ex = (Exception) ex.getCause();
126: }
127: LOG.log(Level.SEVERE, "failed to publish endpoint", ex);
128: // TODO throw decent exception here
129: //throw new RuntimeException(ex);
130: }
131: }
132:
133: public ClassLoader getClassLoader() {
134: return parentLoader;
135: }
136:
137: Document getWsdlAsDocument() {
138:
139: Document doc = null;
140: try {
141: WebService ws = serviceImplementation.getClass()
142: .getAnnotation(WebService.class);
143: if (ws != null) {
144: DocumentBuilderFactory factory = DocumentBuilderFactory
145: .newInstance();
146: factory.setNamespaceAware(true);
147: DocumentBuilder builder = factory.newDocumentBuilder();
148: doc = builder.parse(ws.wsdlLocation());
149: } else {
150: LOG.severe("could not get WebService annotation from "
151: + serviceImplementation);
152: }
153: } catch (Exception ex) {
154: ex.printStackTrace();
155: }
156: return doc;
157: }
158:
159: static class WebServiceClassFinder {
160: private final String rootPath;
161: private final ClassLoader parent;
162:
163: public WebServiceClassFinder(String argRootPath,
164: ClassLoader loader) {
165: if (argRootPath.endsWith(File.separator)) {
166: argRootPath = argRootPath.substring(0, argRootPath
167: .length() - 2);
168: }
169: rootPath = argRootPath;
170: parent = loader;
171: }
172:
173: public Collection<Class<?>> findServiceConsumerClasses()
174: throws MalformedURLException {
175: return find(new Matcher() {
176: public boolean accept(Class<?> clz) {
177: return ServiceConsumer.class.isAssignableFrom(clz)
178: && (clz.getModifiers() & Modifier.ABSTRACT) == 0;
179: }
180: });
181: }
182:
183: public Collection<Class<?>> findWebServiceClasses()
184: throws MalformedURLException {
185:
186: return find(new Matcher() {
187: public boolean accept(Class<?> clz) {
188: return clz.getAnnotation(WebService.class) != null
189: && (clz.getModifiers() & Modifier.ABSTRACT) == 0;
190: }
191: });
192: }
193:
194: private Collection<Class<?>> find(Matcher matcher)
195: throws MalformedURLException {
196: List<Class<?>> classes = new ArrayList<Class<?>>();
197:
198: File root = new File(rootPath);
199: URL[] urls = { root.toURL() };
200: URLClassLoader loader = new URLClassLoader(urls, parent);
201:
202: find(root, loader, classes, matcher);
203: return classes;
204: }
205:
206: private void find(File dir, ClassLoader loader,
207: Collection<Class<?>> classes, Matcher matcher) {
208:
209: File[] files = dir.listFiles();
210: for (File f : files) {
211: if (f.toString().endsWith(".class")) {
212: Class<?> clz = loadClass(loader, f);
213: if (matcher.accept(clz)) {
214: classes.add(clz);
215: }
216: } else if (f.isDirectory()) {
217: find(f, loader, classes, matcher);
218: }
219: }
220: }
221:
222: private Class<?> loadClass(ClassLoader loader, File classFile) {
223:
224: String fileName = classFile.toString();
225: String className = fileName
226: .substring(rootPath.length() + 1);
227: className = className.substring(0,
228: className.length() - ".class".length()).replace(
229: File.separatorChar, '.');
230:
231: try {
232: return loader.loadClass(className);
233: } catch (ClassNotFoundException ex) {
234: LOG.severe("failed to load class: " + className);
235: }
236: return null;
237: }
238:
239: interface Matcher {
240: boolean accept(Class<?> clz);
241: }
242: }
243:
244: private void parseJbiDescriptor() {
245:
246: // right now, all we are interested in is an endpoint name
247: // from the jbi dd.
248: File metaInf = new File(rootPath, "META-INF");
249: File jbiXml = new File(metaInf, "jbi.xml");
250: try {
251: DocumentBuilderFactory factory = DocumentBuilderFactory
252: .newInstance();
253: factory.setNamespaceAware(true);
254: DocumentBuilder builder = factory.newDocumentBuilder();
255: Document doc = builder.parse(jbiXml.toURL().toString());
256:
257: Element providesEl = (Element) findNode(doc
258: .getDocumentElement(), "provides");
259: endpointName = providesEl.getAttribute("endpoint-name");
260: } catch (Exception ex) {
261: LOG.log(Level.SEVERE, "error parsing " + jbiXml, ex);
262: }
263:
264: }
265:
266: private Node findNode(Node root, String name) {
267:
268: if (name.equals(root.getNodeName())) {
269: return root;
270: }
271:
272: NodeList children = root.getChildNodes();
273: for (int i = 0; i < children.getLength(); i++) {
274: Node child = children.item(i);
275: Node found = findNode(child, name);
276: if (found != null) {
277: return found;
278: }
279: }
280: return null;
281: }
282:
283: }
|