001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.config.sys;
018:
019: import org.apache.openejb.OpenEJBException;
020: import org.apache.openejb.config.ConfigUtils;
021: import org.apache.xbean.finder.ResourceFinder;
022: import org.xml.sax.Attributes;
023: import org.xml.sax.InputSource;
024: import org.xml.sax.SAXException;
025: import org.xml.sax.XMLReader;
026: import org.xml.sax.helpers.XMLFilterImpl;
027: import org.xml.sax.helpers.DefaultHandler;
028:
029: import javax.xml.bind.JAXBContext;
030: import javax.xml.bind.JAXBException;
031: import javax.xml.bind.MarshalException;
032: import javax.xml.bind.Marshaller;
033: import javax.xml.bind.Unmarshaller;
034: import javax.xml.bind.ValidationEvent;
035: import javax.xml.bind.ValidationEventHandler;
036: import javax.xml.bind.ValidationException;
037: import javax.xml.parsers.ParserConfigurationException;
038: import javax.xml.parsers.SAXParser;
039: import javax.xml.parsers.SAXParserFactory;
040: import javax.xml.transform.sax.SAXSource;
041: import java.io.ByteArrayOutputStream;
042: import java.io.File;
043: import java.io.FileInputStream;
044: import java.io.FileOutputStream;
045: import java.io.IOException;
046: import java.io.InputStream;
047: import java.io.OutputStream;
048: import java.net.MalformedURLException;
049: import java.net.URL;
050: import java.util.HashMap;
051: import java.util.Map;
052: import java.util.Set;
053: import java.util.TreeSet;
054: import java.util.List;
055:
056: public abstract class JaxbOpenejb {
057: @SuppressWarnings({"unchecked"})
058: public static <T> T create(Class<T> type) {
059: if (type == null)
060: throw new NullPointerException("type is null");
061:
062: if (type == ConnectionManager.class) {
063: return (T) createConnectionManager();
064: } else if (type == Connector.class) {
065: return (T) createConnector();
066: } else if (type == Container.class) {
067: return (T) createContainer();
068: } else if (type == Deployments.class) {
069: return (T) createDeployments();
070: } else if (type == JndiProvider.class) {
071: return (T) createJndiProvider();
072: } else if (type == Openejb.class) {
073: return (T) createOpenejb();
074: } else if (type == ProxyFactory.class) {
075: return (T) createProxyFactory();
076: } else if (type == Resource.class) {
077: return (T) createResource();
078: } else if (type == SecurityService.class) {
079: return (T) createSecurityService();
080: } else if (type == ServiceProvider.class) {
081: return (T) createServiceProvider();
082: } else if (type == ServicesJar.class) {
083: return (T) createServicesJar();
084: } else if (type == TransactionManager.class) {
085: return (T) createTransactionManager();
086: }
087: throw new IllegalArgumentException("Unknown type "
088: + type.getName());
089: }
090:
091: public static <T> T create(String type) {
092: if (type == null)
093: throw new NullPointerException("type is null");
094:
095: if (type.equals("ConnectionManager")) {
096: return (T) createConnectionManager();
097: } else if (type.equals("Connector")) {
098: return (T) createConnector();
099: } else if (type.equals("Container")) {
100: return (T) createContainer();
101: } else if (type.equals("Deployments")) {
102: return (T) createDeployments();
103: } else if (type.equals("JndiProvider")) {
104: return (T) createJndiProvider();
105: } else if (type.equals("Openejb")) {
106: return (T) createOpenejb();
107: } else if (type.equals("ProxyFactory")) {
108: return (T) createProxyFactory();
109: } else if (type.equals("Resource")) {
110: return (T) createResource();
111: } else if (type.equals("SecurityService")) {
112: return (T) createSecurityService();
113: } else if (type.equals("ServiceProvider")) {
114: return (T) createServiceProvider();
115: } else if (type.equals("ServicesJar")) {
116: return (T) createServicesJar();
117: } else if (type.equals("TransactionManager")) {
118: return (T) createTransactionManager();
119: }
120: throw new IllegalArgumentException("Unknown type " + type);
121: }
122:
123: public static ServicesJar readServicesJar(String providerName)
124: throws OpenEJBException {
125: InputStream in = null;
126: URL url = null;
127: try {
128: ResourceFinder finder = new ResourceFinder("META-INF/",
129: Thread.currentThread().getContextClassLoader());
130: url = finder.find(providerName + "/service-jar.xml");
131: in = url.openStream();
132:
133: ServicesJar servicesJar = parseServicesJar(in);
134:
135: // ServicesJar servicesJar = unmarshal(ServicesJar.class, in);
136: return servicesJar;
137: } catch (MalformedURLException e) {
138: throw new OpenEJBException(
139: "Unable to resolve service provider "
140: + providerName, e);
141: } catch (Exception e) {
142: throw new OpenEJBException(
143: "Unable to read OpenEJB service-jar file for provider "
144: + providerName + " at " + url, e);
145: } finally {
146: if (in != null) {
147: try {
148: in.close();
149: } catch (IOException e) {
150: }
151: }
152: }
153: }
154:
155: private static ServicesJar parseServicesJar(InputStream in)
156: throws ParserConfigurationException, SAXException,
157: IOException {
158: InputSource inputSource = new InputSource(in);
159:
160: SAXParserFactory factory = SAXParserFactory.newInstance();
161: factory.setNamespaceAware(true);
162: factory.setValidating(false);
163: SAXParser parser = factory.newSAXParser();
164:
165: final ServicesJar servicesJar1 = new ServicesJar();
166:
167: parser.parse(inputSource, new DefaultHandler() {
168: private ServiceProvider provider;
169: private StringBuilder content;
170:
171: public void startDocument() throws SAXException {
172: }
173:
174: public void startElement(String uri, String localName,
175: String qName, Attributes att) throws SAXException {
176: if (!localName.equals("ServiceProvider"))
177: return;
178:
179: provider = new ServiceProvider();
180: provider.setId(att.getValue("", "id"));
181: provider.setService(att.getValue("", "service"));
182: provider.setFactoryName(att
183: .getValue("", "factory-name"));
184: provider
185: .setConstructor(att.getValue("", "constructor"));
186: provider.setClassName(att.getValue("", "class-name"));
187: String typesString = att.getValue("", "types");
188: if (typesString != null) {
189: ListAdapter listAdapter = new ListAdapter();
190: List<String> types = listAdapter
191: .unmarshal(typesString);
192: provider.getTypes().addAll(types);
193: }
194: servicesJar1.getServiceProvider().add(provider);
195: }
196:
197: public void characters(char ch[], int start, int length)
198: throws SAXException {
199: if (content == null)
200: content = new StringBuilder();
201: content.append(ch, start, length);
202: }
203:
204: public void endElement(String uri, String localName,
205: String qName) throws SAXException {
206: if (provider == null || content == null)
207: return;
208:
209: try {
210: PropertiesAdapter propertiesAdapter = new PropertiesAdapter();
211: provider.getProperties().putAll(
212: propertiesAdapter.unmarshal(content
213: .toString()));
214: } catch (Exception e) {
215: throw new SAXException(e);
216: }
217: provider = null;
218: content = null;
219: }
220: });
221: ServicesJar servicesJar = servicesJar1;
222: return servicesJar;
223: }
224:
225: public static Openejb readConfig(String configFile)
226: throws OpenEJBException {
227: InputStream in = null;
228: try {
229: if (configFile.startsWith("jar:")) {
230: URL url = new URL(configFile);
231: in = url.openStream();
232: } else if (configFile.startsWith("file:")) {
233: URL url = new URL(configFile);
234: in = url.openStream();
235: } else {
236: in = new FileInputStream(configFile);
237: }
238: Openejb openejb = unmarshal(Openejb.class, in);
239: return openejb;
240: } catch (MalformedURLException e) {
241: throw new OpenEJBException("Unable to resolve location "
242: + configFile, e);
243: } catch (Exception e) {
244: throw new OpenEJBException(
245: "Unable to read OpenEJB configuration file at "
246: + configFile, e);
247: } finally {
248: if (in != null) {
249: try {
250: in.close();
251: } catch (IOException e) {
252: }
253: }
254: }
255: }
256:
257: public static void writeConfig(String configFile, Openejb openejb)
258: throws OpenEJBException {
259: OutputStream out = null;
260: try {
261: File file = new File(configFile);
262: out = new FileOutputStream(file);
263: marshal(Openejb.class, openejb, out);
264: } catch (IOException e) {
265: throw new OpenEJBException(ConfigUtils.messages.format(
266: "conf.1040", configFile, e.getLocalizedMessage()),
267: e);
268: } catch (MarshalException e) {
269: if (e.getCause() instanceof IOException) {
270: throw new OpenEJBException(ConfigUtils.messages.format(
271: "conf.1040", configFile, e
272: .getLocalizedMessage()), e);
273: } else {
274: throw new OpenEJBException(ConfigUtils.messages.format(
275: "conf.1050", configFile, e
276: .getLocalizedMessage()), e);
277: }
278: } catch (ValidationException e) {
279: /* TODO: Implement informative error handling here.
280: The exception will say "X doesn't match the regular
281: expression Y"
282: This should be checked and more relevant information
283: should be given -- not everyone understands regular
284: expressions.
285: */
286: /* NOTE: This doesn't seem to ever happen. When the object graph
287: * is invalid, the MarshalException is thrown, not this one as you
288: * would think.
289: */
290: throw new OpenEJBException(ConfigUtils.messages.format(
291: "conf.1060", configFile, e.getLocalizedMessage()),
292: e);
293: } catch (JAXBException e) {
294: throw new OpenEJBException(e);
295: } finally {
296: if (out != null) {
297: try {
298: out.close();
299: } catch (Exception e) {
300: }
301: }
302: }
303: }
304:
305: public static final ThreadLocal<Set<String>> currentPublicId = new ThreadLocal<Set<String>>();
306:
307: private static Map<Class, JAXBContext> jaxbContexts = new HashMap<Class, JAXBContext>();
308:
309: public static <T> String marshal(Class<T> type, Object object)
310: throws JAXBException {
311: ByteArrayOutputStream baos = new ByteArrayOutputStream();
312:
313: marshal(type, object, baos);
314:
315: return new String(baos.toByteArray());
316: }
317:
318: public static <T> void marshal(Class<T> type, Object object,
319: OutputStream out) throws JAXBException {
320: JAXBContext jaxbContext = getContext(type);
321: Marshaller marshaller = jaxbContext.createMarshaller();
322:
323: marshaller.setProperty("jaxb.formatted.output", true);
324:
325: marshaller.marshal(object, out);
326: }
327:
328: private static <T> JAXBContext getContext(Class<T> type)
329: throws JAXBException {
330: JAXBContext jaxbContext = jaxbContexts.get(type);
331: if (jaxbContext == null) {
332: jaxbContext = JAXBContext.newInstance(type);
333: jaxbContexts.put(type, jaxbContext);
334: }
335: return jaxbContext;
336: }
337:
338: @SuppressWarnings({"unchecked"})
339: public static <T> T unmarshal(Class<T> type, InputStream in)
340: throws ParserConfigurationException, SAXException,
341: JAXBException {
342: InputSource inputSource = new InputSource(in);
343:
344: SAXParserFactory factory = SAXParserFactory.newInstance();
345: factory.setNamespaceAware(true);
346: factory.setValidating(false);
347: SAXParser parser = factory.newSAXParser();
348:
349: JAXBContext ctx = getContext(type);
350: Unmarshaller unmarshaller = ctx.createUnmarshaller();
351: unmarshaller.setEventHandler(new ValidationEventHandler() {
352: public boolean handleEvent(ValidationEvent validationEvent) {
353: System.out.println(validationEvent);
354: return false;
355: }
356: });
357:
358: NamespaceFilter xmlFilter = new NamespaceFilter(parser
359: .getXMLReader());
360: xmlFilter.setContentHandler(unmarshaller
361: .getUnmarshallerHandler());
362:
363: SAXSource source = new SAXSource(xmlFilter, inputSource);
364:
365: currentPublicId.set(new TreeSet<String>());
366: try {
367: return (T) unmarshaller.unmarshal(source);
368: } finally {
369: currentPublicId.set(null);
370: }
371: }
372:
373: public static class NamespaceFilter extends XMLFilterImpl {
374:
375: public NamespaceFilter(XMLReader xmlReader) {
376: super (xmlReader);
377: }
378:
379: public InputSource resolveEntity(String publicId,
380: String systemId) throws SAXException, IOException {
381: Set<String> publicIds = currentPublicId.get();
382: if (publicIds != null) {
383: publicIds.add(publicId);
384: }
385: return super .resolveEntity(publicId, systemId);
386: }
387:
388: public void startElement(String uri, String localName,
389: String qname, Attributes atts) throws SAXException {
390: super .startElement(
391: "http://www.openejb.org/System/Configuration",
392: localName, qname, atts);
393: }
394: }
395:
396: public static ConnectionManager createConnectionManager() {
397: return new ConnectionManager();
398: }
399:
400: public static Connector createConnector() {
401: return new Connector();
402: }
403:
404: public static Container createContainer() {
405: return new Container();
406: }
407:
408: public static Deployments createDeployments() {
409: return new Deployments();
410: }
411:
412: public static JndiProvider createJndiProvider() {
413: return new JndiProvider();
414: }
415:
416: public static Openejb createOpenejb() {
417: return new Openejb();
418: }
419:
420: public static ProxyFactory createProxyFactory() {
421: return new ProxyFactory();
422: }
423:
424: public static Resource createResource() {
425: return new Resource();
426: }
427:
428: public static SecurityService createSecurityService() {
429: return new SecurityService();
430: }
431:
432: public static ServiceProvider createServiceProvider() {
433: return new ServiceProvider();
434: }
435:
436: public static ServicesJar createServicesJar() {
437: return new ServicesJar();
438: }
439:
440: public static TransactionManager createTransactionManager() {
441: return new TransactionManager();
442: }
443: }
|