blob: 1c77d2a4d2e02c03c8d37d0c8b2e29df2292a3c2 [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 com.sun.syndication.io.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.sun.syndication.io.DelegatingModuleGenerator;
import com.sun.syndication.io.DelegatingModuleParser;
import com.sun.syndication.io.WireFeedGenerator;
import com.sun.syndication.io.WireFeedParser;
/**
* <p>
* Override the default Rome plugin manager to be OSGi compliant around classloader.
* </p>
*
* @author Alejandro Abdelnur
* @author Jean-Baptiste Onofré
* @author Lukasz Dywicki
*/
public abstract class PluginManager {
private String[] _propertyValues;
private Map _pluginsMap;
private List _pluginsList;
private List _keys;
private WireFeedParser _parentParser;
private WireFeedGenerator _parentGenerator;
/**
* <p>
* Creates a PluginManager.
* <p>
*
* @param propertyKey property key defining the plugins classes.
*/
protected PluginManager(String propertyKey) {
this(propertyKey, null, null);
}
protected PluginManager(String propertyKey, WireFeedParser parentParser, WireFeedGenerator parentGenerator) {
_parentParser = parentParser;
_parentGenerator = parentGenerator;
_propertyValues = PropertiesLoader.getPropertiesLoader().getTokenizedProperty(propertyKey, ", ");
loadPlugins();
_pluginsMap = Collections.unmodifiableMap(_pluginsMap);
_pluginsList = Collections.unmodifiableList(_pluginsList);
_keys = Collections.unmodifiableList(new ArrayList(_pluginsMap.keySet()));
}
protected abstract String getKey(Object obj);
protected List getKeys() {
return _keys;
}
protected List getPlugins() {
return _pluginsList;
}
protected Map getPluginMap() {
return _pluginsMap;
}
protected Object getPlugin(String key) {
return _pluginsMap.get(key);
}
// PRIVATE - LOADER PART
private void loadPlugins() {
List finalPluginsList = new ArrayList();
_pluginsList = new ArrayList();
_pluginsMap = new HashMap();
String className = null;
try {
Class[] classes = getClasses();
for (int i = 0; i < classes.length; i++) {
className = classes[i].getName();
Object plugin = classes[i].newInstance();
if (plugin instanceof DelegatingModuleParser) {
((DelegatingModuleParser) plugin).setFeedParser(_parentParser);
}
if (plugin instanceof DelegatingModuleGenerator) {
((DelegatingModuleGenerator) plugin).setFeedGenerator(_parentGenerator);
}
_pluginsMap.put(getKey(plugin), plugin);
_pluginsList.add(plugin); // to preserve the order of definition in the rome.properties files
}
Iterator i = _pluginsMap.values().iterator();
while (i.hasNext()) {
finalPluginsList.add(i.next()); // to remove overridden plugin impls
}
i = _pluginsList.iterator();
while (i.hasNext()) {
Object plugin = i.next();
if (!finalPluginsList.contains(plugin)) {
i.remove();
}
}
} catch (Exception ex) {
throw new RuntimeException("could not instantiate plugin " + className, ex);
} catch (ExceptionInInitializerError er) {
throw new RuntimeException("could not instantiate plugin " + className, er);
}
}
/**
* <p>
* Loads and returns the classes defined in the properties files. If the system property "rome.pluginmanager.useloadclass" is
* set to true then classLoader.loadClass will be used to load classes (instead of Class.forName). This is designed to improve
* OSGi compatibility. Further information can be found in https://rome.dev.java.net/issues/show_bug.cgi?id=118
* </p>
*
* @return array containing the classes defined in the properties files.
* @throws ClassNotFoundException thrown if one of the classes defined in the properties file cannot be loaded and hard failure is ON.
*/
private Class[] getClasses() throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
List classes = new ArrayList();
boolean useLoadClass = Boolean.valueOf(System.getProperty("rome.pluginmanager.useloadclass", "false")).booleanValue();
for (int i = 0; i < _propertyValues.length; i++) {
Class mClass = null;
try {
if (useLoadClass) {
mClass = classLoader.loadClass(_propertyValues[i]);
} else {
mClass = Class.forName(_propertyValues[i], true, classLoader);
}
} catch (ClassNotFoundException e) {
// if external class loader fail use local class loader
mClass = getClass().getClassLoader().loadClass(_propertyValues[i]);
}
classes.add(mClass);
}
Class[] array = new Class[classes.size()];
classes.toArray(array);
return array;
}
}