/*
* 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 java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.xml.namespace.QName;
import org.apache.axiom.om.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.SynapseException;
import org.apache.synapse.Startup;
import org.apache.synapse.config.XMLToObjectMapper;
import org.apache.synapse.startup.quartz.SimpleQuartzFactory;
import sun.misc.Service;
public class StartupFinder implements XMLToObjectMapper {
private static final Log log = LogFactory
.getLog(ConfigurationFactoryAndSerializerFinder.class);
private final static StartupFinder instance = new StartupFinder();
/**
* A map of mediator QNames to implementation class
*/
private static Map<QName,Class<? extends StartupFactory>> factoryMap
= new HashMap<QName,Class<? extends StartupFactory>>();
private static Map<QName,Class<? extends StartupSerializer>> serializerMap
= new HashMap<QName,Class<? extends StartupSerializer>>();
private static boolean initialized = false;
public static synchronized StartupFinder getInstance() {
if (!initialized) {
loadStartups();
}
return instance;
}
/**
* Force re initialization next time
*/
public static synchronized void reset() {
factoryMap.clear();
serializerMap.clear();
initialized = false;
}
private static final Class<?>[] builtins = {SimpleQuartzFactory.class};
private StartupFinder() {
}
private static void loadStartups() {
// preregister any built in
for (Class<?> builtin : builtins) {
if (builtin != null) {
Class<? extends StartupFactory> b = builtin.asSubclass(StartupFactory.class);
StartupFactory sf;
try {
sf = b.newInstance();
} catch (Exception e) {
throw new SynapseException("cannot instantiate " + b.getName(), e);
}
factoryMap.put(sf.getTagQName(), b);
serializerMap.put(sf.getTagQName(), sf.getSerializerClass());
}
}
registerExtensions();
initialized = true;
}
private void handleException(String msg) {
log.error(msg);
throw new SynapseException(msg);
}
/**
* Register pluggable 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() {
// log.debug("Registering mediator extensions found in the classpath : "
// + System.getResource("java.class.path"));
// register MediatorFactory extensions
Iterator<?> it = Service.providers(StartupFactory.class);
while (it.hasNext()) {
StartupFactory sf = (StartupFactory) it.next();
QName tag = sf.getTagQName();
factoryMap.put(tag, sf.getClass());
serializerMap.put(tag, sf.getSerializerClass());
if (log.isDebugEnabled()) {
log.debug("Added StartupFactory " + sf.getClass()
+ " to handle " + tag);
}
}
}
/**
* Check whether an element with the given qualified name defines a startup.
*
* @param name to be identified whether it is a startup or not
* @return true if there is a startup registered with the factory map in the name, false if not
*/
public boolean isStartup(QName name) {
return factoryMap.containsKey(name);
}
/**
* 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 configuration for creating the startup
* @param properties bag of properties with additional information
* @return Processor
*/
@SuppressWarnings({"UnusedDeclaration"})
public Startup getStartup(OMElement element, Properties properties) {
QName qName = element.getQName();
if (log.isDebugEnabled()) {
log.debug("Creating the Startup for : " + qName);
}
Class<? extends StartupFactory> cls = factoryMap.get(qName);
if (cls == null) {
String msg = "Unknown Startup type referenced by startup element : " + qName;
log.error(msg);
throw new SynapseException(msg);
}
try {
StartupFactory sf = cls.newInstance();
return sf.createStartup(element);
} 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 will serialize the config using the supplied QName (looking
* up the right class to do it)
*
* @param parent -
* Parent OMElement to which the created element will be added if
* not null
* @param startup -
* Startup to be serialized
* @return OMElement startup
*/
public OMElement serializeStartup(OMElement parent, Startup startup) {
Class<? extends StartupSerializer> cls = serializerMap.get(startup.getTagQName());
if (cls == null) {
String msg = "Unknown startup type referenced by startup element : "
+ startup.getTagQName();
log.error(msg);
throw new SynapseException(msg);
}
try {
StartupSerializer ss = cls.newInstance();
return ss.serializeStartup(parent, startup);
} catch (InstantiationException e) {
String msg = "Error initializing startup serializer: " + cls;
log.error(msg);
throw new SynapseException(msg, e);
} catch (IllegalAccessException e) {
String msg = "Error initializing startup ser: " + cls;
log.error(msg);
throw new SynapseException(msg, e);
}
}
/*
* This method exposes all the StartupFactories and its Extensions
*/
public Map<QName,Class<? extends StartupFactory>> getFactoryMap() {
return factoryMap;
}
/*
* This method exposes all the StartupSerializers and its Extensions
*/
public Map<QName,Class<? extends StartupSerializer>> getSerializerMap() {
return serializerMap;
}
/**
* Allow the startup finder to act as an XMLToObjectMapper for
* Startup (i.e. Startup) loaded dynamically from a Registry
*
* @param om to build the startup object
* @param properties bag of properties with additional information
* @return startup created
*/
public Startup getObjectFromOMNode(OMNode om, Properties properties) {
if (om instanceof OMElement) {
return getStartup((OMElement) om, properties);
} else {
handleException("Invalid configuration XML : " + om);
}
return null;
}
}