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

📄 dynamicrepositoryclassloader.java

📁 jsr170接口的java实现。是个apache的开源项目。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * 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.jackrabbit.classloader;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import javax.jcr.Property;import javax.jcr.RepositoryException;import javax.jcr.Session;import javax.jcr.observation.Event;import javax.jcr.observation.EventIterator;import javax.jcr.observation.EventListener;import javax.jcr.observation.ObservationManager;import org.apache.jackrabbit.classloader.DynamicPatternPath.Listener;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * The <code>DynamicRepositoryClassLoader</code> class extends the * {@link org.apache.jackrabbit.classloader.RepositoryClassLoader} and provides the * functionality to load classes and resources from the JCR Repository. * Additionally, this class supports the notion of getting 'dirty', which means, * that if a resource loaded through this class loader has been modified in the * Repository, this class loader marks itself dirty, which flag can get * retrieved. This helps the user of this class loader to decide on whether to * {@link #reinstantiate(Session, ClassLoader) reinstantiate} it or continue * using this class loader. * <p> * When a user of the class loader recognizes an instance to be dirty, it can * easily be reinstantiated with the {@link #reinstantiate} method. This * reinstantiation will also rebuild the internal real class path from the same * list of path patterns as was used to create the internal class path for the * original class loader. The resulting internal class path need not be the * same, though. * <p> * As an additional feature the class loaders provides the functionality for * complete reconfiguration of the list of path patterns defined at class loader * construction time through the {@link #reconfigure(String[])} method. This * reconfiguration replaces the internal class path with a new one built from * the new path list and also replaces that path list. Reinstantiating a * reconfigured class loader gets a class loader containing the same path list * as the original class loader had after reconfiguration. That is the original * configuration is lost. While reconfiguration is not able to throw away * classes already loaded, it will nevertheless mark the class loader dirty, if * any classes have already been loaded through it. * <p> * This class is not intended to be extended by clients. * * @author Felix Meschberger */public class DynamicRepositoryClassLoader extends RepositoryClassLoader        implements EventListener, Listener {    /** default log category */    private static final Logger log =        LoggerFactory.getLogger(DynamicRepositoryClassLoader.class);    /**     * Cache of resources used to check class loader expiry. The map is indexed     * by the paths of the expiry properties of the cached resources. This map     * is not complete in terms of resources which have been loaded through this     * class loader. That is for resources loaded through an archive class path     * entry, only one of those resources (the last one loaded) is kept in this     * cache, while the others are ignored.     *     * @see #onEvent(EventIterator)     * @see #findClassLoaderResource(String)     */    private Map modTimeCache;    /**     * Flag indicating whether there are loaded classes which have later been     * expired (e.g. invalidated or modified)     */    private boolean dirty;    /**     * The list of repositories added through either the {@link #addURL} or the     * {@link #addHandle} method.     */    private ClassPathEntry[] addedRepositories;    /**     * Creates a <code>DynamicRepositoryClassLoader</code> from a list of item     * path strings containing globbing pattens for the paths defining the     * class path.     *     * @param session The <code>Session</code> to use to access the class items.     * @param classPath The list of path strings making up the (initial) class     *      path of this class loader. The strings may contain globbing     *      characters which will be resolved to build the actual class path.     * @param parent The parent <code>ClassLoader</code>, which may be     *      <code>null</code>.     *     * @throws NullPointerException if either the session or the handles list     *      is <code>null</code>.     */    public DynamicRepositoryClassLoader(Session session,            String[] classPath, ClassLoader parent) {        // initialize the super class with an empty class path        super(session, new DynamicPatternPath(session, classPath), parent);        // set fields        dirty = false;        modTimeCache = new HashMap();        // register with observation service and path pattern list        registerModificationListener();        log.debug("DynamicRepositoryClassLoader: {} ready", this);    }    /**     * Creates a <code>DynamicRepositoryClassLoader</code> with the same     * configuration as the given <code>DynamicRepositoryClassLoader</code>.     * This constructor is used by the {@link #reinstantiate} method.     * <p>     * Before returning from this constructor the <code>old</code> class loader     * is destroyed and may not be used any more.     *     * @param session The session to associate with this class loader.     * @param old The <code>DynamicRepositoryClassLoader</code> to copy the     *            cofiguration from.     * @param parent The parent <code>ClassLoader</code>, which may be     *            <code>null</code>.     */    private DynamicRepositoryClassLoader(Session session,            DynamicRepositoryClassLoader old, ClassLoader parent) {        // initialize the super class with an empty class path        super(session, old.getHandles(), parent);        // set the configuration and fields        dirty = false;        modTimeCache = new HashMap();        // create a repository from the handles - might get a different one        setRepository(resetClassPathEntries(old.getRepository()));        setAddedRepositories(resetClassPathEntries(old.getAddedRepositories()));        buildRepository();        // register with observation service and path pattern list        registerModificationListener();        // finally finalize the old class loader        old.destroy();        log.debug(            "DynamicRepositoryClassLoader: Copied {}. Do not use that anymore",            old);    }    /**     * Destroys this class loader. This process encompasses all steps needed     * to remove as much references to this class loader as possible.     * <p>     * <em>NOTE</em>: This method just clears all internal fields and especially     * the class path to render this class loader unusable.     * <p>     * This implementation does not throw any exceptions.     */    public void destroy() {        // we expect to be called only once, so we stop destroyal here        if (isDestroyed()) {            log.debug("Instance is already destroyed");            return;        }        // remove ourselves as listeners from other places        unregisterListener();        addedRepositories = null;        super.destroy();    }    //---------- reload support ------------------------------------------------    /**     * Checks whether this class loader already loaded the named resource and     * would load another version if it were instructed to do so. As a side     * effect the class loader sets itself dirty in this case.     * <p>     * Calling this method yields the same result as calling     * {@link #shouldReload(String, boolean)} with the <code>force</code>     * argument set to <code>false</code>.     *     * @param name The name of the resource to check.     *     * @return <code>true</code> if the resource is loaded and reloading would     *      take another version than currently loaded.     *     * @see #isDirty     */    public synchronized boolean shouldReload(String name) {        return shouldReload(name, false);    }    /**     * Checks whether this class loader already loaded the named resource and     * whether the class loader should be set dirty depending on the     * <code>force</code> argument. If the argument is <code>true</code>, the     * class loader is marked dirty and <code>true</code> is returned if the     * resource has been loaded, else the loaded resource is checked for expiry     * and the class loader is only set dirty if the loaded resource has     * expired.     *     * @param name The name of the resource to check.     * @param force <code>true</code> if the class loader should be marked dirty     *      if the resource is loaded, else the class loader is only marked     *      dirty if the resource is loaded and has expired.     *     * @return <code>true</code> if the resource is loaded and     *      <code>force</code> is <code>true</code> or if the resource has     *      expired. <code>true</code> is also returned if this class loader     *      has already been destroyed.     *     * @see #isDirty     */    public synchronized boolean shouldReload(String name, boolean force) {        if (isDestroyed()) {            log.warn("Classloader already destroyed, reload required");            return true;        }        ClassLoaderResource res = getCachedResource(name);        if (res != null) {            log.debug("shouldReload: Expiring cache entry {}", res);            if (force) {                log.debug("shouldReload: Forced dirty flag");                dirty = true;                return true;            }            return expireResource(res);        }        return false;    }    /**     * Returns <code>true</code> if any of the loaded classes need reload. Also     * sets this class loader dirty. If the class loader is already set dirty     * or if this class loader has been destroyed before calling this method,     * it returns immediately.     *     * @return <code>true</code> if any class loader needs to be reinstantiated.     *     * @see #isDirty     */    public synchronized boolean shouldReload() {        // check whether we are already dirty        if (isDirty()) {            log.debug("shouldReload: Dirty, need reload");            return true;        }        // Check whether any class has changed        for (Iterator iter = getCachedResources(); iter.hasNext();) {            if (expireResource((ClassLoaderResource) iter.next())) {                log.debug("shouldReload: Found expired resource, need reload");                return true;            }        }        // No changes, no need to reload        log.debug("shouldReload: No expired resource found, no need to reload");        return false;    }    /**     * Returns whether the class loader is dirty. This can be the case if any     * of the {@link #shouldReload(String)} or {@link #shouldReload()}     * methods returned <code>true</code> or if a loaded class has been expired     * through the observation.     * <p>     * This method may also return <code>true</code> if the <code>Session</code>     * associated with this class loader is not valid anymore.     * <p>     * Finally the method always returns <code>true</code> if the class loader     * has already been destroyed. Note, however, that a destroyed class loader     * cannot be reinstantiated. See {@link #reinstantiate(Session, ClassLoader)}.     * <p>     * If the class loader is dirty, it should be reinstantiated through the     * {@link #reinstantiate} method.     *     * @return <code>true</code> if the class loader is dirty and needs     *      reinstantiation.     */    public boolean isDirty() {        return isDestroyed() || dirty || !getSession().isLive();    }    /**     * Reinstantiates this class loader. That is, a new ClassLoader with no     * loaded class is created with the same configuration as this class loader.     * <p>     * When the new class loader is returned, this class loader has been     * destroyed and may not be used any more.     *     * @param parent The parent <code>ClassLoader</code> for the reinstantiated     * 	    <code>DynamicRepositoryClassLoader</code>, which may be     *      <code>null</code>.     *     * @return a new instance with the same configuration as this class loader.

⌨️ 快捷键说明

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