Author: ate
Date: Mon Sep 3 14:59:13 2012
New Revision: 1380262
URL: http://svn.apache.org/viewvc?rev=1380262&view=rev
Log:
RAVE-694: add support for dynamic mapping reloading, file config based only for
now
Modified:
rave/sandbox/content-services/demo-portal/src/main/webapp/WEB-INF/dispatcher-servlet.xml
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigManager.java
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigUtils.java
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/FileConfigManager.java
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/JcrConfigManager.java
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/HmvcHandlerMethodMappingByConfig.java
Modified:
rave/sandbox/content-services/demo-portal/src/main/webapp/WEB-INF/dispatcher-servlet.xml
URL:
http://svn.apache.org/viewvc/rave/sandbox/content-services/demo-portal/src/main/webapp/WEB-INF/dispatcher-servlet.xml?rev=1380262&r1=1380261&r2=1380262&view=diff
==============================================================================
---
rave/sandbox/content-services/demo-portal/src/main/webapp/WEB-INF/dispatcher-servlet.xml
(original)
+++
rave/sandbox/content-services/demo-portal/src/main/webapp/WEB-INF/dispatcher-servlet.xml
Mon Sep 3 14:59:13 2012
@@ -124,18 +124,6 @@
</bean>
</util:list>
- <!-- FILE BASED LOADING-->
- <!--
- <bean name="hmvcHandlerMappingByConfig"
class="org.apache.rave.portal.web.hmvc.HmvcHandlerMethodMappingByConfig">
- <property name="order" value="-1"/>
- <property name="interceptors" ref="interceptors"/>
- <property name="configurationName" value="myConfiguration"/>
- <property name="configurationPath"
value="classpath:page-configuration.xml"/>
- <property name="urlMappingsPath"
value="classpath:url-configuration.xml"/>
- <property name="configManager" ref="fileConfigurationManager"/>
- </bean>
- -->
-
<bean name="lazyRepositoryFactory"
class="org.apache.rave.jcr.LazyRepositoryFactory">
<constructor-arg>
<bean
class="org.apache.rave.jcr.servlet.ServletContextRepositoryFactory">
@@ -159,7 +147,7 @@
<constructor-arg index="4" value="true"/>
</bean>
- <!-- JCR LOADING -->
+ <!-- JCR|File based LOADING -->
<bean name="hmvcHandlerMappingByConfig"
class="org.apache.rave.portal.web.hmvc.HmvcHandlerMethodMappingByConfig"
depends-on="repositoryBootstrap" destroy-method="shutdown">
<property name="order" value="-1"/>
<property name="configManager" ref="fileConfigurationManager"/>
@@ -171,6 +159,7 @@
-->
<property name="configurationPath"
value="classpath:page-configuration.xml"/>
<property name="urlMappingsPath" value="classpath:url-mapping.xml"/>
+ <property name="refreshDelay" value="10000"/>
</bean>
<bean id="fileConfigurationManager"
class="org.apache.rave.jcr.config.FileConfigManager"/>
Modified:
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigManager.java
URL:
http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigManager.java?rev=1380262&r1=1380261&r2=1380262&view=diff
==============================================================================
---
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigManager.java
(original)
+++
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigManager.java
Mon Sep 3 14:59:13 2012
@@ -57,4 +57,6 @@ public interface ConfigManager {
void saveUrlConfiguration(UrlConfiguration configuration);
+
+ long lastModified(String name);
}
Modified:
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigUtils.java
URL:
http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigUtils.java?rev=1380262&r1=1380261&r2=1380262&view=diff
==============================================================================
---
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigUtils.java
(original)
+++
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/ConfigUtils.java
Mon Sep 3 14:59:13 2012
@@ -22,9 +22,11 @@ package org.apache.rave.jcr.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
+import java.net.URLConnection;
import java.net.URLDecoder;
import org.slf4j.Logger;
@@ -83,6 +85,27 @@ public final class ConfigUtils {
}
}
+ public static long lastModified(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalArgumentException("resourcePath parameter cannot
be <null>");
+ }
+ if (resourcePath.startsWith(FILE_PATH_PREFIX)) {
+ String fileName =
resourcePath.substring(FILE_PATH_PREFIX.length());
+ return new File(fileName).lastModified();
+ } else if (resourcePath.startsWith(CLASSPATH_PREFIX)) {
+ String classPath =
resourcePath.substring(CLASSPATH_PREFIX.length());
+ URL url =
FileConfigManager.class.getClassLoader().getResource(classPath);
+ if (url == null) {
+ return 0;
+ }
+ return new File(url.getFile()).lastModified();
+ } else {
+ // fallback
+ log.info("Neither file or classpath prefix used, trying to get
resource directly from '{}'", resourcePath);
+ return new File(resourcePath).lastModified();
+ }
+ }
+
public static InputStream getResourceInputStream(String resourcePath) {
if (resourcePath == null) {
throw new IllegalArgumentException("resourcePath parameter cannot
be <null>");
@@ -101,7 +124,15 @@ public final class ConfigUtils {
if (url == null) {
return null;
}
- return
FileConfigManager.class.getClassLoader().getResourceAsStream(classPath);
+ try {
+ // don't use ClassLoader.getResourceAsStream(path) as it
can/does internal caching
+ // of resources, making change/reload detection useless
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setUseCaches(false);
+ return urlConnection.getInputStream();
+ } catch (IOException e) {
+ return null;
+ }
} else {
// fallback
log.info("Neither file or classpath prefix used, trying to get
resource directly from '{}'", resourcePath);
Modified:
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/FileConfigManager.java
URL:
http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/FileConfigManager.java?rev=1380262&r1=1380261&r2=1380262&view=diff
==============================================================================
---
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/FileConfigManager.java
(original)
+++
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/FileConfigManager.java
Mon Sep 3 14:59:13 2012
@@ -107,5 +107,7 @@ public class FileConfigManager implement
throw new IllegalStateException("Not supported");
}
-
+ public long lastModified(String name) {
+ return ConfigUtils.lastModified(name);
+ }
}
Modified:
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/JcrConfigManager.java
URL:
http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/JcrConfigManager.java?rev=1380262&r1=1380261&r2=1380262&view=diff
==============================================================================
---
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/JcrConfigManager.java
(original)
+++
rave/sandbox/content-services/rave-jcr-integration/page-configuration/src/main/java/org/apache/rave/jcr/config/JcrConfigManager.java
Mon Sep 3 14:59:13 2012
@@ -155,5 +155,7 @@ public class JcrConfigManager implements
return new ObjectContentManagerImpl(session, mapper);
}
-
+ public long lastModified(String name) {
+ return 0;
+ }
}
Modified:
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/HmvcHandlerMethodMappingByConfig.java
URL:
http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/HmvcHandlerMethodMappingByConfig.java?rev=1380262&r1=1380261&r2=1380262&view=diff
==============================================================================
---
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/HmvcHandlerMethodMappingByConfig.java
(original)
+++
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/HmvcHandlerMethodMappingByConfig.java
Mon Sep 3 14:59:13 2012
@@ -19,6 +19,7 @@
package org.apache.rave.portal.web.hmvc;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -50,6 +51,7 @@ import org.springframework.web.bind.anno
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.HandlerMethodSelector;
+import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
@@ -66,8 +68,6 @@ public class HmvcHandlerMethodMappingByC
private static final Logger log =
LoggerFactory.getLogger(HmvcHandlerMethodMappingByConfig.class);
- private Map<RequestMappingInfo, HmvcHandlerMethod> hmvcHandlerMethods =
new LinkedHashMap<RequestMappingInfo, HmvcHandlerMethod>();
-
private LazyRepositoryFactory repositoryFactory;
private ConfigManager configManager;
@@ -78,13 +78,46 @@ public class HmvcHandlerMethodMappingByC
private String urlMappingsPath;
+ // delay refresh in milliseconds
+ private long refreshDelay;
+
+ private long configsLastChecked;
+
private boolean configured;
+ // temporary hacked open *reference* to the real but private
handlerMethods map in AbstractHandlerMethodMapping.java
+ private Map<RequestMappingInfo, HandlerMethod> handlerMethods;
+
/**
* Used only when JCR config manager is used
*/
private Credentials credentials;
+ public HmvcHandlerMethodMappingByConfig() {
+ super();
+ // temporary dirty hack to access private handlerMethods map in
AbstractHandlerMethodMapping.java
+ // see #getHandlerMethodsInternal() method which should be provided on
that class
+ try {
+ Field f =
AbstractHandlerMethodMapping.class.getDeclaredField("handlerMethods");
+ f.setAccessible(true);
+ try {
+ handlerMethods = (Map<RequestMappingInfo,
HandlerMethod>)f.get(this);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Unexpected", e);
+ }
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Unexpected", e);
+ }
+ // end temporary dirty hack
+ }
+
+ /**
+ * Temporary method which should be made available on super class
AbstractHandlerMethodMapping.java instead
+ * to allow access to the internal private handlerMethods map.
+ */
+ protected Map<RequestMappingInfo, HandlerMethod>
getHandlerMethodsInternal() {
+ return this.handlerMethods;
+ }
@Override
protected void initHandlerMethods() {
@@ -98,6 +131,7 @@ public class HmvcHandlerMethodMappingByC
} else {
configured = true;
+ configsLastChecked = System.currentTimeMillis();
final PageConfiguration configuration =
configManager.loadConfiguration(configurationPath);
final UrlConfiguration urlConfig =
configManager.loadUrlConfig(urlMappingsPath, configuration);
// TODO use urlConfig
@@ -105,6 +139,22 @@ public class HmvcHandlerMethodMappingByC
}
}
+ protected void reloadConfigIfNeeded() {
+ long currentTime = System.currentTimeMillis();
+ if (configured && (refreshDelay == 0 || configsLastChecked +
refreshDelay < currentTime)) {
+ synchronized (configManager) {
+ if ( configManager.lastModified(configurationPath) >
configsLastChecked ||
+ configManager.lastModified(urlMappingsPath) >
configsLastChecked ) {
+ final PageConfiguration configuration =
configManager.loadConfiguration(configurationPath);
+ final UrlConfiguration urlConfig =
configManager.loadUrlConfig(urlMappingsPath, configuration);
+ // TODO use urlConfig
+ processConfiguration(urlConfig);
+ }
+ }
+ configsLastChecked = currentTime;
+ }
+ }
+
@Override
public synchronized void repositoryAvailable(final Object factoryKey,
final Repository repository) {
Session session = null;
@@ -196,6 +246,9 @@ public class HmvcHandlerMethodMappingByC
private void processConfiguration(UrlConfiguration configuration) {
+ // reset
+ getHandlerMethodsInternal().clear();
+
for (UrlMapping urlMapping : configuration.getMappings()) {
PageDefinition pageDefinition = urlMapping.getPageDefinition();
final String controller = pageDefinition.getController();
@@ -221,10 +274,13 @@ public class HmvcHandlerMethodMappingByC
protected void registerPageHandlerMethod(PageDefinition pageDefinition,
Object handler, Method method, RequestMappingInfo mapping, String[] views) {
HmvcHandlerMethod hmvcHandlerMethod =
getHmvcHandlerMethodForFragment(handler, method, pageDefinition, views);
registerHandlerMethod(handler, method, mapping);
- hmvcHandlerMethods.put(mapping, hmvcHandlerMethod);
+ // replace default HandlerMethod with our own hmvcHandlerMethod
+ getHandlerMethodsInternal().put(mapping, hmvcHandlerMethod);
+ if (logger.isInfoEnabled()) {
+ logger.info("Remapped \"" + mapping + "\" onto hmvc " +
hmvcHandlerMethod);
+ }
}
-
private HmvcHandlerMethod getHmvcHandlerMethodForFragment(Object handler,
Method method, PageFragment fragment, String[] views) {
HmvcHandlerConfiguration config = new HmvcHandlerConfiguration();
config.setName(fragment.getName());
@@ -254,7 +310,6 @@ public class HmvcHandlerMethodMappingByC
return config.getMethod();
}
-
//*************************************************************************************
// UTILITIES
//*************************************************************************************
@@ -281,7 +336,6 @@ public class HmvcHandlerMethodMappingByC
return null;
}
-
private RequestMappingInfo createMappingInfo(RequestMapping annotation,
String path) {
final String[] patterns = {path};
log.info("Creating mapping for patterns:[{}]", patterns);
@@ -297,7 +351,6 @@ public class HmvcHandlerMethodMappingByC
null);
}
-
public void setConfigManager(ConfigManager configManager) {
this.configManager = configManager;
}
@@ -322,6 +375,10 @@ public class HmvcHandlerMethodMappingByC
this.repositoryFactory = repositoryFactory;
}
+ public void setRefreshDelay(long refreshDelay) {
+ this.refreshDelay = refreshDelay;
+ }
+
@Override
protected void handleMatch(RequestMappingInfo info, String lookupPath,
HttpServletRequest request) {
super.handleMatch(info, lookupPath, request);
@@ -334,6 +391,8 @@ public class HmvcHandlerMethodMappingByC
if (repositoryFactory != null) {
repositoryFactory.getRepository();
}
+ reloadConfigIfNeeded();
+
String lookupPath =
getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
@@ -350,9 +409,8 @@ public class HmvcHandlerMethodMappingByC
}
}
- if (handlerMethod != null && mapping != null &&
hmvcHandlerMethods.containsKey(mapping)) {
- // if available return hmvc variant instead
- handlerMethod = hmvcHandlerMethods.get(mapping);
+ if (handlerMethod != null && mapping != null) {
+ // we have a HmvcHandlerMethod match
request.setAttribute(HmvcHandlerMethod.class.getName(),
Boolean.TRUE);
}
return (handlerMethod != null) ?
handlerMethod.createWithResolvedBean() : null;