/*
* 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.synapse.config.xml;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.SynapseException;
import org.apache.synapse.config.SynapseConfiguration;
import org.apache.synapse.config.XMLToObjectMapper;
import sun.misc.Service;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
/**
* This class is based on J2SE Service Provider model
* http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider
* <p/>
* It deals with both the problem of turning an XML into a Synapse config and vice-versa
*/
public class ConfigurationFactoryAndSerializerFinder implements XMLToObjectMapper {
private static final Log log = LogFactory
.getLog(ConfigurationFactoryAndSerializerFinder.class);
private static final Class[] configurationFactories = {
SynapseXMLConfigurationFactory.class,
};
private final static ConfigurationFactoryAndSerializerFinder instance =
new ConfigurationFactoryAndSerializerFinder();
/**
* A map of mediator QNames to implementation class
*/
private final static Map<QName,Class> factoryMap = new HashMap<QName,Class>();
private final static Map<QName,Class> serializerMap = new HashMap<QName,Class>();
private static boolean initialized = false;
public static synchronized ConfigurationFactoryAndSerializerFinder getInstance() {
if (!initialized) {
loadConfigurationFatoriesAndSerializers();
}
return instance;
}
/**
* Force re initialization next time
*/
public static synchronized void reset() {
factoryMap.clear();
serializerMap.clear();
initialized = false;
}
private ConfigurationFactoryAndSerializerFinder() {
}
private void handleException(String msg) {
log.error(msg);
throw new SynapseException(msg);
}
private static void loadConfigurationFatoriesAndSerializers() {
for (Class c : configurationFactories) {
if (c != null) {
try {
ConfigurationFactory fac = (ConfigurationFactory) c.newInstance();
factoryMap.put(fac.getTagQName(), c);
serializerMap.put(fac.getTagQName(), fac.getSerializerClass());
} catch (Exception e) {
throw new SynapseException("Error instantiating " + c.getName(), e);
}
}
}
// now iterate through the available plugable mediator factories
registerExtensions();
initialized = true;
}
/**
* Register plugable mediator factories from the classpath
* <p/>
* This looks for JAR files containing a META-INF/services that adheres to the following
* http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider
*/
private static void registerExtensions() {
// register MediatorFactory extensions
Iterator it = Service.providers(ConfigurationFactory.class);
while (it.hasNext()) {
ConfigurationFactory cf = (ConfigurationFactory) it.next();
QName tag = cf.getTagQName();
factoryMap.put(tag, cf.getClass());
serializerMap.put(tag, cf.getSerializerClass());
if (log.isDebugEnabled()) {
log.debug("Added MediatorFactory " + cf.getClass() + " to handle " + tag);
}
}
}
/**
* This method returns a Processor given an OMElement. This will be used
* recursively by the elements which contain processor elements themselves
* (e.g. rules)
*
* @param element
* @return Processor
*/
public SynapseConfiguration getConfiguration(OMElement element, Properties properties) {
String localName = element.getLocalName();
QName qName;
if (element.getNamespace() != null) {
qName = new QName(element.getNamespace().getNamespaceURI(), localName);
} else {
qName = new QName(localName);
}
if (log.isDebugEnabled()) {
log.debug("getConfiguration(" + qName + ")");
}
Class cls = factoryMap.get(qName);
if (cls == null) {
String msg = "Unknown Configuration type " +
"referenced by configuration element : " + qName;
log.error(msg);
throw new SynapseException(msg);
}
try {
ConfigurationFactory cf = (ConfigurationFactory) cls.newInstance();
return cf.getConfiguration(element, properties);
} catch (InstantiationException e) {
String msg = "Error initializing configuration factory : " + cls;
log.error(msg);
throw new SynapseException(msg, e);
} catch (IllegalAccessException e) {
String msg = "Error initializing configuration factory : " + cls;
log.error(msg);
throw new SynapseException(msg, e);
}
}
/**
* @param synCfg
* @return
*/
public static OMElement serializeConfiguration(SynapseConfiguration synCfg) {
if (synCfg.getDefaultQName() == null) {
return serializeConfiguration(synCfg, XMLConfigConstants.DEFINITIONS_ELT);
} else {
return serializeConfiguration(synCfg, synCfg.getDefaultQName());
}
}
/**
* This method will serialize the config using the supplied QName
* (looking up the right class to do it)
*
* @param synCfg
* @param qName
* @throws XMLStreamException
*/
public static OMElement serializeConfiguration(SynapseConfiguration synCfg, QName qName) {
Class cls = (Class) serializerMap.get(qName);
if (cls == null) {
String msg = "Unknown Configuration type " +
"referenced by configuration element : " + qName;
log.error(msg);
throw new SynapseException(msg);
}
try {
ConfigurationSerializer cs = (ConfigurationSerializer) cls.newInstance();
return cs.serializeConfiguration(synCfg);
} catch (InstantiationException e) {
String msg = "Error initializing configuration factory : " + cls;
log.error(msg);
throw new SynapseException(msg, e);
} catch (IllegalAccessException e) {
String msg = "Error initializing configuration factory : " + cls;
log.error(msg);
throw new SynapseException(msg, e);
}
}
/**
* This method exposes all the ConfigurationFactories and its Extensions
*
* @return Map of factories
*/
public Map getFactoryMap() {
return factoryMap;
}
/**
* This method exposes all the ConfigurationSerializer and its Extensions
*
* @return Map of serializers
*/
public static Map getSerializerMap() {
return serializerMap;
}
/**
* Allow the mediator factory finder to act as an XMLToObjectMapper for Mediators
* (i.e. Sequence Mediator) loaded dynamically from a Registry
*
* @param om configuration from which the object is built
* @param properties bag of properties to pass in any information to the factory
* @return built object
*/
public Object getObjectFromOMNode(OMNode om, Properties properties) {
if (om instanceof OMElement) {
return getConfiguration((OMElement) om, properties);
} else {
handleException("Invalid configuration XML : " + om);
}
return null;
}
}