/* * Copyright (C) 2007-2009 Jive Software. All rights reserved. * * Licensed 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.jivesoftware.openfire.plugin.util.cache; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.container.Plugin; import org.jivesoftware.openfire.container.PluginClassLoader; import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.util.JiveGlobals; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class loader to be used by Openfire to load classes that live in the Hazelcast plugin, * the Openfire core and also classes defined in other plugins. With this new class loader * plugins can now make use of hazelcast.<p> * * However, there is a catch with this class loader. Plugins that define the same class name * (i.e. package and class name) will have a problem if they try to send that class through * the cluster. Hazelcast will deserialize the class and will use the first class definition * found in the list of plugins.<p> * * The sequence of search for this class loader is first check the hazelcast plugin that * includes checking the Openfire core. If not found then try with the other plugins. * * @author Tom Evans * @author Gaston Dombiak */ public class ClusterClassLoader extends ClassLoader { private static Logger logger = LoggerFactory.getLogger(ClusterClassLoader.class); private static final String HAZELCAST_CONFIG_DIR = JiveGlobals.getProperty( "hazelcast.config.xml.directory", JiveGlobals.getHomeDirectory() + "/conf"); private PluginClassLoader hazelcastClassloader; public ClusterClassLoader() { Plugin plugin = XMPPServer.getInstance().getPluginManager().getPlugin("hazelcast"); hazelcastClassloader = XMPPServer.getInstance().getPluginManager().getPluginClassloader(plugin); // this is meant to allow loading configuration files from outside the plugin JAR file File confFolder = new File(HAZELCAST_CONFIG_DIR); try { logger.debug("Adding conf folder {}", confFolder); hazelcastClassloader.addURLFile(confFolder.toURI().toURL()); } catch (MalformedURLException e) { logger.error("Error adding folder {} to classpath {}", HAZELCAST_CONFIG_DIR, e.getMessage()); } } public Class<?> loadClass(String name) throws ClassNotFoundException { try { return hazelcastClassloader.loadClass(name); } catch (ClassNotFoundException e) { PluginManager pluginManager = XMPPServer.getInstance().getPluginManager(); for (Plugin plugin : pluginManager.getPlugins()) { String pluginName = pluginManager.getPluginDirectory(plugin).getName(); if ("hazelcast".equals(pluginName) || "admin".equals(pluginName)) { continue; } PluginClassLoader pluginClassloader = pluginManager.getPluginClassloader(plugin); try { return pluginClassloader.loadClass(name); } catch (ClassNotFoundException e1) { // Do nothing. Continue to the next plugin } } } throw new ClassNotFoundException(name); } public URL getResource(String name) { URL resource = hazelcastClassloader.getResource(name); if (resource == null) { PluginManager pluginManager = XMPPServer.getInstance().getPluginManager(); for (Plugin plugin : pluginManager.getPlugins()) { String pluginName = pluginManager.getPluginDirectory(plugin).getName(); if ("hazelcast".equals(pluginName) || "admin".equals(pluginName)) { continue; } PluginClassLoader pluginClassloader = pluginManager.getPluginClassloader(plugin); resource = pluginClassloader.getResource(name); if (resource != null) { return resource; } } } return resource; } public Enumeration<URL> getResources(String name) throws IOException { Enumeration<URL> answer = null; try { answer = hazelcastClassloader.getResources(name); } catch (IOException e) { // Ignore } if (answer == null || !answer.hasMoreElements()) { PluginManager pluginManager = XMPPServer.getInstance().getPluginManager(); for (Plugin plugin : pluginManager.getPlugins()) { String pluginName = pluginManager.getPluginDirectory(plugin).getName(); if ("hazelcast".equals(pluginName) || "admin".equals(pluginName)) { continue; } PluginClassLoader pluginClassloader = pluginManager.getPluginClassloader(plugin); try { answer = pluginClassloader.getResources(name); } catch (IOException e) { // Ignore } if (answer != null && answer.hasMoreElements()) { return answer; } } } return answer; } }