--- /dev/null
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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.apache;
+
+public interface PeriodicEventListener {
+ /**
+ * Execute a periodic task, such as reloading, etc.
+ */
+ public void periodicEvent();
+}
import javax.management.NotificationListener;
import javax.management.ObjectName;
+import org.apache.PeriodicEventListener;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerServlet;
import org.apache.catalina.Context;
/**
+ * Execute a periodic task, such as reloading, etc. This method will be
+ * invoked inside the classloading context of this container. Unexpected
+ * throwables will be caught and logged.
+ */
+ public void backgroundProcess() {
+ super.backgroundProcess();
+
+ if (!started)
+ return;
+
+ if (getServlet() != null && (getServlet() instanceof PeriodicEventListener)) {
+ ((PeriodicEventListener) getServlet()).periodicEvent();
+ }
+ }
+
+
+ /**
* Extract the root cause from a servlet exception.
*
* @param e The servlet exception
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.cert.Certificate;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
* @author Glenn L. Nielsen
* @version $Revision: 306189 $
*/
-public final class JspRuntimeContext implements Runnable {
+public final class JspRuntimeContext {
// Logger
private Log log = LogFactory.getLog(JspRuntimeContext.class);
if (!options.getDevelopment()
&& appBase != null
&& options.getCheckInterval() > 0) {
- if (appBase.endsWith(File.separator) ) {
- appBase = appBase.substring(0,appBase.length()-1);
- }
- String directory =
- appBase.substring(appBase.lastIndexOf(File.separator));
- threadName = threadName + "[" + directory + "]";
- threadStart();
+ lastCheck = System.currentTimeMillis();
}
}
private PermissionCollection permissionCollection;
private CodeSource codeSource;
private String classpath;
+ private long lastCheck = -1L;
/**
* Maps JSP pages to their JspServletWrapper's
private Map<String, JspServletWrapper> jsps = new ConcurrentHashMap<String, JspServletWrapper>();
- /**
- * The background thread.
- */
- private Thread thread = null;
-
-
- /**
- * The background thread completion semaphore.
- */
- private boolean threadDone = false;
-
-
- /**
- * Name to register for the background thread.
- */
- private String threadName = "JspRuntimeContext";
-
// ------------------------------------------------------ Public Methods
/**
* Process a "destory" event for this web application context.
*/
public void destroy() {
- threadStop();
-
Iterator servlets = jsps.values().iterator();
while (servlets.hasNext()) {
((JspServletWrapper) servlets.next()).destroy();
}
- // -------------------------------------------------------- Private Methods
-
/**
* Method used by background thread to check the JSP dependencies
* registered with this class for JSP's.
*/
- private void checkCompile() {
+ public void checkCompile() {
+
+ if (lastCheck < 0) {
+ // Checking was disabled
+ return;
+ }
+ long now = System.currentTimeMillis();
+ if (now > (lastCheck + (options.getCheckInterval() * 1000L))) {
+ lastCheck = now;
+ } else {
+ return;
+ }
+
Object [] wrappers = jsps.values().toArray();
for (int i = 0; i < wrappers.length; i++ ) {
JspServletWrapper jsw = (JspServletWrapper)wrappers[i];
}
}
}
+
}
/**
return classpath;
}
+
+ // -------------------------------------------------------- Private Methods
+
+
/**
* Method used to initialize classpath for compiles.
*/
}
- // -------------------------------------------------------- Thread Support
-
- /**
- * Start the background thread that will periodically check for
- * changes to compile time included files in a JSP.
- *
- * @exception IllegalStateException if we should not be starting
- * a background thread now
- */
- protected void threadStart() {
-
- // Has the background thread already been started?
- if (thread != null) {
- return;
- }
-
- // Start the background thread
- threadDone = false;
- thread = new Thread(this, threadName);
- thread.setDaemon(true);
- thread.start();
-
- }
-
-
- /**
- * Stop the background thread that is periodically checking for
- * changes to compile time included files in a JSP.
- */
- protected void threadStop() {
-
- if (thread == null) {
- return;
- }
-
- threadDone = true;
- thread.interrupt();
- try {
- thread.join();
- } catch (InterruptedException e) {
- ;
- }
-
- thread = null;
-
- }
-
- /**
- * Sleep for the duration specified by the <code>checkInterval</code>
- * property.
- */
- protected void threadSleep() {
-
- try {
- Thread.sleep(options.getCheckInterval() * 1000L);
- } catch (InterruptedException e) {
- ;
- }
-
- }
-
-
- // ------------------------------------------------------ Background Thread
-
-
- /**
- * The background thread that checks for changes to files
- * included by a JSP and flags that a recompile is required.
- */
- public void run() {
-
- // Loop until the termination semaphore is set
- while (!threadDone) {
-
- // Wait for our check interval
- threadSleep();
-
- // Check for included files which are newer than the
- // JSP which uses them.
- try {
- checkCompile();
- } catch (Throwable t) {
- log.error("Exception checking if recompile needed: ", t);
- }
- }
-
- }
-
}