⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reloadingclassloader.java

📁 Wicket一个开发Java Web应用程序框架。它使得开发web应用程序变得容易而轻松。 Wicket利用一个POJO data beans组件使得它可以与任何持久层技术相结合。
💻 JAVA
字号:
/* * 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.wicket.application;import java.io.IOException;import java.net.URL;import java.net.URLClassLoader;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Set;import org.apache.wicket.util.file.File;import org.apache.wicket.util.listener.IChangeListener;import org.apache.wicket.util.time.Duration;import org.apache.wicket.util.watch.ModificationWatcher;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Custom ClassLoader that reverses the classloader lookups, and that is able to notify a listener * when a class file is changed. *  * @author <a href="mailto:jbq@apache.org">Jean-Baptiste Quenot</a> */public class ReloadingClassLoader extends URLClassLoader{	private static final Logger log = LoggerFactory.getLogger(ReloadingClassLoader.class);	private static final Set urls = new HashSet();	private static final List patterns = new ArrayList();	protected boolean tryClassHere(String name)	{		// don't include classes in the java or javax.servlet package		if (name != null && (name.startsWith("java.") || name.startsWith("javax.servlet")))		{			return false;		}		// Scan includes, then excludes		boolean tryHere;		// If no explicit includes, try here		if (patterns == null || patterns.size() == 0)		{			tryHere = true;		}		else		{			// See if it matches include patterns			tryHere = false;			Iterator includesIterator = patterns.iterator();			while (includesIterator.hasNext())			{				String rawpattern = (String)includesIterator.next();				if (rawpattern.length() <= 1)				{					continue;				}				boolean isInclude = rawpattern.substring(0, 1).equals("+");				String pattern = rawpattern.substring(1);				if (WildcardMatcherHelper.match(pattern, name) != null)				{					tryHere = isInclude;				}			}		}		return tryHere;	}	/**	 * Include a pattern	 * 	 * @param pattern	 *            the pattern to include	 */	public static void includePattern(String pattern)	{		patterns.add("+" + pattern);	}	/**	 * Exclude a pattern	 * 	 * @param pattern	 *            the pattern to exclude	 */	public static void excludePattern(String pattern)	{		patterns.add("-" + pattern);	}	/**	 * Returns the list of all configured inclusion or exclusion patterns	 * 	 * @return list of patterns as String	 */	public static List getPatterns()	{		return patterns;	}	/**	 * Add the location of a directory containing class files	 * 	 * @param url	 *            the URL for the directory	 */	public static void addLocation(URL url)	{		urls.add(url);	}	/**	 * Returns the list of all configured locations of directories containing class files	 * 	 * @return list of locations as URL	 */	public static Set getLocations()	{		return urls;	}	/**	 * Add all the url locations we can find for the provided class loader	 * 	 * @param loader	 *            class loader	 */	private static void addClassLoaderUrls(ClassLoader loader)	{		if (loader != null)		{			final Enumeration resources;			try			{				resources = loader.getResources("");			}			catch (IOException e)			{				throw new RuntimeException(e);			}			while (resources.hasMoreElements())			{				URL location = (URL)resources.nextElement();				ReloadingClassLoader.addLocation(location);			}		}	}	private IChangeListener listener;	private final Duration pollFrequency = Duration.seconds(3);	private final ModificationWatcher watcher;	static	{		addClassLoaderUrls(ReloadingClassLoader.class.getClassLoader());		excludePattern("org.apache.wicket.*");		includePattern("org.apache.wicket.examples.*");	}	/**	 * Create a new reloading ClassLoader from a list of URLs, and initialize the	 * ModificationWatcher to detect class file modifications	 * 	 * @param parent	 *            the parent classloader in case the class file cannot be loaded from the above	 *            locations	 */	public ReloadingClassLoader(ClassLoader parent)	{		super(new URL[] {}, parent);		// probably doubles from this class, but just in case		addClassLoaderUrls(parent);		for (Iterator i = urls.iterator(); i.hasNext();)		{			addURL((URL)i.next());		}		watcher = new ModificationWatcher(pollFrequency);	}	/**	 * Gets a resource from this <code>ClassLoader</class>.  If the	 * resource does not exist in this one, we check the parent.	 * Please note that this is the exact opposite of the	 * <code>ClassLoader</code> spec.  We use it to work around	 * inconsistent class loaders from third party vendors.	 *	 * @param name of resource	 */	public final URL getResource(final String name)	{		URL resource = findResource(name);		ClassLoader parent = getParent();		if (resource == null && parent != null)		{			resource = parent.getResource(name);		}		return resource;	}	/**	 * Loads the class from this <code>ClassLoader</class>.  If the	 * class does not exist in this one, we check the parent.  Please	 * note that this is the exact opposite of the	 * <code>ClassLoader</code> spec.  We use it to load the class	 * from the same classloader as WicketFilter or WicketServlet.	 * When found, the class file is watched for modifications.	 *	 * @param     name the name of the class	 * @param     resolve if <code>true</code> then resolve the class	 * @return    the resulting <code>Class</code> object	 * @exception ClassNotFoundException if the class could not be found	 */	public final Class loadClass(String name, boolean resolve) throws ClassNotFoundException	{		// First check if it's already loaded		Class clazz = findLoadedClass(name);		if (clazz == null)		{			final ClassLoader parent = getParent();			if (tryClassHere(name))			{				try				{					clazz = findClass(name);					watchForModifications(clazz);				}				catch (ClassNotFoundException cnfe)				{					if (parent == null)					{						// Propagate exception						throw cnfe;					}				}			}			if (clazz == null)			{				if (parent == null)				{					throw new ClassNotFoundException(name);				}				else				{					// Will throw a CFNE if not found in parent					clazz = parent.loadClass(name);				}			}		}		if (resolve)		{			resolveClass(clazz);		}		return clazz;	}	/**	 * Sets the listener that will be notified when a class changes	 * 	 * @param listener	 *            the listener to notify upon class change	 */	public void setListener(IChangeListener listener)	{		this.listener = listener;	}	/**	 * Watch changes of a class file by locating it in the list of location URLs and adding the	 * corresponding file to the ModificationWatcher	 * 	 * @param clz	 *            the class to watch	 */	private void watchForModifications(Class clz)	{		// Watch class in the future		Iterator locationsIterator = urls.iterator();		File clzFile = null;		while (locationsIterator.hasNext())		{			// FIXME only works for directories, but JARs etc could be checked			// as well			URL location = (URL)locationsIterator.next();			String clzLocation = location.getFile() + clz.getName().replaceAll("\\.", "/") +					".class";			log.debug("clzLocation=" + clzLocation);			clzFile = new File(clzLocation);			final File finalClzFile = clzFile;			if (clzFile.exists())			{				log.info("Watching changes of class " + clzFile);				watcher.add(clzFile, new IChangeListener()				{					public void onChange()					{						log.info("Class file " + finalClzFile + " has changed, reloading");						try						{							listener.onChange();						}						catch (Exception e)						{							log.error("Could not notify listener", e);							// If an error occurs when the listener is notified,							// remove the watched object to avoid rethrowing the							// exception at next check							// FIXME check if class file has been deleted							watcher.remove(finalClzFile);						}					}				});				break;			}			else			{				log.debug("Class file does not exist: " + clzFile);			}		}		if (clzFile != null && !clzFile.exists())		{			log.debug("Could not locate class " + clz.getName());		}	}	/**	 * Remove the ModificationWatcher from the current reloading class loader	 */	public void destroy()	{		watcher.destroy();	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -