blob: adbcf9a3761f7e7f68aa12ca63c5e5e63eec345f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.config.sys;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.jee.JAXBContextFactory;
import org.apache.openejb.config.ConfigUtils;
import org.apache.xbean.finder.ResourceFinder;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.MarshalException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.ValidationException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.List;
public abstract class JaxbOpenejb {
@SuppressWarnings({"unchecked"})
public static <T> T create(Class<T> type) {
if (type == null) throw new NullPointerException("type is null");
if (type == ConnectionManager.class) {
return (T) createConnectionManager();
} else if (type == Connector.class) {
return (T) createConnector();
} else if (type == Container.class) {
return (T) createContainer();
} else if (type == Deployments.class) {
return (T) createDeployments();
} else if (type == JndiProvider.class) {
return (T) createJndiProvider();
} else if (type == Openejb.class) {
return (T) createOpenejb();
} else if (type == ProxyFactory.class) {
return (T) createProxyFactory();
} else if (type == Resource.class) {
return (T) createResource();
} else if (type == SecurityService.class) {
return (T) createSecurityService();
} else if (type == ServiceProvider.class) {
return (T) createServiceProvider();
} else if (type == ServicesJar.class) {
return (T) createServicesJar();
} else if (type == TransactionManager.class) {
return (T) createTransactionManager();
}
throw new IllegalArgumentException("Unknown type " + type.getName());
}
public static <T> T create(String type) {
if (type == null) throw new NullPointerException("type is null");
if (type.equals("ConnectionManager")) {
return (T) createConnectionManager();
} else if (type.equals("Connector")) {
return (T) createConnector();
} else if (type.equals("Container")) {
return (T) createContainer();
} else if (type.equals("Deployments")) {
return (T) createDeployments();
} else if (type.equals("JndiProvider")) {
return (T) createJndiProvider();
} else if (type.equals("Openejb")) {
return (T) createOpenejb();
} else if (type.equals("ProxyFactory")) {
return (T) createProxyFactory();
} else if (type.equals("Resource")) {
return (T) createResource();
} else if (type.equals("SecurityService")) {
return (T) createSecurityService();
} else if (type.equals("ServiceProvider")) {
return (T) createServiceProvider();
} else if (type.equals("ServicesJar")) {
return (T) createServicesJar();
} else if (type.equals("TransactionManager")) {
return (T) createTransactionManager();
}
throw new IllegalArgumentException("Unknown type " + type);
}
public static ServicesJar readServicesJar(String providerName) throws OpenEJBException {
InputStream in = null;
URL url = null;
try {
ResourceFinder finder = new ResourceFinder("META-INF/", Thread.currentThread().getContextClassLoader());
String resourceName = providerName + "/service-jar.xml";
try {
url = finder.find(resourceName);
} catch (IOException e) {
//Make sure the default service-jar shipped with openejb-core could be read
finder = new ResourceFinder("META-INF/", JaxbOpenejb.class.getClassLoader());
url = finder.find(resourceName);
}
in = url.openStream();
ServicesJar servicesJar = parseServicesJar(in);
return servicesJar;
} catch (MalformedURLException e) {
throw new OpenEJBException("Unable to resolve service provider " + providerName, e);
} catch (Exception e) {
throw new OpenEJBException("Unable to read OpenEJB service-jar file for provider " + providerName + " at " + url, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
}
private static ServicesJar parseServicesJar(InputStream in) throws ParserConfigurationException, SAXException, IOException {
InputSource inputSource = new InputSource(in);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
SAXParser parser = factory.newSAXParser();
final ServicesJar servicesJar1 = new ServicesJar();
parser.parse(inputSource, new DefaultHandler(){
private ServiceProvider provider;
private StringBuilder content;
public void startDocument() throws SAXException {
}
public void startElement(String uri, String localName, String qName, Attributes att) throws SAXException {
if (!localName.equals("ServiceProvider")) return;
provider = new ServiceProvider();
provider.setId(att.getValue("","id"));
provider.setService(att.getValue("","service"));
provider.setFactoryName(att.getValue("","factory-name"));
provider.setConstructor(att.getValue("","constructor"));
provider.setClassName(att.getValue("","class-name"));
String typesString = att.getValue("", "types");
if (typesString != null){
ListAdapter listAdapter = new ListAdapter();
List<String> types = listAdapter.unmarshal(typesString);
provider.getTypes().addAll(types);
}
servicesJar1.getServiceProvider().add(provider);
}
public void characters(char ch[], int start, int length) throws SAXException {
if (content == null) content = new StringBuilder();
content.append(ch, start, length);
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (provider == null || content == null) return;
try {
PropertiesAdapter propertiesAdapter = new PropertiesAdapter();
provider.getProperties().putAll(propertiesAdapter.unmarshal(content.toString()));
} catch (Exception e) {
throw new SAXException(e);
}
provider = null;
content = null;
}
});
ServicesJar servicesJar = servicesJar1;
return servicesJar;
}
public static Openejb readConfig(String configFile) throws OpenEJBException {
InputStream in = null;
try {
if (configFile.startsWith("jar:")) {
URL url = new URL(configFile);
in = url.openStream();
} else if (configFile.startsWith("file:")) {
URL url = new URL(configFile);
in = url.openStream();
} else {
in = new FileInputStream(configFile);
}
Openejb openejb = unmarshal(Openejb.class, in);
return openejb;
} catch (MalformedURLException e) {
throw new OpenEJBException("Unable to resolve location " + configFile, e);
} catch (Exception e) {
throw new OpenEJBException("Unable to read OpenEJB configuration file at " + configFile, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
}
public static void writeConfig(String configFile, Openejb openejb) throws OpenEJBException {
OutputStream out = null;
try {
File file = new File(configFile);
out = new FileOutputStream(file);
marshal(Openejb.class, openejb, out);
} catch (IOException e) {
throw new OpenEJBException(ConfigUtils.messages.format("conf.1040", configFile, e.getLocalizedMessage()), e);
} catch (MarshalException e) {
if (e.getCause() instanceof IOException) {
throw new OpenEJBException(ConfigUtils.messages.format("conf.1040", configFile, e.getLocalizedMessage()), e);
} else {
throw new OpenEJBException(ConfigUtils.messages.format("conf.1050", configFile, e.getLocalizedMessage()), e);
}
} catch (ValidationException e) {
/* TODO: Implement informative error handling here.
The exception will say "X doesn't match the regular
expression Y"
This should be checked and more relevant information
should be given -- not everyone understands regular
expressions.
*/
/* NOTE: This doesn't seem to ever happen. When the object graph
* is invalid, the MarshalException is thrown, not this one as you
* would think.
*/
throw new OpenEJBException(ConfigUtils.messages.format("conf.1060", configFile, e.getLocalizedMessage()), e);
} catch (JAXBException e) {
throw new OpenEJBException(e);
} finally {
if (out != null) {
try {
out.close();
} catch (Exception e) {
}
}
}
}
public static final ThreadLocal<Set<String>> currentPublicId = new ThreadLocal<Set<String>>();
private static Map<Class, JAXBContext> jaxbContexts = new HashMap<Class, JAXBContext>();
public static <T> String marshal(Class<T> type, Object object) throws JAXBException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
marshal(type, object, baos);
return new String(baos.toByteArray());
}
public static <T> void marshal(Class<T> type, Object object, OutputStream out) throws JAXBException {
JAXBContext jaxbContext = getContext(type);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty("jaxb.formatted.output", true);
marshaller.marshal(object, out);
}
private static <T> JAXBContext getContext(Class<T> type) throws JAXBException {
JAXBContext jaxbContext = jaxbContexts.get(type);
if (jaxbContext == null) {
jaxbContext = JAXBContextFactory.newInstance(type);
jaxbContexts.put(type, jaxbContext);
}
return jaxbContext;
}
public static <T> T unmarshal(Class<T> type, InputStream in, boolean filter) throws ParserConfigurationException, SAXException, JAXBException {
InputSource inputSource = new InputSource(in);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
SAXParser parser = factory.newSAXParser();
JAXBContext ctx = getContext(type);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
public boolean handleEvent(ValidationEvent validationEvent) {
System.out.println(validationEvent);
return false;
}
});
SAXSource source;
if (filter) {
NamespaceFilter xmlFilter = new NamespaceFilter(parser.getXMLReader());
xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
source = new SAXSource(xmlFilter, inputSource);
} else {
source = new SAXSource(inputSource);
}
currentPublicId.set(new TreeSet<String>());
try {
return unmarshaller.unmarshal(source, type).getValue();
} finally {
currentPublicId.set(null);
}
}
@SuppressWarnings({"unchecked"})
public static <T> T unmarshal(Class<T> type, InputStream in) throws ParserConfigurationException, SAXException, JAXBException {
return unmarshal(type, in, true);
}
public static class NamespaceFilter extends XMLFilterImpl {
public NamespaceFilter(XMLReader xmlReader) {
super(xmlReader);
}
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
Set<String> publicIds = currentPublicId.get();
if (publicIds != null) {
publicIds.add(publicId);
}
return super.resolveEntity(publicId, systemId);
}
public void startElement(String uri, String localName, String qname, Attributes atts) throws SAXException {
super.startElement("http://www.openejb.org/System/Configuration", localName, qname, atts);
}
}
public static ConnectionManager createConnectionManager() {
return new ConnectionManager();
}
public static Connector createConnector() {
return new Connector();
}
public static Container createContainer() {
return new Container();
}
public static Deployments createDeployments() {
return new Deployments();
}
public static JndiProvider createJndiProvider() {
return new JndiProvider();
}
public static Openejb createOpenejb() {
return new Openejb();
}
public static ProxyFactory createProxyFactory() {
return new ProxyFactory();
}
public static Resource createResource() {
return new Resource();
}
public static SecurityService createSecurityService() {
return new SecurityService();
}
public static ServiceProvider createServiceProvider() {
return new ServiceProvider();
}
public static ServicesJar createServicesJar() {
return new ServicesJar();
}
public static TransactionManager createTransactionManager() {
return new TransactionManager();
}
}