/* * Copyright 2013 The Skfiy Open Association. * * 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.skfiy.typhon.script; import java.io.File; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; import org.skfiy.typhon.Component; import org.skfiy.typhon.Constants; import org.skfiy.typhon.Container; import org.skfiy.typhon.Typhons; import org.skfiy.util.Assert; import org.skfiy.util.ClassUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 生产版脚本管理器. * * @author Kevin Zou <kevinz@skfiy.org> */ @Singleton public class ProductionScriptManager implements Component, ScriptManager { private static final Logger LOG = LoggerFactory.getLogger(ProductionScriptManager.class); @Inject private Container container; private File targetDir; private final Map<String, Script> scripts = new HashMap<>(); private ScriptClassLoader scriptClassLoader = new ScriptClassLoader(); private Component.Status status; @Override public void init() { targetDir = new File(Typhons.getProperty(Constants.SCRIPTS_OUT_DIR, Typhons.getProperty(Constants.SCRIPTS_DIR))); initClassLoader(targetDir); initScripts(targetDir); status = Component.Status.INITIALIZED; LOG.debug("ProductionScriptManager inited successful..."); } @Override public void reload() { throw new UnsupportedOperationException("Not supported yet."); } @Override public void destroy() { status = Component.Status.DESTROYED; scripts.clear(); container = null; targetDir = null; scriptClassLoader = null; LOG.debug("ProductionScriptManager destroyed successful..."); } @Override public <T extends Script> T getScript(String name) { Assert.notNull(name); Assert.state(status == Component.Status.INITIALIZED, "[Assertion failed] - this state invariant must be initialized"); Script script = scripts.get(name); if (script == null) { throw new NotFoundScriptException(name); } return (T) script; } private void initClassLoader(File dir) { scriptClassLoader.addFile(dir); if (dir.isDirectory()) { File[] files = dir.listFiles(); for (File f : files) { initClassLoader(f); } } } private void initScripts(File dir) { File[] files = dir.listFiles(); for (File f : files) { if (f.isDirectory()) { initScripts(f); } else if (!f.getName().contains("$") && f.getName().endsWith(".class")) { String name = getScriptCanonicalName(f); scripts.put(name, newScript(name)); } } } private Script newScript(String name) { try { Class clazz = ClassUtils.forName(name, scriptClassLoader); Script script = (Script) clazz.newInstance(); container.injectMembers(script); return script; } catch (Exception ex) { LOG.error("创建[{}]脚本实例错误", name, ex); throw new ScriptException("创建[" + name + "]脚本实例错误", ex); } } private String getScriptCanonicalName(File f) { String name = f.getName(); StringBuilder sb = new StringBuilder(name.substring(0, name.lastIndexOf("."))); for (;;) { File parentFile = f.getParentFile(); if (targetDir.equals(parentFile)) { break; } sb.insert(0, ".").insert(0, parentFile.getName()); f = parentFile; } return sb.toString(); } }