package act.boot; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * 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. * #L% */ import act.BytecodeEnhancerManager; import act.asm.ClassReader; import act.asm.ClassWriter; import act.boot.app.FullStackAppBootstrapClassLoader; import act.boot.server.ServerBootstrapClassLoader; import act.util.ActClassLoader; import act.util.ByteCodeVisitor; import act.util.ClassInfoRepository; import act.util.ClassNode; import org.osgl.$; import org.osgl.logging.L; import org.osgl.logging.Logger; import org.osgl.util.C; import org.osgl.util.E; import org.osgl.util.IO; import org.osgl.util.S; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.ProtectionDomain; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; /** * Base class for Act class loaders */ public abstract class BootstrapClassLoader extends ClassLoader implements PluginClassProvider, ActClassLoader { public static final String FILE_SCAN_LIST = "act.scan.list"; protected static final Logger logger = L.get(BootstrapClassLoader.class); private BytecodeEnhancerManager enhancerManager = new BytecodeEnhancerManager(); protected ClassInfoRepository classInfoRepository = new ClassInfoRepository(); protected BootstrapClassLoader(ClassLoader parent) { super(parent); } @Override public ClassInfoRepository classInfoRepository() { return classInfoRepository; } public Class<?> loadedClass(String name) { Class<?> c = findLoadedClass(name); if (null == c) { ClassLoader p = getParent(); if (null != p && p instanceof ActClassLoader) { return ((ActClassLoader)p).loadedClass(name); } } return c; } private static ClassLoader _getParent() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (null == cl) { cl = ClassLoader.getSystemClassLoader(); } return cl; } protected Class<?> defineClassX(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) { int i = name.lastIndexOf('.'); if (i != -1) { String pkgName = name.substring(0, i); // Check if package already loaded. if (getPackage(pkgName) == null) { try { definePackage(pkgName, null, null, null, null, null, null, null); } catch (IllegalArgumentException iae) { throw new AssertionError("Cannot find package " + pkgName); } } } return super.defineClass(name, b, off, len, protectionDomain); } protected Class<?> defineClass(String name, byte[] ba) { Class<?> c = null; $.Var<ClassWriter> cw = $.val(null); ByteCodeVisitor enhancer = enhancerManager.generalEnhancer(name, cw); if (null == enhancer) { c = defineClassX(name, ba, 0, ba.length, DOMAIN); } else { Exception exception = null; ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_FRAMES); cw.set(w); enhancer.commitDownstream(); ClassReader r; r = new ClassReader(ba); try { r.accept(enhancer, 0); byte[] baNew = w.toByteArray(); c = defineClassX(name, baNew, 0, baNew.length, DOMAIN); } catch (Error e) { throw e; } catch (Exception e) { exception = e; } if (null != exception) { logger.error(exception, "Error enhancing class %s", name); throw E.unexpected(exception); } } return c; } protected static java.security.ProtectionDomain DOMAIN; static { DOMAIN = (java.security.ProtectionDomain) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { return BootstrapClassLoader.class.getProtectionDomain(); } }); } protected static final Set<String> protectedClasses = C.set( BootstrapClassLoader.class.getName(), ClassInfoRepository.class.getName(), ClassNode.class.getName(), ServerBootstrapClassLoader.class.getName(), FullStackAppBootstrapClassLoader.class.getName(), ActClassLoader.class.getName(), PluginClassProvider.class.getName() //Plugin.class.getName(), //ClassFilter.class.getName() ); public Set<String> scanList() { Set<String> scanList = new HashSet<String>(); try { final Enumeration<URL> systemResources = this.getResources(FILE_SCAN_LIST); while (systemResources.hasMoreElements()) { InputStream is = systemResources.nextElement().openStream(); String s = IO.readContentAsString(is); scanList.addAll( C.listOf(s.split("[\r\n]+")) .filter(S.F.startsWith("#").negate()) .filter(S.F.IS_BLANK.negate())); } } catch (IOException e) { throw E.ioException(e); } return scanList; } }