/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.autoloader; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import com.scooterframework.common.logging.LogUtil; /** * MyClassLoader class * * @author (Fei) John Chen * */ public class MyClassLoader extends ClassLoader { protected LogUtil log = LogUtil.getLogger(this.getClass().getName()); static private long key = 0L; private ClassManager caller; private String initiatingClassName; private ClassWork cwh; private ConcurrentMap<String, LoadedClass> loadedClasses = new ConcurrentHashMap<String, LoadedClass>(); public MyClassLoader(ClassManager caller) { this(MyClassLoader.class.getClassLoader(), caller); } public MyClassLoader(ClassLoader parent, ClassManager caller) { super(parent); this.caller = caller; key = key + 1; cwh = new ClassWork(this); } public long getKey() { return key; } public Class<?> loadMyClass(String className) throws ClassNotFoundException { initiatingClassName = className; return loadClass(className, true); } protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException { Class<?> c = null; // See if type has already been loaded LoadedClass loadedClass = (LoadedClass)loadedClasses.get(className); if (loadedClass == null) { //record the newly loaded class if (!isAllowedToChange(className)) { c = super.loadClass(className, resolve); return c; } else { c = cwh.changeClass(className); if (c == null) c = super.loadClass(className, resolve); loadedClass = new LoadedClass(c, key); loadedClasses.put(className, loadedClass); } } else { c = loadedClass.clazz; resolve = false; } //check if the source file has been changed if (sourceChanged()) { loadedClasses.clear(); caller.createNewClassLoader(className); c = caller.loadMyClass(initiatingClassName); } if (resolve) { resolveClass(c); } return c; } protected boolean sourceChanged() { boolean changed = false; if (loadedClasses == null || loadedClasses.size() == 0) return changed; for (Map.Entry<String, LoadedClass> entry : loadedClasses.entrySet()) { String className = entry.getKey(); LoadedClass loadedClass = (LoadedClass)loadedClasses.get(className); SourceFile sourceFile = FileMonitor.getSourceFile(className); if (sourceFile != null && loadedClass != null && loadedClass.loadedTime < sourceFile.getLastSourceModifiedTime()) { changed = true; break; } } return changed; } private boolean isAllowedToChange(String className) { boolean check = false; if (((FileMonitor.isClassMonitored(className) || ClassWorkHelper.isAllowedClassName(className)) && !AutoLoaderConfig.getInstance().notAllowedToChange(className)) || (className.startsWith("com.scooterframework") && className.endsWith("Test")) || (className.startsWith("com.scooterframework.test.model")) ) { check = true; } return check; } }