You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by tc...@apache.org on 2005/03/27 17:03:58 UTC
svn commit: r159152 - in cocoon/trunk: lib/ lib/core/ lib/optional/
src/java/org/apache/cocoon/ src/java/org/apache/cocoon/components/fam/
src/java/org/apache/cocoon/components/treeprocessor/
Author: tcurdt
Date: Sun Mar 27 07:03:57 2005
New Revision: 159152
URL: http://svn.apache.org/viewcvs?view=rev&rev=159152
Log:
auto-reload the sitemap on classpath changes
Added:
cocoon/trunk/lib/core/commons-jci-r159148.jar (with props)
cocoon/trunk/src/java/org/apache/cocoon/components/fam/
cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitor.java
cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitorImpl.java
Removed:
cocoon/trunk/lib/optional/commons-jci-0.1-dev.jar
Modified:
cocoon/trunk/lib/jars.xml
cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
Added: cocoon/trunk/lib/core/commons-jci-r159148.jar
URL: http://svn.apache.org/viewcvs/cocoon/trunk/lib/core/commons-jci-r159148.jar?view=auto&rev=159152
==============================================================================
Binary file - no diff available.
Propchange: cocoon/trunk/lib/core/commons-jci-r159148.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: cocoon/trunk/lib/jars.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/lib/jars.xml?view=diff&r1=159151&r2=159152
==============================================================================
--- cocoon/trunk/lib/jars.xml (original)
+++ cocoon/trunk/lib/jars.xml Sun Mar 27 07:03:57 2005
@@ -1068,7 +1068,7 @@
API for compiling java
</description>
<used-by>javaflow</used-by>
- <lib>optional/commons-jci-0.1-dev.jar</lib>
+ <lib>core/commons-jci-0.1-dev.jar</lib>
<homepage></homepage>
</file>
Modified: cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles?view=diff&r1=159151&r2=159152
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles Sun Mar 27 07:03:57 2005
@@ -183,6 +183,10 @@
<!--=========================================================================-->
+ <role name="org.apache.cocoon.components.fam.SitemapMonitor"
+ shorthand="fam"
+ default-class="org.apache.cocoon.components.fam.SitemapMonitorImpl"/>
+
<role name="org.apache.cocoon.components.classloader.ClassLoaderManager"
shorthand="classloader"
default-class="org.apache.cocoon.components.classloader.ClassLoaderManagerImpl"/>
Added: cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitor.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitor.java?view=auto&rev=159152
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitor.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitor.java Sun Mar 27 07:03:57 2005
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2002-2005 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.cocoon.components.fam;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.commons.jci.monitor.FilesystemAlterationListener;
+
+public interface SitemapMonitor {
+ String ROLE = SitemapMonitor.class.getName();
+
+ void subscribeSitemap( FilesystemAlterationListener listener, Configuration sitemap ) throws ConfigurationException;
+
+ void unsubscribeSitemap( FilesystemAlterationListener listener);
+}
Added: cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitorImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitorImpl.java?view=auto&rev=159152
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitorImpl.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/fam/SitemapMonitorImpl.java Sun Mar 27 07:03:57 2005
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2002-2005 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.cocoon.components.fam;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.commons.jci.monitor.FilesystemAlterationListener;
+import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+
+public final class SitemapMonitorImpl extends AbstractLogEnabled implements SitemapMonitor, Serviceable, ThreadSafe, Initializable, Disposable {
+
+ private ServiceManager manager;
+ private SourceResolver resolver;
+ private FilesystemAlterationMonitor monitor = new FilesystemAlterationMonitor();
+
+
+ public void service( ServiceManager manager ) throws ServiceException {
+ this.manager = manager;
+ this.resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
+ }
+
+ private File[] parseConfiguration(Configuration config) throws ConfigurationException {
+ List urlList = new ArrayList();
+ Configuration[] children = config.getChild("components").getChild("classpath").getChildren();
+ for (int i = 0; i < children.length; i++) {
+ Configuration child = children[i];
+ String name = child.getName();
+ Source src = null;
+ try {
+ src = resolver.resolveURI(child.getAttribute("src"));
+
+ if ("class-dir".equals(name)) {
+ String dir = src.getURI();
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("class-dir:" + dir);
+ }
+ urlList.add(new File(dir.substring(5)));
+ } else if ("lib-dir".equals(name)) {
+ String dir = src.getURI();
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("lib-dir:" + dir);
+ }
+ urlList.add(new File(dir.substring(5)));
+ } else {
+ throw new ConfigurationException("Unexpected element " + name + " at " + child.getLocation());
+ }
+ } catch(ConfigurationException ce) {
+ resolver.release(src);
+ throw ce;
+ } catch(Exception e) {
+ resolver.release(src);
+ throw new ConfigurationException("Error loading " + name + " at " + child.getLocation(), e);
+ }
+ }
+
+ return (File[])urlList.toArray(new File[urlList.size()]);
+ }
+
+ public void subscribeSitemap( FilesystemAlterationListener listener, Configuration sitemap ) throws ConfigurationException {
+ File[] dirs = parseConfiguration(sitemap);
+ for (int i = 0; i < dirs.length; i++) {
+ monitor.addListener(listener, dirs[i]);
+ }
+ }
+
+ public void unsubscribeSitemap( FilesystemAlterationListener listener) {
+ monitor.removeListener(listener);
+ }
+
+ public void initialize() throws Exception {
+ Thread myThread = new Thread(monitor);
+ myThread.start();
+ }
+
+
+ public void dispose() {
+ }
+}
Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java?view=diff&r1=159151&r2=159152
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java Sun Mar 27 07:03:57 2005
@@ -15,6 +15,7 @@
*/
package org.apache.cocoon.components.treeprocessor;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
@@ -42,6 +43,7 @@
import org.apache.cocoon.sitemap.LeaveSitemapEventListener;
import org.apache.cocoon.sitemap.SitemapExecutor;
import org.apache.cocoon.sitemap.SitemapListener;
+import org.apache.commons.jci.monitor.FilesystemAlterationListener;
/**
* The concrete implementation of {@link Processor}, containing the evaluation tree and associated
@@ -50,7 +52,7 @@
* @version $Id$
*/
public class ConcreteTreeProcessor extends AbstractLogEnabled
- implements Processor, Disposable {
+ implements Processor, Disposable, FilesystemAlterationListener {
/** Our ServiceManager */
private ServiceManager manager;
@@ -84,6 +86,75 @@
/** Optional event listeners for the leave sitemap event */
private List leaveSitemapEventListeners = new ArrayList();
+ /** Needs a reload? */
+ protected volatile boolean needsReload = false;
+ protected boolean fresh = true;
+
+ public void onChangeDirectory( final File changeDirectory ) {
+ if (!fresh) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Sitemap reload required");
+ }
+ needsReload = true;
+ }
+ }
+
+ public void onChangeFile( final File changedFile ) {
+ if (!fresh) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Sitemap reload required");
+ }
+ needsReload = true;
+ }
+ }
+
+ public void onCreateDirectory( final File createdDirectory ) {
+ if (!fresh) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Sitemap reload required");
+ }
+ needsReload = true;
+ }
+ }
+
+ public void onCreateFile( final File createdFile ) {
+ if (!fresh) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Sitemap reload required");
+ }
+ needsReload = true;
+ }
+ }
+
+ public void onDeleteDirectory( final File deletedDirectory ) {
+ if (!fresh) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Sitemap reload required");
+ }
+ needsReload = true;
+ }
+ }
+
+ public void onDeleteFile( final File deletedFile ) {
+ if (!fresh) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Sitemap reload required");
+ }
+ needsReload = true;
+ }
+ }
+
+ public void onStart() {
+ }
+
+ public void onStop() {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Now tracking classpath changes");
+ }
+ fresh = false;
+ }
+
+
/**
* Builds a concrete processig, given the wrapping processor
*/
@@ -161,6 +232,10 @@
}
}
+ boolean isReloadNeeded() {
+ return needsReload;
+ }
+
public TreeProcessor getWrappingProcessor() {
return this.wrappingProcessor;
}
Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java?view=diff&r1=159151&r2=159152
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java Sun Mar 27 07:03:57 2005
@@ -16,7 +16,6 @@
package org.apache.cocoon.components.treeprocessor;
import java.net.URL;
-
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
@@ -33,16 +32,15 @@
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.thread.ThreadSafe;
-
import org.apache.cocoon.Processor;
import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.components.fam.SitemapMonitor;
import org.apache.cocoon.components.source.SourceUtil;
import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.internal.EnvironmentHelper;
import org.apache.cocoon.sitemap.SitemapExecutor;
import org.apache.cocoon.sitemap.impl.DefaultExecutor;
-
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.regexp.RE;
@@ -87,7 +85,9 @@
/** Check for reload? */
protected boolean checkReload;
-
+
+ protected SitemapMonitor fom;
+
/** The source resolver */
protected SourceResolver resolver;
@@ -135,6 +135,7 @@
this.manager = parent.concreteProcessor.getServiceManager();
this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+ this.fom = (SitemapMonitor) this.manager.lookup(SitemapMonitor.ROLE);
this.environmentHelper = new EnvironmentHelper(parent.environmentHelper);
// Setup environment helper
ContainerUtil.enableLogging(this.environmentHelper, this.getLogger());
@@ -170,6 +171,7 @@
public void service(ServiceManager manager) throws ServiceException {
this.manager = manager;
this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+ this.fom = (SitemapMonitor) this.manager.lookup(SitemapMonitor.ROLE);
}
public void initialize() throws Exception {
@@ -345,7 +347,7 @@
*/
private void setupConcreteProcessor(Environment env) throws Exception {
// first, check for sitemap changes
- if (this.concreteProcessor == null ||
+ if (this.concreteProcessor == null || this.concreteProcessor.isReloadNeeded() ||
(this.checkReload && this.source.getLastModified() != this.lastModified)) {
buildConcreteProcessor(env);
}
@@ -359,7 +361,7 @@
// Now that we entered the synchronized area, recheck what's already
// been checked in process().
- if (this.concreteProcessor != null && source.getLastModified() == this.lastModified) {
+ if (this.concreteProcessor != null && source.getLastModified() == this.lastModified && !this.concreteProcessor.isReloadNeeded()) {
// Nothing changed
return;
}
@@ -367,6 +369,7 @@
long startTime = System.currentTimeMillis();
long newLastModified;
ConcreteTreeProcessor newProcessor;
+ ConcreteTreeProcessor oldProcessor = this.concreteProcessor;
// We have to do a call to enterProcessor() here as during building
// of the tree, components (e.g. actions) are already instantiated
@@ -408,6 +411,21 @@
treeBuilder.getComponentLocator(),
treeBuilder.getEnterSitemapEventListeners(),
treeBuilder.getLeaveSitemapEventListeners());
+
+ fom.unsubscribeSitemap(oldProcessor);
+
+ Configuration classpath = sitemapProgram.getChild("components").getChild("classpath", false);
+ if (classpath != null) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("ConcreteTreeProcessor listening for changes");
+ }
+
+ fom.subscribeSitemap(newProcessor, sitemapProgram);
+ }
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("ConcreteTreeProcessor ready");
+ }
} finally {
this.manager.release(treeBuilder);
}
@@ -421,10 +439,10 @@
}
// Switch to the new processor (ensure it's never temporarily null)
- ConcreteTreeProcessor oldProcessor = this.concreteProcessor;
this.concreteProcessor = newProcessor;
this.lastModified = newLastModified;
+
// Dispose the old processor, if any
if (oldProcessor != null) {
oldProcessor.markForDisposal();
@@ -456,6 +474,7 @@
this.resolver.release(this.source.getSource());
this.source = null;
}
+ this.manager.release(this.fom);
this.manager.release(this.resolver);
this.resolver = null;
this.manager = null;