WW-3799 converts FileManager into a bean, adds default implementation and defines new extension point

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@1326928 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Lukasz Lenart
2012-04-17 05:03:45 +00:00
parent 73c976a028
commit 73e763faf8
59 changed files with 739 additions and 559 deletions
@@ -64,6 +64,9 @@ public final class StrutsConstants {
/** The com.opensymphony.xwork2.ObjectFactory implementation class */
public static final String STRUTS_OBJECTFACTORY = "struts.objectFactory";
/** The com.opensymphony.xwork2.util.FileManager implementation class */
public static final String STRUTS_FILEMANAGER = "struts.fileManager";
/** The com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation class */
public static final String STRUTS_OBJECTTYPEDETERMINER = "struts.objectTypeDeterminer";
@@ -22,6 +22,7 @@
package org.apache.struts2.config;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.UnknownHandlerManager;
@@ -189,6 +190,14 @@ import java.util.StringTokenizer;
* <td>singleton</td>
* <td>Helper class used with URLRenderer to provide exact logic for building URLs</td>
* </tr>
* <tr>
* <td>com.opensymphony.xwork2.FileManager</td>
* <td>struts.fileManager</td>
* <td>singleton</td>
* <td>Used to access files on the File System as also to monitor if reload is needed,
* can be implemented / overwritten to meet specific an application server needs
* </td>
* </tr>
* </table>
*
* <!-- END SNIPPET: extensionPoints -->
@@ -234,6 +243,7 @@ public class BeanSelectionProvider implements ConfigurationProvider {
public void register(ContainerBuilder builder, LocatableProperties props) {
alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);
alias(FileManager.class, StrutsConstants.STRUTS_FILEMANAGER, builder, props);
alias(XWorkConverter.class, StrutsConstants.STRUTS_XWORKCONVERTER, builder, props);
alias(TextProvider.class, StrutsConstants.STRUTS_XWORKTEXTPROVIDER, builder, props, Scope.DEFAULT);
alias(ActionProxyFactory.class, StrutsConstants.STRUTS_ACTIONPROXYFACTORY, builder, props);
@@ -24,6 +24,7 @@ package org.apache.struts2.dispatcher;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.config.Configuration;
@@ -39,7 +40,6 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
@@ -397,7 +397,8 @@ public class Dispatcher {
}
private void init_CheckConfigurationReloading(Container container) {
FileManager.setReloadingConfigs("true".equals(container.getInstance(String.class,
FileManager fileManager = container.getInstance(FileManager.class);
fileManager.setReloadingConfigs("true".equals(container.getInstance(String.class,
StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD)));
}
@@ -21,9 +21,10 @@
package org.apache.struts2.views.freemarker;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
@@ -176,6 +177,8 @@ public class FreemarkerManager {
protected String templateUpdateDelay;
protected Map<String,TagLibrary> tagLibraries;
private FileManager fileManager;
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setEncoding(String encoding) {
this.encoding = encoding;
@@ -211,6 +214,11 @@ public class FreemarkerManager {
this.tagLibraries = Collections.unmodifiableMap(map);
}
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
public boolean getNoCharsetInContentType() {
return noCharsetInContentType;
}
@@ -427,7 +435,8 @@ public class FreemarkerManager {
InputStream in = null;
try {
in = FileManager.loadFile("freemarker.properties", FreemarkerManager.class);
in = fileManager.loadFile(ClassLoaderUtil.getResource("freemarker.properties", getClass()));
if (in != null) {
Properties p = new Properties();
@@ -29,6 +29,9 @@
<bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />
<bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />
<bean type="com.opensymphony.xwork2.FileManager" class="com.opensymphony.xwork2.util.fs.DefaultFileManager" name="xwork"/>
<bean type="com.opensymphony.xwork2.FileManager" class="com.opensymphony.xwork2.util.fs.DefaultFileManager" name="struts"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" class="com.opensymphony.xwork2.DefaultActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/>
@@ -23,6 +23,7 @@ package org.apache.struts2.dispatcher;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
@@ -31,6 +32,7 @@ import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsTestCase;
@@ -194,6 +196,11 @@ public class DispatcherTest extends StrutsTestCase {
Mock mockContainer = new Mock(Container.class);
mockConfiguration.expectAndReturn("getContainer", mockContainer.proxy());
mockContainer.expectAndReturn("getInstance", C.args(C.eq(ObjectFactory.class)), destroyedObjectFactory);
mockConfiguration.expectAndReturn("getContainer", mockContainer.proxy());
mockConfiguration.expectAndReturn("getContainer", mockContainer.proxy());
FileManager fileManager = new DefaultFileManager();
mockContainer.expectAndReturn("getInstance", C.args(C.eq(FileManager.class)), fileManager);
mockContainer.expectAndReturn("getInstance", C.args(C.eq(FileManager.class)), fileManager);
mockConfiguration.expect("destroy");
mockConfiguration.matchAndReturn("getPackageConfigs", new HashMap<String, PackageConfig>());
@@ -221,7 +228,8 @@ public class DispatcherTest extends StrutsTestCase {
Mock mockContainer = new Mock(Container.class);
mockContainer.matchAndReturn("getInstance", C.args(C.eq(ObjectFactory.class)), new ObjectFactory());
mockContainer.matchAndReturn("getInstance", C.args(C.eq(FileManager.class)), new DefaultFileManager());
Mock mockConfiguration = new Mock(Configuration.class);
mockConfiguration.matchAndReturn("getPackageConfigs", packageConfigs);
mockConfiguration.matchAndReturn("getContainer", mockContainer.proxy());
@@ -21,17 +21,10 @@
package org.apache.struts2.dispatcher;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsConstants;
import com.mockobjects.servlet.MockFilterChain;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import org.apache.struts2.StrutsTestCase;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
@@ -41,14 +34,13 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import com.mockobjects.servlet.MockFilterChain;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Context;
import com.opensymphony.xwork2.inject.Factory;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
/**
* FilterDispatcher TestCase.
@@ -24,6 +24,7 @@ package org.apache.struts2.views.freemarker;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import com.opensymphony.xwork2.util.ValueStack;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
@@ -265,6 +266,7 @@ public class FreeMarkerResultTest extends StrutsTestCase {
super.setUp();
mgr = new FreemarkerManager();
mgr.setEncoding("UTF-8");
mgr.setFileManager(new DefaultFileManager());
stringWriter = new StringWriter();
writer = new PrintWriter(stringWriter);
response = new StrutsMockHttpServletResponse();
@@ -21,6 +21,7 @@
package org.apache.struts2.views.freemarker;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.StrutsTestCase;
import org.apache.struts2.views.jsp.StrutsMockServletContext;
@@ -33,6 +34,7 @@ public class FreemarkerManagerTest extends StrutsTestCase {
public void testIfStrutsEncodingIsSetProperty() throws Exception {
FreemarkerManager mgr = new FreemarkerManager();
mgr.setEncoding("UTF-8");
mgr.setFileManager(new DefaultFileManager());
StrutsMockServletContext servletContext = new StrutsMockServletContext();
servletContext.setAttribute(FreemarkerManager.CONFIG_SERVLET_CONTEXT_KEY, null);
freemarker.template.Configuration conf = mgr.getConfiguration(servletContext);
@@ -21,12 +21,19 @@
package org.apache.struts2.views.jsp.ui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Scope.Strategy;
import com.opensymphony.xwork2.validator.ValidationInterceptor;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.TestAction;
import org.apache.struts2.TestConfigurationProvider;
@@ -35,14 +42,11 @@ import org.apache.struts2.views.jsp.AbstractUITagTest;
import org.apache.struts2.views.jsp.ActionTag;
import org.easymock.EasyMock;
import com.opensymphony.xwork2.*;
import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Scope.Strategy;
import com.opensymphony.xwork2.validator.ValidationInterceptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -205,7 +209,7 @@ public class FormTagTest extends AbstractUITagTest {
public void removeScopeStrategy() {}
public void setScopeStrategy(Strategy scopeStrategy) {}
public <T> T getInstance(Class<T> type, String name) {return null;}
public <T> T getInstance(Class<T> type) {return null;}
public <T> T getInstance(Class<T> type) {return cont.getInstance(type);}
public Set<String> getInstanceNames(Class<?> type) {return null;}
public void inject(Object o) {
@@ -292,7 +296,7 @@ public class FormTagTest extends AbstractUITagTest {
public void removeScopeStrategy() {}
public void setScopeStrategy(Strategy scopeStrategy) {}
public <T> T getInstance(Class<T> type, String name) {return null;}
public <T> T getInstance(Class<T> type) {return null;}
public <T> T getInstance(Class<T> type) {return cont.getInstance(type);}
public Set<String> getInstanceNames(Class<?> type) {return null;}
public void inject(Object o) {
@@ -376,7 +380,7 @@ public class FormTagTest extends AbstractUITagTest {
public void removeScopeStrategy() {}
public void setScopeStrategy(Strategy scopeStrategy) {}
public <T> T getInstance(Class<T> type, String name) {return null;}
public <T> T getInstance(Class<T> type) {return null;}
public <T> T getInstance(Class<T> type) {return cont.getInstance(type);}
public Set<String> getInstanceNames(Class<?> type) {return null;}
public void inject(Object o) {
@@ -457,7 +461,7 @@ public class FormTagTest extends AbstractUITagTest {
public void removeScopeStrategy() {}
public void setScopeStrategy(Strategy scopeStrategy) {}
public <T> T getInstance(Class<T> type, String name) {return null;}
public <T> T getInstance(Class<T> type) {return null;}
public <T> T getInstance(Class<T> type) {return cont.getInstance(type);}
public Set<String> getInstanceNames(Class<?> type) {return null;}
public void inject(Object o) {
@@ -21,6 +21,7 @@
package org.apache.struts2.convention;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
@@ -31,7 +32,6 @@ import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.WildcardHelper;
import com.opensymphony.xwork2.util.classloader.ReloadingClassLoader;
@@ -109,6 +109,8 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder {
private static final String DEFAULT_METHOD = "execute";
private boolean eagerLoading = false;
private FileManager fileManager;
/**
* Constructs actions based on a list of packages.
*
@@ -293,6 +295,11 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder {
this.eagerLoading = "true".equals(eagerLoading);
}
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
protected void initReloadClassLoader() {
//when the configuration is reloaded, a new classloader will be setup
if (isReloadEnabled() && reloadingClassLoader == null)
@@ -911,7 +918,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder {
//watch class file
if (isReloadEnabled()) {
URL classFile = actionClass.getResource(actionClass.getSimpleName() + ".class");
FileManager.loadFile(classFile, false);
fileManager.monitorFile(classFile);
loadedFileUrls.add(classFile.toString());
}
}
@@ -1067,7 +1074,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder {
public boolean needsReload() {
if (devMode && reload) {
for (String url : loadedFileUrls) {
if (FileManager.fileNeedsReloading(url)) {
if (fileManager.fileNeedsReloading(url)) {
if (LOG.isDebugEnabled())
LOG.debug("File [#0] changed, configuration will be reloaded", url);
return true;
@@ -1,7 +1,8 @@
package org.apache.struts2.oval.interceptor;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import net.sf.oval.configuration.Configurer;
@@ -9,6 +10,7 @@ import net.sf.oval.configuration.annotation.AnnotationsConfigurer;
import net.sf.oval.configuration.annotation.JPAAnnotationsConfigurer;
import net.sf.oval.configuration.xml.XMLConfigurer;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -26,12 +28,19 @@ public class DefaultOValValidationManager implements OValValidationManager {
protected boolean validateJPAAnnotations;
private FileManager fileManager;
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
public synchronized List<Configurer> getConfigurers(Class clazz, String context, boolean validateJPAAnnotations) {
this.validateJPAAnnotations =validateJPAAnnotations;
final String validatorKey = buildValidatorKey(clazz, context);
if (validatorCache.containsKey(validatorKey)) {
if (FileManager.isReloadingConfigs()) {
if (fileManager.isReloadingConfigs()) {
List<Configurer> configurers = buildXMLConfigurers(clazz, context, true, null);
//add an annotation configurer
@@ -133,11 +142,12 @@ public class DefaultOValValidationManager implements OValValidationManager {
}
protected XMLConfigurer loadFile(String fileName, Class clazz, boolean checkFile) {
if ((checkFile && FileManager.fileNeedsReloading(fileName, clazz)) || !validatorFileCache.containsKey(fileName)) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
if ((checkFile && fileManager.fileNeedsReloading(fileUrl)) || !validatorFileCache.containsKey(fileName)) {
java.io.InputStream is = null;
try {
is = FileManager.loadFile(fileName, clazz);
is = fileManager.loadFile(fileUrl);
if (is != null) {
if (LOG.isDebugEnabled()) {
@@ -24,9 +24,9 @@ package org.apache.struts2.portlet.dispatcher;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
@@ -241,7 +241,8 @@ public class Jsr168Dispatcher extends GenericPortlet implements StrutsStatics {
container = dispatcherUtils.getContainer();
//check for configuration reloading
if ("true".equalsIgnoreCase(container.getInstance(String.class, StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD))) {
FileManager.setReloadingConfigs(true);
FileManager fileManager = container.getInstance(FileManager.class);
fileManager.setReloadingConfigs(true);
}
actionMapper = container.getInstance(ActionMapper.class);
@@ -0,0 +1,47 @@
package com.opensymphony.xwork2;
import java.io.InputStream;
import java.net.URL;
/**
* Basic interface to access file on the File System and to monitor changes
*/
public interface FileManager {
void setReloadingConfigs(boolean reloadingConfigs);
boolean isReloadingConfigs();
/**
* Checks if given file changed and must be reloaded if {@link #isReloadingConfigs()} is true
*
* @param fileName to check
* @return true if file changed
*/
boolean fileNeedsReloading(String fileName);
/**
* Checks if file represented by provided URL should be reloaded
*
* @param fileUrl url to a file
* @return true if file exists and should be reloaded, if url is null return false
*/
boolean fileNeedsReloading(URL fileUrl);
/**
* Loads opens the named file and returns the InputStream
*
* @param fileUrl - the URL of the file to open
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
InputStream loadFile(URL fileUrl);
/**
* Adds file to list of monitored files if {@link #isReloadingConfigs()} is true
*
* @param fileUrl {@link URL} to file to be monitored
*/
void monitorFile(URL fileUrl);
}
@@ -15,14 +15,14 @@
*/
package com.opensymphony.xwork2.config;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
@@ -69,7 +69,7 @@ public class ConfigurationManager {
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
conditionalReload();
conditionalReload(configuration.getContainer());
}
return configuration;
@@ -82,29 +82,6 @@ public class ConfigurationManager {
public synchronized void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
/**
* Get the current list of ConfigurationProviders. If no custom ConfigurationProviders have been added, this method
* will return a list containing only the default ConfigurationProvider, XMLConfigurationProvider. if a custom
* ConfigurationProvider has been added, then the XmlConfigurationProvider must be added by hand.
* </p>
* <p/>
* WARNING: This returns only ContainerProviders that can be cast into ConfigurationProviders
*
* @return the list of registered ConfigurationProvider objects
* @see ConfigurationProvider
* @deprecated Since 2.1, use {@link #getContainerProviders()}
*/
@Deprecated public List<ConfigurationProvider> getConfigurationProviders() {
List<ContainerProvider> contProviders = getContainerProviders();
List<ConfigurationProvider> providers = new ArrayList<ConfigurationProvider>();
for (ContainerProvider prov : contProviders) {
if (prov instanceof ConfigurationProvider) {
providers.add((ConfigurationProvider) prov);
}
}
return providers;
}
/**
* Get the current list of ConfigurationProviders. If no custom ConfigurationProviders have been added, this method
@@ -134,21 +111,7 @@ public class ConfigurationManager {
/**
* Set the list of configuration providers
*
* @param configurationProviders
* @deprecated Since 2.1, use {@link #setContainerProvider()}
*/
@Deprecated public void setConfigurationProviders(List<ConfigurationProvider> configurationProviders) {
// Silly copy necessary due to lack of ability to cast generic lists
List<ContainerProvider> contProviders = new ArrayList<ContainerProvider>();
contProviders.addAll(configurationProviders);
setContainerProviders(contProviders);
}
/**
* Set the list of configuration providers
*
* @param containerProviders
* @param containerProviders list of {@link ConfigurationProvider} to be set
*/
public void setContainerProviders(List<ContainerProvider> containerProviders) {
providerLock.lock();
@@ -159,17 +122,6 @@ public class ConfigurationManager {
}
}
/**
* adds a configuration provider to the List of ConfigurationProviders. a given ConfigurationProvider may be added
* more than once
*
* @param provider the ConfigurationProvider to register
* @deprecated Since 2.1, use {@link #addContainerProvider()}
*/
@Deprecated public void addConfigurationProvider(ConfigurationProvider provider) {
addContainerProvider(provider);
}
/**
* adds a configuration provider to the List of ConfigurationProviders. a given ConfigurationProvider may be added
* more than once
@@ -181,32 +133,24 @@ public class ConfigurationManager {
containerProviders.add(provider);
}
}
/**
* clears the registered ConfigurationProviders. this method will call destroy() on each of the registered
* ConfigurationProviders
*
* @see com.opensymphony.xwork2.config.ConfigurationProvider#destroy
* @deprecated Since 2.1, use {@link #clearContainerProviders()}
*/
@Deprecated public void clearConfigurationProviders() {
clearContainerProviders();
}
public void clearContainerProviders() {
for (ContainerProvider containerProvider : containerProviders) {
try {
containerProvider.destroy();
}
catch(Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("error while destroying container provider ["+containerProvider+"]", e);
}
}
clearContainerProvider(containerProvider);
}
containerProviders.clear();
}
private void clearContainerProvider(ContainerProvider containerProvider) {
try {
containerProvider.destroy();
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Error while destroying container provider [" + containerProvider + "]", e);
}
}
}
/**
* Destroy its managing Configuration instance
*/
@@ -221,59 +165,66 @@ public class ConfigurationManager {
/**
* Reloads the Configuration files if the configuration files indicate that they need to be reloaded.
* @param container current container used to obtain instance of {@link com.opensymphony.xwork2.util.fs.DefaultFileManager}
*/
public synchronized void conditionalReload() {
if (FileManager.isReloadingConfigs()) {
boolean reload;
public synchronized void conditionalReload(Container container) {
FileManager fileManager = container.getInstance(FileManager.class);
if (fileManager.isReloadingConfigs()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Checking ConfigurationProviders for reload.");
}
reload = false;
List<ContainerProvider> providers = getContainerProviders();
for (ContainerProvider provider : providers) {
if (provider.needsReload()) {
if (LOG.isInfoEnabled()) {
LOG.info("Detected container provider "+provider+" needs to be reloaded. Reloading all providers.");
}
reload = true;
//break;
}
boolean reload = needReloadContainerProviders(providers);
if (!reload) {
reload = needReloadPackageProviders();
}
if (packageProviders != null && reload) {
for (PackageProvider provider : packageProviders) {
if (provider.needsReload()) {
if (LOG.isInfoEnabled()) {
LOG.info("Detected package provider "+provider+" needs to be reloaded. Reloading all providers.");
}
reload = true;
//break;
}
}
}
if (reload) {
for (ContainerProvider containerProvider : containerProviders) {
try {
containerProvider.destroy();
}
catch(Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("error while destroying configuration provider ["+containerProvider+"]", e);
}
}
}
packageProviders = configuration.reloadContainer(providers);
reloadProviders(providers);
}
}
}
private boolean needReloadPackageProviders() {
if (packageProviders != null) {
for (PackageProvider provider : packageProviders) {
if (provider.needsReload()) {
if (LOG.isInfoEnabled()) {
LOG.info("Detected package provider " + provider + " needs to be reloaded. Reloading all providers.");
}
return true;
}
}
}
return false;
}
private boolean needReloadContainerProviders(List<ContainerProvider> providers) {
for (ContainerProvider provider : providers) {
if (provider.needsReload()) {
if (LOG.isInfoEnabled()) {
LOG.info("Detected container provider " + provider + " needs to be reloaded. Reloading all providers.");
}
return true;
}
}
return false;
}
private void reloadProviders(List<ContainerProvider> providers) {
for (ContainerProvider containerProvider : containerProviders) {
try {
containerProvider.destroy();
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("error while destroying configuration provider [" + containerProvider + "]", e);
}
}
}
packageProviders = this.configuration.reloadContainer(providers);
}
public synchronized void reload() {
packageProviders = getConfiguration().reloadContainer(getContainerProviders());
}
}
@@ -17,6 +17,7 @@ package com.opensymphony.xwork2.config.impl;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.DefaultTextProvider;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.config.Configuration;
@@ -52,6 +53,7 @@ import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import com.opensymphony.xwork2.util.PatternMatcher;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
@@ -200,8 +202,10 @@ public class DefaultConfiguration implements Configuration {
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
Container bootstrap = createBootstrapContainer();
for (final ContainerProvider containerProvider : providers)
{
bootstrap.inject(containerProvider);
containerProvider.init(this);
containerProvider.register(builder, props);
}
@@ -216,7 +220,7 @@ public class DefaultConfiguration implements Configuration {
ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
Container bootstrap = createBootstrapContainer();
setContext(bootstrap);
container = builder.create(false);
setContext(container);
@@ -265,6 +269,7 @@ public class DefaultConfiguration implements Configuration {
protected Container createBootstrapContainer() {
ContainerBuilder builder = new ContainerBuilder();
builder.factory(ObjectFactory.class, Scope.SINGLETON);
builder.factory(FileManager.class, DefaultFileManager.class, Scope.SINGLETON);
builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON);
builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON);
builder.factory(XWorkConverter.class, Scope.SINGLETON);
@@ -4,6 +4,7 @@ import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.DefaultActionProxyFactory;
import com.opensymphony.xwork2.DefaultTextProvider;
import com.opensymphony.xwork2.DefaultUnknownHandlerManager;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.TextProviderSupport;
import com.opensymphony.xwork2.UnknownHandlerManager;
@@ -39,6 +40,7 @@ import com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import com.opensymphony.xwork2.util.PatternMatcher;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.WildcardHelper;
@@ -87,6 +89,7 @@ public class XWorkConfigurationProvider implements ConfigurationProvider {
.factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON)
.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
.factory(XWorkConverter.class, Scope.SINGLETON)
.factory(FileManager.class, DefaultFileManager.class, Scope.SINGLETON)
.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON)
.factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON)
.factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON)
@@ -16,6 +16,7 @@
package com.opensymphony.xwork2.config.providers;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.config.Configuration;
@@ -73,6 +74,8 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
private Configuration configuration;
private boolean throwExceptionOnDuplicateBeans = true;
private FileManager fileManager;
public XmlConfigurationProvider() {
this("xwork.xml", true);
}
@@ -109,6 +112,11 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
this.objectFactory = objectFactory;
}
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
/**
* Returns an unmodifiable map of DTD mappings
*/
@@ -335,7 +343,7 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
public boolean needsReload() {
for (String url : loadedFileUrls) {
if (FileManager.fileNeedsReloading(url)) {
if (fileManager.fileNeedsReloading(url)) {
return true;
}
}
@@ -932,7 +940,7 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
while (urls.hasNext()) {
try {
url = urls.next();
is = FileManager.loadFile(url);
is = fileManager.loadFile(url);
InputSource in = new InputSource(is);
@@ -1038,4 +1046,11 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
List<Document> getDocuments() {
return documents;
}
@Override
public String toString() {
return "XmlConfigurationProvider{" +
"configFileName='" + configFileName + '\'' +
'}';
}
}
@@ -16,6 +16,7 @@
package com.opensymphony.xwork2.conversion.impl;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.XWorkMessages;
import com.opensymphony.xwork2.XWorkException;
@@ -181,7 +182,7 @@ public class XWorkConverter extends DefaultTypeConverter {
private TypeConverter defaultTypeConverter;
private ObjectFactory objectFactory;
private FileManager fileManager;
protected XWorkConverter() {
}
@@ -200,6 +201,11 @@ public class XWorkConverter extends DefaultTypeConverter {
this.defaultTypeConverter = conv;
}
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
public static String getConversionErrorMessage(String propertyName, ValueStack stack) {
String defaultMessage = LocalizedTextUtil.findDefaultText(XWorkMessages.DEFAULT_INVALID_FIELDVALUE,
ActionContext.getContext().getLocale(),
@@ -237,7 +243,7 @@ public class XWorkConverter extends DefaultTypeConverter {
return indexes;
}
public static String buildConverterFilename(Class clazz) {
public String buildConverterFilename(Class clazz) {
String className = clazz.getName();
return className.replace('.', '/') + "-conversion.properties";
}
@@ -481,7 +487,7 @@ public class XWorkConverter extends DefaultTypeConverter {
protected void addConverterMapping(Map<String, Object> mapping, Class clazz) {
try {
String converterFilename = buildConverterFilename(clazz);
InputStream is = FileManager.loadFile(converterFilename, clazz);
InputStream is = fileManager.loadFile(ClassLoaderUtil.getResource(converterFilename, clazz));
if (is != null) {
if (LOG.isDebugEnabled()) {
@@ -737,8 +743,9 @@ public class XWorkConverter extends DefaultTypeConverter {
private Map<String, Object> conditionalReload(Class clazz, Map<String, Object> oldValues) throws Exception {
Map<String, Object> mapping = oldValues;
if (FileManager.isReloadingConfigs()) {
if (FileManager.fileNeedsReloading(buildConverterFilename(clazz), clazz)) {
if (fileManager.isReloadingConfigs()) {
URL fileUrl = ClassLoaderUtil.getResource(buildConverterFilename(clazz), clazz);
if (fileManager.fileNeedsReloading(fileUrl.toString())) {
mapping = buildConverterMapping(clazz);
}
}
@@ -174,6 +174,8 @@ public class ClassLoaderUtil {
}
}
/**
* Aggregates Enumeration instances into one iterator and filters out duplicates. Always keeps one
* ahead of the enumerator to protect against returning duplicates.
@@ -1,324 +0,0 @@
/*
* Copyright 2002-2003,2009 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 com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
* FileManager
* <p/>
* This class was brought in from oscore trunk revision 147.
*
* @author Jason Carreira
* Created May 7, 2003 8:44:26 PM
*/
public class FileManager {
//~ Static fields/initializers /////////////////////////////////////////////
private static Logger LOG = LoggerFactory.getLogger(FileManager.class);
private static Map<String, Revision> files = Collections.synchronizedMap(new HashMap<String, Revision>());
protected static boolean reloadingConfigs = true;
private static final String JAR_FILE_NAME_SEPARATOR = "!/";
private static final String JAR_FILE_EXTENSION_END = ".jar/";
//~ Constructors ///////////////////////////////////////////////////////////
private FileManager() {
}
//~ Methods ////////////////////////////////////////////////////////////////
public static void setReloadingConfigs(boolean reloadingConfigs) {
FileManager.reloadingConfigs = reloadingConfigs;
}
public static boolean isReloadingConfigs() {
return reloadingConfigs;
}
public static boolean fileNeedsReloading(String fileName, Class clazz) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
return fileUrl != null && fileNeedsReloading(fileUrl.toString());
}
public static boolean fileNeedsReloading(String fileName) {
Revision revision = files.get(fileName);
if (revision == null) {
// no revision yet and we keep the revision history, so
// return whether the file needs to be loaded for the first time
return reloadingConfigs;
}
return revision.needsReloading();
}
/**
* Loads opens the named file and returns the InputStream
*
* @param fileName - the name of the file to open
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
public static InputStream loadFile(String fileName, Class clazz) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
return loadFile(fileUrl);
}
/**
* Loads opens the named file and returns the InputStream
*
* @param fileUrl - the URL of the file to open
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
public static InputStream loadFile(URL fileUrl) {
return loadFile(fileUrl, true);
}
/**
* Loads opens the named file and returns the InputStream
*
* @param fileUrl - the URL of the file to open
* @param openStream - if true, open an InputStream to the file and return it
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
public static InputStream loadFile(URL fileUrl, boolean openStream) {
if (fileUrl == null) {
return null;
}
String fileName = fileUrl.toString();
InputStream is = null;
if (openStream) {
try {
is = fileUrl.openStream();
if (is == null) {
throw new IllegalArgumentException("No file '" + fileName + "' found as a resource");
}
} catch (IOException e) {
throw new IllegalArgumentException("No file '" + fileName + "' found as a resource");
}
}
if (isReloadingConfigs()) {
Revision revision;
if (LOG.isDebugEnabled()) {
LOG.debug("Creating revision for URL: " +fileName);
}
if (URLUtil.isJBossUrl(fileUrl)) {
revision = JBossFileRevision.build(fileUrl);
} else if (URLUtil.isJarURL(fileUrl)) {
revision = JarEntryRevision.build(fileUrl);
} else {
revision = FileRevision.build(fileUrl);
}
if (revision == null) {
files.put(fileName, Revision.build(fileUrl));
} else {
files.put(fileName, revision);
}
}
return is;
}
//~ Inner Classes //////////////////////////////////////////////////////////
/**
* Class represents common revsion resource, should be used as default class when no other option exists
*/
private static class Revision {
public Revision() {
}
public boolean needsReloading() {
return false;
}
public static Revision build(URL fileUrl) {
return new Revision();
}
}
/**
* Represents file resource revision, used for file://* resources
*/
private static class FileRevision extends Revision {
private File file;
private long lastModified;
public FileRevision(File file, long lastUpdated) {
if (file == null) {
throw new IllegalArgumentException("File cannot be null");
}
this.file = file;
this.lastModified = lastUpdated;
}
public File getFile() {
return file;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public long getLastModified() {
return lastModified;
}
public boolean needsReloading() {
return this.lastModified < this.file.lastModified();
}
public static Revision build(URL fileUrl) {
File file;
try {
file = new File(fileUrl.toURI());
} catch (URISyntaxException e) {
file = new File(fileUrl.getPath());
} catch (Throwable t) {
return null;
}
if (file.exists() && file.canRead()) {
long lastModified = file.lastModified();
return new FileRevision(file, lastModified);
}
return null;
}
}
/**
* Represents file resource revision, used for vfszip://* resources
*/
private static class JBossFileRevision extends FileRevision {
public JBossFileRevision(File file, long lastUpdated) {
super(file, lastUpdated);
}
public static Revision build(URL fileUrl) {
File file;
URL url = URLUtil.normalizeToFileProtocol(fileUrl);
try {
if (url != null) {
file = new File(url.toURI());
} else {
return null;
}
} catch (URISyntaxException e) {
file = new File(url.getPath());
}
if (file.exists() && file.canRead()) {
long lastModified = file.lastModified();
return new FileRevision(file, lastModified);
}
return null;
}
}
/**
* Represents jar resurce revision, used for jar://* resource
*/
private static class JarEntryRevision extends Revision {
private String jarFileName;
private String fileNameInJar;
private long lastModified;
public JarEntryRevision(String jarFileName, String fileNameInJar, long lastModified) {
if ((jarFileName == null) || (fileNameInJar == null)) {
throw new IllegalArgumentException("JarFileName and FileNameInJar cannot be null");
}
this.jarFileName = jarFileName;
this.fileNameInJar = fileNameInJar;
this.lastModified = lastModified;
}
public boolean needsReloading() {
ZipEntry entry;
try {
JarFile jarFile = new JarFile(this.jarFileName);
entry = jarFile.getEntry(this.fileNameInJar);
}
catch (IOException e) {
entry = null;
}
return entry != null && (lastModified < entry.getTime());
}
public static Revision build(URL fileUrl) {
// File within a Jar
// Find separator index of jar filename and filename within jar
String jarFileName = "";
try {
String fileName = fileUrl.toString();
int separatorIndex = fileName.indexOf(JAR_FILE_NAME_SEPARATOR);
if (separatorIndex == -1) {
separatorIndex = fileName.lastIndexOf(JAR_FILE_EXTENSION_END);
}
if (separatorIndex == -1) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not find end of jar file!");
}
return null;
}
// Split file name
jarFileName = fileName.substring(0, separatorIndex);
int index = separatorIndex + JAR_FILE_NAME_SEPARATOR.length();
String fileNameInJar = fileName.substring(index).replaceAll("%20", " ");
URL url = URLUtil.normalizeToFileProtocol(fileUrl);
if (url != null) {
JarFile jarFile = new JarFile(FileUtils.toFile(url));
ZipEntry entry = jarFile.getEntry(fileNameInJar);
return new JarEntryRevision(jarFileName.toString(), fileNameInJar, entry.getTime());
} else {
return null;
}
} catch (Throwable e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not create JarEntryRevision for [" + jarFileName + "]!", e);
}
return null;
}
}
}
}
@@ -88,7 +88,6 @@ public class XWorkTestCaseHelper {
// clear out configuration
if (configurationManager != null) {
configurationManager.destroyConfiguration();
configurationManager = null;
}
ActionContext.setContext(null);
}
@@ -0,0 +1,114 @@
/*
* Copyright 2002-2003,2009 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 com.opensymphony.xwork2.util.fs;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.util.URLUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Default implementation of {@link FileManager}
*/
public class DefaultFileManager implements FileManager {
private static Logger LOG = LoggerFactory.getLogger(DefaultFileManager.class);
private Map<String, Revision> files = Collections.synchronizedMap(new HashMap<String, Revision>());
protected boolean reloadingConfigs = true;
static final String JAR_FILE_NAME_SEPARATOR = "!/";
static final String JAR_FILE_EXTENSION_END = ".jar/";
public DefaultFileManager() {
}
public void setReloadingConfigs(boolean reloadingConfigs) {
this.reloadingConfigs = reloadingConfigs;
}
public boolean isReloadingConfigs() {
return reloadingConfigs;
}
public boolean fileNeedsReloading(URL fileUrl) {
return fileUrl != null && fileNeedsReloading(fileUrl.toString());
}
public boolean fileNeedsReloading(String fileName) {
Revision revision = files.get(fileName);
if (revision == null) {
// no revision yet and we keep the revision history, so
// return whether the file needs to be loaded for the first time
return reloadingConfigs;
}
return revision.needsReloading();
}
public InputStream loadFile(URL fileUrl) {
if (fileUrl == null) {
return null;
}
InputStream is = openFile(fileUrl);
monitorFile(fileUrl);
return is;
}
private InputStream openFile(URL fileUrl) {
try {
InputStream is = fileUrl.openStream();
if (is == null) {
throw new IllegalArgumentException("No file '" + fileUrl + "' found as a resource");
}
return is;
} catch (IOException e) {
throw new IllegalArgumentException("No file '" + fileUrl + "' found as a resource");
}
}
public void monitorFile(URL fileUrl) {
if (isReloadingConfigs()) {
String fileName = fileUrl.toString();
Revision revision;
if (LOG.isDebugEnabled()) {
LOG.debug("Creating revision for URL: " +fileName);
}
if (URLUtil.isJBossUrl(fileUrl)) {
revision = JBossFileRevision.build(fileUrl);
} else if (URLUtil.isJarURL(fileUrl)) {
revision = JarEntryRevision.build(fileUrl);
} else {
revision = FileRevision.build(fileUrl);
}
if (revision == null) {
files.put(fileName, Revision.build(fileUrl));
} else {
files.put(fileName, revision);
}
}
}
}
@@ -0,0 +1,54 @@
package com.opensymphony.xwork2.util.fs;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
/**
* Represents file resource revision, used for file://* resources
*/
class FileRevision extends Revision {
private File file;
private long lastModified;
public FileRevision(File file, long lastUpdated) {
if (file == null) {
throw new IllegalArgumentException("File cannot be null");
}
this.file = file;
this.lastModified = lastUpdated;
}
public File getFile() {
return file;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public long getLastModified() {
return lastModified;
}
public boolean needsReloading() {
return this.lastModified < this.file.lastModified();
}
public static Revision build(URL fileUrl) {
File file;
try {
file = new File(fileUrl.toURI());
} catch (URISyntaxException e) {
file = new File(fileUrl.getPath());
} catch (Throwable t) {
return null;
}
if (file.exists() && file.canRead()) {
long lastModified = file.lastModified();
return new FileRevision(file, lastModified);
}
return null;
}
}
@@ -0,0 +1,36 @@
package com.opensymphony.xwork2.util.fs;
import com.opensymphony.xwork2.util.URLUtil;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
/**
* Represents file resource revision, used for vfszip://* resources
*/
class JBossFileRevision extends FileRevision {
public JBossFileRevision(File file, long lastUpdated) {
super(file, lastUpdated);
}
public static Revision build(URL fileUrl) {
File file;
URL url = URLUtil.normalizeToFileProtocol(fileUrl);
try {
if (url != null) {
file = new File(url.toURI());
} else {
return null;
}
} catch (URISyntaxException e) {
file = new File(url.getPath());
}
if (file.exists() && file.canRead()) {
long lastModified = file.lastModified();
return new FileRevision(file, lastModified);
}
return null;
}
}
@@ -0,0 +1,82 @@
package com.opensymphony.xwork2.util.fs;
import com.opensymphony.xwork2.util.URLUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.io.FileUtils;
import java.io.IOException;
import java.net.URL;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
* Represents jar resource revision, used for jar://* resource
*/
class JarEntryRevision extends Revision {
private static Logger LOG = LoggerFactory.getLogger(JarEntryRevision.class);
private String jarFileName;
private String fileNameInJar;
private long lastModified;
public JarEntryRevision(String jarFileName, String fileNameInJar, long lastModified) {
if ((jarFileName == null) || (fileNameInJar == null)) {
throw new IllegalArgumentException("JarFileName and FileNameInJar cannot be null");
}
this.jarFileName = jarFileName;
this.fileNameInJar = fileNameInJar;
this.lastModified = lastModified;
}
public boolean needsReloading() {
ZipEntry entry;
try {
JarFile jarFile = new JarFile(this.jarFileName);
entry = jarFile.getEntry(this.fileNameInJar);
}
catch (IOException e) {
entry = null;
}
return entry != null && (lastModified < entry.getTime());
}
public static Revision build(URL fileUrl) {
// File within a Jar
// Find separator index of jar filename and filename within jar
String jarFileName = "";
try {
String fileName = fileUrl.toString();
int separatorIndex = fileName.indexOf(DefaultFileManager.JAR_FILE_NAME_SEPARATOR);
if (separatorIndex == -1) {
separatorIndex = fileName.lastIndexOf(DefaultFileManager.JAR_FILE_EXTENSION_END);
}
if (separatorIndex == -1) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not find end of jar file!");
}
return null;
}
// Split file name
jarFileName = fileName.substring(0, separatorIndex);
int index = separatorIndex + DefaultFileManager.JAR_FILE_NAME_SEPARATOR.length();
String fileNameInJar = fileName.substring(index).replaceAll("%20", " ");
URL url = URLUtil.normalizeToFileProtocol(fileUrl);
if (url != null) {
JarFile jarFile = new JarFile(FileUtils.toFile(url));
ZipEntry entry = jarFile.getEntry(fileNameInJar);
return new JarEntryRevision(jarFileName.toString(), fileNameInJar, entry.getTime());
} else {
return null;
}
} catch (Throwable e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not create JarEntryRevision for [" + jarFileName + "]!", e);
}
return null;
}
}
}
@@ -0,0 +1,20 @@
package com.opensymphony.xwork2.util.fs;
import java.net.URL;
/**
* Class represents common revision resource, should be used as default class when no other option exists
*/
class Revision {
public Revision() {
}
public boolean needsReloading() {
return false;
}
public static Revision build(URL fileUrl) {
return new Revision();
}
}
@@ -19,9 +19,10 @@ package com.opensymphony.xwork2.validator;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
@@ -30,6 +31,7 @@ import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -59,6 +61,7 @@ public class AnnotationActionValidatorManager implements ActionValidatorManager
private ValidatorFactory validatorFactory;
private ValidatorFileParser validatorFileParser;
private FileManager fileManager;
@Inject
public void setValidatorFactory(ValidatorFactory fac) {
@@ -70,6 +73,11 @@ public class AnnotationActionValidatorManager implements ActionValidatorManager
this.validatorFileParser = parser;
}
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
public List<Validator> getValidators(Class clazz, String context) {
return getValidators(clazz, context, null);
}
@@ -79,7 +87,7 @@ public class AnnotationActionValidatorManager implements ActionValidatorManager
final List<ValidatorConfig> cfgs;
if (validatorCache.containsKey(validatorKey)) {
if (FileManager.isReloadingConfigs()) {
if (fileManager.isReloadingConfigs()) {
validatorCache.put(validatorKey, buildValidatorConfigs(clazz, context, true, null));
}
} else {
@@ -366,11 +374,13 @@ public class AnnotationActionValidatorManager implements ActionValidatorManager
private List<ValidatorConfig> loadFile(String fileName, Class clazz, boolean checkFile) {
List<ValidatorConfig> retList = Collections.emptyList();
if ((checkFile && FileManager.fileNeedsReloading(fileName, clazz)) || !validatorFileCache.containsKey(fileName)) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
if ((checkFile && fileManager.fileNeedsReloading(fileUrl)) || !validatorFileCache.containsKey(fileName)) {
InputStream is = null;
try {
is = FileManager.loadFile(fileName, clazz);
is = fileManager.loadFile(fileUrl);
if (is != null) {
retList = new ArrayList<ValidatorConfig>(validatorFileParser.parseActionValidatorConfigs(validatorFactory, is, fileName));
@@ -16,8 +16,9 @@
package com.opensymphony.xwork2.validator;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
@@ -25,6 +26,7 @@ import com.opensymphony.xwork2.validator.validators.VisitorFieldValidator;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
@@ -51,6 +53,7 @@ public class DefaultActionValidatorManager implements ActionValidatorManager {
private final Logger LOG = LoggerFactory.getLogger(DefaultActionValidatorManager.class);
private ValidatorFactory validatorFactory;
private ValidatorFileParser validatorFileParser;
private FileManager fileManager;
@Inject
public void setValidatorFileParser(ValidatorFileParser parser) {
@@ -62,6 +65,11 @@ public class DefaultActionValidatorManager implements ActionValidatorManager {
this.validatorFactory = fac;
}
@Inject
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
public synchronized List<Validator> getValidators(Class clazz, String context) {
return getValidators(clazz, context, null);
}
@@ -70,7 +78,7 @@ public class DefaultActionValidatorManager implements ActionValidatorManager {
final String validatorKey = buildValidatorKey(clazz, context);
if (validatorCache.containsKey(validatorKey)) {
if (FileManager.isReloadingConfigs()) {
if (fileManager.isReloadingConfigs()) {
validatorCache.put(validatorKey, buildValidatorConfigs(clazz, context, true, null));
}
} else {
@@ -318,11 +326,12 @@ public class DefaultActionValidatorManager implements ActionValidatorManager {
private List<ValidatorConfig> loadFile(String fileName, Class clazz, boolean checkFile) {
List<ValidatorConfig> retList = Collections.emptyList();
if ((checkFile && FileManager.fileNeedsReloading(fileName, clazz)) || !validatorFileCache.containsKey(fileName)) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
if ((checkFile && fileManager.fileNeedsReloading(fileUrl.toString())) || !validatorFileCache.containsKey(fileName)) {
InputStream is = null;
try {
is = FileManager.loadFile(fileName, clazz);
is = fileManager.loadFile(fileUrl);
if (is != null) {
retList = new ArrayList<ValidatorConfig>(validatorFileParser.parseActionValidatorConfigs(validatorFactory, is, fileName));
@@ -96,6 +96,8 @@ public class ActionInvocationTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider);
}
}
@@ -40,7 +40,9 @@ public class ChainResultTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider);
}
public void testNamespaceAndActionExpressionEvaluation() throws Exception {
@@ -31,7 +31,9 @@ public class DefaultClasstTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider);
}
public void testWildCardEvaluation() throws Exception {
@@ -59,7 +59,10 @@ public class LocaleAwareTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"), new MockConfigurationProvider());
super.setUp();
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider, new MockConfigurationProvider());
ValueStack stack = container.getInstance(ValueStackFactory.class).createValueStack();
stack.getContext().put(ActionContext.CONTAINER, container);
@@ -44,6 +44,8 @@ public class ProxyInvocationTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-proxyinvoke.xml"));
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-proxyinvoke.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider);
}
}
@@ -32,7 +32,9 @@ public class WildCardResultTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider);
}
public void testWildCardEvaluation() throws Exception {
@@ -19,10 +19,10 @@ package com.opensymphony.xwork2.config;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import java.util.Properties;
@@ -37,11 +37,10 @@ import java.util.Properties;
public class ConfigurationManagerTest extends XWorkTestCase {
Mock configProviderMock;
private FileManager fileManager;
private Configuration configuration;
public void testConfigurationReload() {
FileManager.setReloadingConfigs(true);
// now check that it reloads
configProviderMock.expectAndReturn("needsReload", Boolean.TRUE);
configProviderMock.expect("init", C.isA(Configuration.class));
@@ -49,7 +48,8 @@ public class ConfigurationManagerTest extends XWorkTestCase {
configProviderMock.expect("loadPackages", C.ANY_ARGS);
configProviderMock.expect("destroy", C.ANY_ARGS);
configProviderMock.matchAndReturn("toString", "mock");
configurationManager.getConfiguration();
configuration.getContainer().getInstance(FileManager.class).setReloadingConfigs(true);
configuration = configurationManager.getConfiguration();
configProviderMock.verify();
// this will be called in teardown
@@ -57,10 +57,10 @@ public class ConfigurationManagerTest extends XWorkTestCase {
}
public void testNoConfigurationReload() {
FileManager.setReloadingConfigs(false);
// now check that it doesn't try to reload
configurationManager.getConfiguration();
configuration.getContainer().getInstance(FileManager.class).setReloadingConfigs(false);
configuration = configurationManager.getConfiguration();
configProviderMock.verify();
// this will be called in teardown
@@ -162,20 +162,20 @@ public class ConfigurationManagerTest extends XWorkTestCase {
ConfigurationProvider mockProvider = (ConfigurationProvider) configProviderMock.proxy();
configurationManager.addContainerProvider(new XWorkConfigurationProvider());
configurationManager.addContainerProvider(mockProvider);
//the first time it always inits
configProviderMock.expect("init", C.isA(Configuration.class));
configProviderMock.expect("register", C.ANY_ARGS);
configProviderMock.expect("loadPackages", C.ANY_ARGS);
configProviderMock.matchAndReturn("toString", "mock");
configurationManager.getConfiguration();
configuration = configurationManager.getConfiguration();
}
@Override
protected void tearDown() throws Exception {
configProviderMock.expect("destroy");
FileManager.setReloadingConfigs(true);
super.tearDown();
}
}
@@ -207,7 +207,11 @@ public class ConfigurationTest extends XWorkTestCase {
}
public void testMultipleContainerProviders() throws Exception {
System.out.println("-----");
// to start from scratch
configurationManager.destroyConfiguration();
// to build basic configuration
configurationManager.getConfiguration();
Mock mockContainerProvider = new Mock(ContainerProvider.class);
mockContainerProvider.expect("init", C.ANY_ARGS);
mockContainerProvider.expect("register", C.ANY_ARGS);
@@ -215,7 +219,11 @@ public class ConfigurationTest extends XWorkTestCase {
mockContainerProvider.matchAndReturn("toString", "foo");
mockContainerProvider.matchAndReturn("destroy", null);
mockContainerProvider.expectAndReturn("needsReload", true);
// the order of providers must be changed as just first is checked if reload is needed
configurationManager.addContainerProvider((ContainerProvider) mockContainerProvider.proxy());
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(provider);
configurationManager.addContainerProvider(provider);
Configuration config = null;
try {
@@ -225,13 +233,11 @@ public class ConfigurationTest extends XWorkTestCase {
fail();
}
RuntimeConfiguration configuration = config.getRuntimeConfiguration();
// check that it has configuration from xml
assertNotNull(configuration.getActionConfig("/foo/bar", "Bar"));
System.out.println("-----");
mockContainerProvider.verify();
}
@@ -302,9 +308,11 @@ public class ConfigurationTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(provider);
loadConfigurationProviders(provider);
}
public static class MyPackageProvider implements PackageProvider {
static Configuration config;
public void loadPackages() throws ConfigurationException {}
@@ -15,6 +15,7 @@
*/
package com.opensymphony.xwork2.config.providers;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.config.ConfigurationProvider;
@@ -36,6 +37,7 @@ public abstract class ConfigurationTestBase extends XWorkTestCase {
XmlConfigurationProvider prov = new XmlConfigurationProvider(filename, true);
prov.setObjectFactory(container.getInstance(ObjectFactory.class));
prov.setFileManager(container.getInstance(FileManager.class));
prov.init(configuration);
prov.loadPackages();
return prov;
@@ -21,6 +21,7 @@ import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import java.util.ArrayList;
import java.util.List;
@@ -34,6 +35,7 @@ public class XmlConfigurationProviderInterceptorParamOverridingTest extends XWor
public void testInterceptorParamOveriding() throws Exception {
DefaultConfiguration conf = new DefaultConfiguration();
final XmlConfigurationProvider p = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-interceptor-param-overriding.xml");
p.setFileManager(new DefaultFileManager());
conf.reload(new ArrayList<ConfigurationProvider>() {
{
add(new XWorkConfigurationProvider());
@@ -6,6 +6,7 @@ import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import java.util.ArrayList;
import java.util.List;
@@ -21,6 +22,7 @@ public class XmlConfigurationProviderInterceptorStackParamOverridingTest extends
public void testInterceptorStackParamOveriding() throws Exception {
DefaultConfiguration conf = new DefaultConfiguration();
final XmlConfigurationProvider p = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-interceptor-stack-param-overriding.xml");
p.setFileManager(new DefaultFileManager());
configurationManager.addContainerProvider(p);
conf.reload(new ArrayList<ConfigurationProvider>(){
{
@@ -97,7 +97,9 @@ public class XmlConfigurationProviderInterceptorsTest extends ConfigurationTestB
}
public void testInterceptorDefaultRefs() throws ConfigurationException {
loadConfigurationProviders(new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-interceptor-defaultref.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-interceptor-defaultref.xml");
container.inject(provider);
loadConfigurationProviders(provider);
// expectations - the inherited interceptor stack
// default package
@@ -15,13 +15,13 @@
*/
package com.opensymphony.xwork2.config.providers;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.impl.MockConfiguration;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.FileManager;
import org.w3c.dom.Document;
import java.io.File;
@@ -51,6 +51,7 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
}
};
prov.setObjectFactory(container.getInstance(ObjectFactory.class));
prov.setFileManager(container.getInstance(FileManager.class));
prov.init(configuration);
List<Document> docs = prov.getDocuments();
assertEquals(3, docs.size());
@@ -73,7 +74,7 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
}
public void testNeedsReload() throws Exception {
FileManager.setReloadingConfigs(true);
container.getInstance(FileManager.class).setReloadingConfigs(true);
final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-actions.xml";
ConfigurationProvider provider = buildConfigurationProvider(filename);
@@ -149,7 +150,7 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
public void testEmptySpaces() throws Exception {
final String filename = "com/opensymphony/xwork2/config/providers/xwork- test.xml";
FileManager.setReloadingConfigs(true);
container.getInstance(FileManager.class).setReloadingConfigs(true);
ConfigurationProvider provider = buildConfigurationProvider(filename);
assertTrue(!provider.needsReload());
@@ -165,7 +166,7 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
}
public void testConfigsInJarFiles() throws Exception {
FileManager.setReloadingConfigs(true);
container.getInstance(FileManager.class).setReloadingConfigs(true);
testProvider("xwork-jar.xml");
testProvider("xwork-zip.xml");
testProvider("xwork - jar.xml");
@@ -46,7 +46,9 @@ public class AliasInterceptorTest extends XWorkTestCase {
Map<String, Object> params = new HashMap<String, Object>();
params.put("aliasSource", "source here");
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(provider);
loadConfigurationProviders(provider);
ActionProxy proxy = actionProxyFactory.createActionProxy("", "aliasTest", params);
SimpleAction actionOne = (SimpleAction) proxy.getAction();
actionOne.setAliasSource("name to be copied");
@@ -339,7 +339,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
}
public void testNonexistentParametersGetLoggedInDevMode() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"),
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider,
new MockConfigurationProvider(Collections.singletonMap("devMode", "true")));
Map<String, Object> params = new HashMap<String, Object>();
params.put("not_a_property", "There is no action property named like this");
@@ -357,7 +359,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
}
public void testNonexistentParametersAreIgnoredInProductionMode() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"),
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider,
new MockConfigurationProvider(Collections.singletonMap("devMode", "false")));
Map<String, Object> params = new HashMap<String, Object>();
params.put("not_a_property", "There is no action property named like this");
@@ -571,7 +575,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"), new MockConfigurationProvider());
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME);
container.inject(config.getInterceptors().get(0).getInterceptor());
@@ -40,8 +40,11 @@ public class AnnotationWorkflowInterceptorTest extends XWorkTestCase {
private final AnnotationWorkflowInterceptor annotationWorkflow = new AnnotationWorkflowInterceptor();
@Override
public void setUp() {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-default.xml"), new MockConfigurationProvider());
public void setUp() throws Exception{
super.setUp();
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-default.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
}
public void testInterceptsBeforeAndAfter() throws Exception {
@@ -19,7 +19,9 @@ public class ActionsFromSpringTest extends XWorkTestCase {
super.setUp();
// Set up XWork
loadConfigurationProviders(new XmlConfigurationProvider("com/opensymphony/xwork2/spring/actionContext-xwork.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("com/opensymphony/xwork2/spring/actionContext-xwork.xml");
container.inject(provider);
loadConfigurationProviders(provider);
appContext = ((SpringObjectFactory)container.getInstance(ObjectFactory.class)).appContext;
}
@@ -38,8 +38,10 @@ public class ActionAutowiringInterceptorTest extends XWorkTestCase {
public void testSetAutowireType() throws Exception {
XmlConfigurationProvider prov = new XmlConfigurationProvider("xwork-default.xml");
container.inject(prov);
prov.setThrowExceptionOnDuplicateBeans(false);
XmlConfigurationProvider c = new XmlConfigurationProvider("com/opensymphony/xwork2/spring/xwork-autowire.xml");
container.inject(c);
loadConfigurationProviders(c, prov);
StaticWebApplicationContext appContext = new StaticWebApplicationContext();
@@ -1,5 +1,6 @@
package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.XWorkTestCase;
import java.io.InputStream;
@@ -12,7 +13,15 @@ import java.net.URL;
* @since <pre>02/18/2009</pre>
* @version 1.0
*/
public class FileManagerTest extends XWorkTestCase {
public class DefaultFileManagerTest extends XWorkTestCase {
private FileManager fileManager;
@Override
public void setUp() throws Exception {
super.setUp();
fileManager = container.getInstance(FileManager.class);
}
public void testGetFileInJar() throws Exception {
testLoadFile("xwork-jar.xml");
@@ -26,11 +35,11 @@ public class FileManagerTest extends XWorkTestCase {
}
private void testLoadFile(String fileName) {
FileManager.setReloadingConfigs(true);
URL url = ClassLoaderUtil.getResource(fileName, FileManagerTest.class);
InputStream file = FileManager.loadFile(url, true);
fileManager.setReloadingConfigs(true);
URL url = ClassLoaderUtil.getResource(fileName, DefaultFileManagerTest.class);
InputStream file = fileManager.loadFile(url);
assertNotNull(file);
assertFalse(!FileManager.fileNeedsReloading(fileName));
assertFalse(!fileManager.fileNeedsReloading(fileName));
}
}
@@ -246,7 +246,9 @@ public class LocalizedTextUtilTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(provider);
loadConfigurationProviders(provider);
ActionContext.getContext().setLocale(Locale.US);
}
@@ -97,6 +97,8 @@ public class MyBeanActionTest extends XWorkTestCase {
super.setUp();
// ensure we're using the default configuration, not simple config
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(provider);
loadConfigurationProviders(provider);
}
}
@@ -15,14 +15,29 @@
*/
package com.opensymphony.xwork2.validator;
import com.opensymphony.xwork2.*;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.AnnotatedTestBean;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.SimpleAction;
import com.opensymphony.xwork2.SimpleAnnotationAction;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.test.AnnotationDataAware2;
import com.opensymphony.xwork2.test.AnnotationUser;
import com.opensymphony.xwork2.test.SimpleAnnotationAction2;
import com.opensymphony.xwork2.test.SimpleAnnotationAction3;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.validator.validators.*;
import com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator;
import com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator;
import com.opensymphony.xwork2.validator.validators.EmailValidator;
import com.opensymphony.xwork2.validator.validators.ExpressionValidator;
import com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator;
import com.opensymphony.xwork2.validator.validators.RequiredFieldValidator;
import com.opensymphony.xwork2.validator.validators.RequiredStringValidator;
import com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator;
import com.opensymphony.xwork2.validator.validators.URLValidator;
import org.easymock.EasyMock;
import java.util.List;
@@ -83,10 +98,11 @@ public class AnnotationActionValidatorManagerTest extends XWorkTestCase {
}
public void testGetValidatorsForGivenMethodNameWithoutReloading() throws ValidationException {
FileManager fileManager = container.getInstance(FileManager.class);
List validatorList = annotationActionValidatorManager.getValidators(SimpleAnnotationAction.class, alias, "execute");
//disable configuration reload/devmode
FileManager.setReloadingConfigs(false);
fileManager.setReloadingConfigs(false);
//17 in the class level + 0 in the alias
assertEquals(12, validatorList.size());
@@ -22,6 +22,7 @@ import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.test.DataAware2;
import com.opensymphony.xwork2.test.SimpleAction2;
import com.opensymphony.xwork2.test.SimpleAction3;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import com.opensymphony.xwork2.util.ValueStack;
import junit.framework.TestCase;
@@ -56,6 +57,8 @@ public class DefaultActionValidatorManagerTest extends TestCase {
mockValidatorFactory = new Mock(ValidatorFactory.class);
actionValidatorManager.setValidatorFactory((ValidatorFactory)mockValidatorFactory.proxy());
actionValidatorManager.setFileManager(new DefaultFileManager());
stubValueStack = new StubValueStack();
ActionContext.setContext(new ActionContext(new HashMap<String, Object>()));
ActionContext.getContext().setValueStack(stubValueStack);
@@ -177,7 +177,10 @@ public class DoubleRangeValidatorTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-default.xml"), new MockConfigurationProvider());
super.setUp();
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-default.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
val = new DoubleRangeFieldValidator();
val.setValueStack(ActionContext.getContext().getValueStack());
}
@@ -62,6 +62,9 @@ public class IntRangeValidatorTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"), new MockConfigurationProvider());
super.setUp();
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
}
}
@@ -60,6 +60,9 @@ public class LongRangeValidatorTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"), new MockConfigurationProvider());
super.setUp();
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
}
}
@@ -38,7 +38,9 @@ public class ModelDrivenValidationTest extends XWorkTestCase {
Map<String, Object> context = new HashMap<String, Object>();
context.put(ActionContext.PARAMETERS, params);
loadConfigurationProviders(new XmlConfigurationProvider("xwork-sample.xml"));
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(provider);
loadConfigurationProviders(provider);
ActionProxy proxy = actionProxyFactory.createActionProxy(null, "TestModelDrivenValidation", context);
assertEquals(Action.SUCCESS, proxy.execute());
@@ -60,6 +60,9 @@ public class ShortRangeValidatorTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"), new MockConfigurationProvider());
super.setUp();
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
}
}
@@ -224,10 +224,13 @@ public class SimpleActionValidationTest extends XWorkTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
origLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
loadConfigurationProviders(new XmlConfigurationProvider("xwork-test-beans.xml"), new MockConfigurationProvider());
XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-test-beans.xml");
container.inject(provider);
loadConfigurationProviders(provider, new MockConfigurationProvider());
}
@Override
@@ -110,7 +110,11 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
protected void setUp() throws Exception {
super.setUp();
loadConfigurationProviders(new XmlConfigurationProvider("xwork-default.xml"), new XmlConfigurationProvider("xwork-test-validation.xml"));
XmlConfigurationProvider provider1 = new XmlConfigurationProvider("xwork-default.xml");
container.inject(provider1);
XmlConfigurationProvider provider2 = new XmlConfigurationProvider("xwork-test-validation.xml");
container.inject(provider2);
loadConfigurationProviders(provider1, provider2);
}
}