| /* |
| * 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 rewrite.org.apache.myfaces.extensions.scripting.monitor; |
| |
| |
| |
| import rewrite.org.apache.myfaces.extensions.scripting.common.ScriptingConst; |
| import rewrite.org.apache.myfaces.extensions.scripting.context.WeavingContext; |
| |
| import javax.servlet.ServletContext; |
| import java.io.File; |
| import java.lang.ref.WeakReference; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| /** |
| * Central daemon thread which watches the resources |
| * for changes and marks them as changed. |
| * This watchdog daemon is the central core |
| * of the entire scripting engine it runs asynchronously |
| * to your program and keeps an eye on the resources |
| * and their dependencies, once a file has changed |
| * all the referring dependencies are also marked |
| * as being to reloaded. |
| * |
| * @author Werner Punz (latest modification by $Author$) |
| * @version $Revision$ $Date$ |
| */ |
| public class ResourceMonitor extends Thread { |
| |
| private static final String CONTEXT_KEY = "extscriptDaemon"; |
| |
| static ResourceMonitor _instance = null; |
| |
| //Map<String, ClassResource> _classMap = new ConcurrentHashMap<String, ClassResource>(8, 0.75f, 1); |
| //ClassDependencies _dependencyMap = new ClassDependencies(); |
| |
| /** |
| * This map is a shortcut for the various scripting engines. |
| * It keeps track whether the engines source paths |
| * have dirty files or not and if true we enforce a recompile at the |
| * next refresh! |
| * <p/> |
| * We keep track on engine level to avoid to search the classMap for every refresh |
| * the classMap still is needed for various identification tasks which are reload |
| * related |
| */ |
| Map<Integer, Boolean> _systemRecompileMap = new ConcurrentHashMap<Integer, Boolean>(8, 0.75f, 1); |
| |
| boolean _running = false; |
| // boolean _contextInitialized = false; |
| Logger _log = Logger.getLogger(ResourceMonitor.class.getName()); |
| // ScriptingWeaver _weavers = null; |
| static WeakReference<ServletContext> _externalContext; |
| |
| public static synchronized void startup(ServletContext externalContext) { |
| |
| if (_externalContext != null) return; |
| _externalContext = new WeakReference<ServletContext>(externalContext); |
| if(getInstance() != null) return; |
| |
| //we currently keep it as singleton but in the long run we will move it into the context |
| //like everything else singleton-wise |
| |
| _instance = new ResourceMonitor(); |
| |
| /** |
| * daemon thread to allow forced |
| * shutdowns for web context restarts |
| */ |
| _instance.setDaemon(true); |
| _instance.setRunning(true); |
| //_instance.start(); |
| _externalContext.get().setAttribute(CONTEXT_KEY, _instance); |
| |
| |
| } |
| |
| public static synchronized void clear() { |
| |
| } |
| |
| public static synchronized ResourceMonitor getInstance() { |
| //we do it in this complicated manner because of find bugs |
| //practically this cannot really happen except for shutdown were it is not important anymore |
| ServletContext context = _externalContext.get(); |
| if (context != null) { |
| return (ResourceMonitor) context.getAttribute(CONTEXT_KEY); |
| } |
| return null; |
| } |
| |
| /** |
| * Central run method |
| * which performs the entire scanning process |
| */ |
| public void run() { |
| |
| while(_running) { |
| if(!_running) break; |
| //we run the full scan on the classes to bring our data structures up to the task |
| performMonitoringTask(); |
| sleep(); |
| } |
| |
| if (_log.isLoggable(Level.INFO)) { |
| _log.info("[EXT-SCRIPTING] Dynamic reloading watch daemon is shutting down"); |
| } |
| } |
| |
| public void initialMonitoring() { |
| WeavingContext context = WeavingContext.getInstance(); |
| context.initialFullScan(); |
| //we compile wherever needed, taints are now in place due to our scan already being performed |
| if(context.compile()) { |
| //we now have to perform a full dependency scan to bring our dependency map to the latest state |
| context.scanDependencies(); |
| //we next retaint all classes according to our dependency graph |
| context.markTaintedDependends(); |
| } |
| } |
| |
| public void performMonitoringTask() |
| { |
| WeavingContext context = WeavingContext.getInstance(); |
| context.initialFullScan(); |
| |
| //we compile wherever needed, taints are now in place due to our scan already being performed |
| if(context.compile()) { |
| //we now have to perform a full dependency scan to bring our dependency map to the latest state |
| context.scanDependencies(); |
| //we next retaint all classes according to our dependency graph |
| context.markTaintedDependends(); |
| } |
| } |
| |
| private void sleep() |
| { |
| try { |
| Thread.sleep(ScriptingConst.TAINT_INTERVAL); |
| } catch (InterruptedException e) { |
| //if the server shuts down while we are in sleep we get an error |
| //which we better should swallow |
| } |
| } |
| |
| /** |
| * central tainted mark method which keeps |
| * track if some file in one of the supported engines has changed |
| * and if yes marks the file as tainted as well |
| * as marks the engine as having to do a full recompile |
| */ |
| private final void checkForChanges() { |
| |
| } |
| |
| /** |
| * recursive walk over our meta data to taint also the classes |
| * which refer to our refreshing class so that those |
| * are reloaded as well, this helps to avoid classcast |
| * exceptions caused by imports and casts on long running artifacts |
| * |
| * @param className the origin classname which needs to be walked recursively |
| */ |
| private void dependencyTainted(String className) { |
| |
| } |
| |
| |
| |
| public void setRunning(boolean running) { |
| this._running = running; |
| } |
| } |
| |