/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.myfaces.extensions.validator.test.base; | |
import junit.framework.TestCase; | |
import org.apache.shale.test.mock.*; | |
import org.apache.shale.test.el.MockExpressionFactory; | |
import org.apache.myfaces.extensions.validator.ExtValInformation; | |
import org.apache.myfaces.extensions.validator.test.base.mock.*; | |
import org.apache.myfaces.extensions.validator.test.base.util.TestUtils; | |
import org.apache.myfaces.extensions.validator.util.ExtValUtils; | |
import org.apache.myfaces.extensions.validator.core.renderkit.DefaultRenderKitWrapperFactory; | |
import org.apache.myfaces.extensions.validator.core.startup.ExtValStartupListener; | |
import org.apache.myfaces.extensions.validator.core.factory.DefaultFactoryFinder; | |
import org.apache.myfaces.extensions.validator.core.factory.FactoryNames; | |
import org.apache.myfaces.extensions.validator.core.ExtValContext; | |
import org.apache.myfaces.extensions.validator.core.ExtValCoreConfiguration; | |
import org.apache.myfaces.extensions.validator.core.DefaultExtValCoreConfiguration; | |
import org.apache.myfaces.extensions.validator.core.ExtValModuleConfiguration; | |
import org.apache.myfaces.extensions.validator.core.el.AbstractELHelperFactory; | |
import org.apache.myfaces.extensions.validator.core.el.ELHelper; | |
import org.apache.myfaces.shared_impl.config.MyfacesConfig; | |
import javax.faces.render.RenderKit; | |
import javax.faces.render.RenderKitFactory; | |
import javax.faces.FactoryFinder; | |
import javax.faces.el.ValueBinding; | |
import javax.faces.application.ApplicationFactory; | |
import javax.faces.application.FacesMessage; | |
import javax.faces.component.UIViewRoot; | |
import javax.faces.component.UIInput; | |
import javax.el.ValueExpression; | |
import java.net.URLClassLoader; | |
import java.net.URL; | |
import java.io.StringWriter; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Modifier; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
/** | |
* Abstract Shale Test base class, which sets up the JSF environment. If the test | |
* overrides <code>setUp()</code> and/or <code>tearDown()</code>, then those | |
* methods but call the overwitten method to insure a valid test environment. | |
*/ | |
@SuppressWarnings("deprecation") | |
public abstract class AbstractExValTestCase extends TestCase | |
{ | |
protected MockApplication application; | |
protected MockServletConfig config; | |
protected MockExternalContext externalContext; | |
protected MockFacesContext facesContext; | |
protected MockFacesContextFactory facesContextFactory; | |
protected MockLifecycle lifecycle; | |
protected MockLifecycleFactory lifecycleFactory; | |
protected RenderKit renderKit; | |
protected MockHttpServletRequest request; | |
protected MockHttpServletResponse response; | |
protected MockServletContext servletContext; | |
protected MockHttpSession session; | |
protected MockExpressionFactory expressionFactory; | |
private ClassLoader threadContextClassLoader; | |
/** Response Writer */ | |
private MockResponseWriter writer; | |
/** | |
* Construct a new instance of the test. | |
* | |
* @param name Name of the test. | |
*/ | |
public AbstractExValTestCase(String name) | |
{ | |
super(name); | |
application = null; | |
config = null; | |
externalContext = null; | |
facesContext = null; | |
facesContextFactory = null; | |
lifecycle = null; | |
lifecycleFactory = null; | |
renderKit = null; | |
request = null; | |
response = null; | |
servletContext = null; | |
session = null; | |
expressionFactory = null; | |
threadContextClassLoader = null; | |
} | |
/** | |
* Setup the test environment, including the following: | |
* <ul> | |
* <li>Set the Application Map.</li> | |
* <li>Set a response writer</li> | |
* <li>Add Tomahawk's renderers to the faces context.</li> | |
* </ul> | |
*/ | |
protected void setUp() throws Exception | |
{ | |
threadContextClassLoader = Thread.currentThread().getContextClassLoader(); | |
Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0], getClass().getClassLoader())); | |
servletContext = new MockServletContext(); | |
//for testing the fallback | |
//servletContext.addInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + ".DEACTIVATE_EL_RESOLVER", "true"); | |
servletContext.addInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + ".CUSTOM_VALIDATION_STRATEGY_FACTORY", MockValidationStrategyFactory.class.getName()); | |
servletContext.addInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + ".CUSTOM_MESSAGE_RESOLVER_FACTORY", MockMessageResolverFactory.class.getName()); | |
servletContext.addInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + ".CUSTOM_META_DATA_TRANSFORMER_FACTORY", MockMetaDataTransformerFactory.class.getName()); | |
addInitializationParameters(); | |
config = new MockServletConfig(servletContext); | |
session = new MockHttpSession(); | |
session.setServletContext(servletContext); | |
request = new MockHttpServletRequest(session); | |
request.setServletContext(servletContext); | |
response = new MockHttpServletResponse(); | |
FactoryFinder.releaseFactories(); | |
FactoryFinder.setFactory("javax.faces.application.ApplicationFactory", ExtValMockApplicationFactory.class.getName()); | |
FactoryFinder.setFactory("javax.faces.context.FacesContextFactory", "org.apache.shale.test.mock.MockFacesContextFactory"); | |
FactoryFinder.setFactory("javax.faces.lifecycle.LifecycleFactory", "org.apache.shale.test.mock.MockLifecycleFactory"); | |
FactoryFinder.setFactory("javax.faces.render.RenderKitFactory", "org.apache.shale.test.mock.MockRenderKitFactory"); | |
externalContext = new MockExternalContext(servletContext, request, response); | |
lifecycleFactory = (MockLifecycleFactory)FactoryFinder.getFactory("javax.faces.lifecycle.LifecycleFactory"); | |
lifecycle = (MockLifecycle)lifecycleFactory.getLifecycle("DEFAULT"); | |
facesContextFactory = (MockFacesContextFactory)FactoryFinder.getFactory("javax.faces.context.FacesContextFactory"); | |
facesContext = (MockFacesContext)facesContextFactory.getFacesContext(servletContext, request, response, lifecycle); | |
externalContext = (MockExternalContext)facesContext.getExternalContext(); | |
UIViewRoot root = new UIViewRoot(); | |
root.setViewId("/viewId"); | |
root.setRenderKitId("HTML_BASIC"); | |
facesContext.setViewRoot(root); | |
ApplicationFactory applicationFactory = (ApplicationFactory)FactoryFinder.getFactory("javax.faces.application.ApplicationFactory"); | |
application = (MockApplication)applicationFactory.getApplication(); | |
facesContext.setApplication(application); | |
RenderKitFactory renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory("javax.faces.render.RenderKitFactory"); | |
//Wrap renderers with proper exval wrapper | |
renderKit = new DefaultRenderKitWrapperFactory().create(new MockRenderKit()); | |
renderKitFactory.addRenderKit("HTML_BASIC", renderKit); | |
// additional setup not provided automatically by the shale mock stuff | |
facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), new MyfacesConfig()); | |
writer = new MockResponseWriter(new StringWriter(), null, null); | |
facesContext.setResponseWriter(writer); | |
TestUtils.addDefaultRenderers(facesContext); | |
TestUtils.addDefaultValidators(facesContext); | |
expressionFactory = (MockExpressionFactory)application.getExpressionFactory(); | |
applyCustomConfigurations(); | |
// This triggers already the config object. So it is possible that you | |
// need to set your custom config also in the getCustomConfigObjects method. | |
final ELHelper defaultElHelper = ExtValUtils.getELHelper(); | |
ExtValContext.getContext().getFactoryFinder() | |
.getFactory(FactoryNames.EL_HELPER_FACTORY, AbstractELHelperFactory.class) | |
.setCustomELHelperFactory(new AbstractELHelperFactory() { | |
protected ELHelper createELHelper() | |
{ | |
return new MockELHelper(defaultElHelper); | |
} | |
}); | |
final ExtValCoreConfiguration customExtValCoreConfiguration = getCustomExtValCoreConfiguration(); | |
//execute startup listener | |
new ExtValStartupListener() { | |
private static final long serialVersionUID = -3861810605160281884L; | |
@Override | |
protected void initModuleConfig() | |
{ | |
if(customExtValCoreConfiguration != null) | |
{ | |
ExtValCoreConfiguration.use(customExtValCoreConfiguration, true); | |
} | |
else | |
{ | |
ExtValCoreConfiguration.use(new DefaultExtValCoreConfiguration(), true); | |
} | |
} | |
@Override | |
protected void init() | |
{ | |
initModuleConfig(); | |
super.init(); | |
} | |
}.init(); | |
invokeStartupListeners(); | |
} | |
protected ExtValCoreConfiguration getCustomExtValCoreConfiguration() | |
{ | |
//override it - if needed | |
return null; | |
} | |
protected void addInitializationParameters() | |
{ | |
//override it - if needed | |
} | |
protected void addInitParameter(String key, String value) | |
{ | |
servletContext.addInitParameter(key, value); | |
} | |
private void applyCustomConfigurations() | |
{ | |
ExtValModuleConfiguration[] customConfigs = getCustomConfigObjects(); | |
if (customConfigs != null) | |
{ | |
for (ExtValModuleConfiguration moduleConfiguration : customConfigs) | |
{ | |
ExtValContext.getContext().addModuleConfiguration(getAbstractModuleConfiguration(moduleConfiguration), | |
moduleConfiguration, false); | |
} | |
} | |
} | |
protected ExtValModuleConfiguration[] getCustomConfigObjects() | |
{ | |
return null; | |
} | |
@SuppressWarnings("unchecked") | |
private static Class<? extends ExtValModuleConfiguration> getAbstractModuleConfiguration( | |
Object moduleConfiguration) | |
{ | |
Class<? extends ExtValModuleConfiguration> result = (Class<? extends ExtValModuleConfiguration>) moduleConfiguration | |
.getClass(); | |
while (!Modifier.isAbstract(result.getModifiers()) | |
&& !Object.class.getName().equals(result.getName())) | |
{ | |
result = (Class<? extends ExtValModuleConfiguration>) result | |
.getSuperclass(); | |
} | |
return result; | |
} | |
protected abstract void invokeStartupListeners(); | |
/** | |
* Tear down the test environment. | |
*/ | |
protected void tearDown() throws Exception | |
{ | |
resetFactoryFinder(); | |
resetExtValContext(); | |
application = null; | |
config = null; | |
externalContext = null; | |
facesContext.release(); | |
facesContext = null; | |
lifecycle = null; | |
lifecycleFactory = null; | |
renderKit = null; | |
request = null; | |
response = null; | |
servletContext = null; | |
session = null; | |
FactoryFinder.releaseFactories(); | |
Thread.currentThread().setContextClassLoader(threadContextClassLoader); | |
expressionFactory = null; | |
threadContextClassLoader = null; | |
} | |
private void resetFactoryFinder() | |
{ | |
try | |
{ | |
Field factoryMap = DefaultFactoryFinder.class.getDeclaredField("factoryMap"); | |
factoryMap.setAccessible(true); | |
factoryMap.set(ExtValContext.getContext().getFactoryFinder(), new HashMap<FactoryNames, Object>()); | |
} | |
catch (Exception e) | |
{ | |
throw new IllegalStateException("cannot reset the factory finder", e); | |
} | |
} | |
protected void resetExtValContext() | |
{ | |
try | |
{ | |
Field context = ExtValContext.class.getDeclaredField("extValContext"); | |
context.setAccessible(true); | |
context.set(ExtValContext.getContext(), null); | |
} | |
catch (Exception e) | |
{ | |
throw new IllegalStateException("cannot reset the extval-context", e); | |
} | |
} | |
protected void checkMessageCount(int expected) | |
{ | |
int i = 0; | |
for(Iterator messages = facesContext.getMessages(); messages.hasNext();) | |
{ | |
messages.next(); | |
i++; | |
} | |
assertEquals("Complete message count", expected, i); | |
} | |
protected void checkMessageCount(String clientId, int expected) | |
{ | |
int i = 0; | |
for(Iterator messages = facesContext.getMessages(clientId); messages.hasNext();) | |
{ | |
messages.next(); | |
i++; | |
} | |
assertEquals("Complete message count", expected, i); | |
} | |
protected void checkMessageSeverities(FacesMessage.Severity... severities) | |
{ | |
int i = 0; | |
for(Iterator messages = facesContext.getMessages(); messages.hasNext();) | |
{ | |
assertEquals(severities[i], ((FacesMessage)messages.next()).getSeverity()); | |
i++; | |
} | |
} | |
protected void assertNavigationBlocked(boolean isBlocked) | |
{ | |
assertEquals(isBlocked, this.facesContext.getRenderResponse()); | |
} | |
/** | |
* Verify the following: | |
* <ul> | |
* <li>id is not null</li> | |
* <li>Response is complete</li> | |
* <li>Responce contains the id</li> | |
* </ul> | |
* | |
* @param id ID to verify | |
*/ | |
protected void assertIdExists(String id) | |
{ | |
assertNotNull("ID is not null", id); | |
assertTrue("Response Complete", facesContext.getResponseComplete()); | |
String output = writer.getWriter().toString(); | |
assertNotNull("Has output", output); | |
assertTrue("Contains id '" + id + "'", output.indexOf(id) != -1); | |
} | |
protected void createValueBinding(UIInput uiInput, String name, String expression) | |
{ | |
ValueBinding valueBinding = application.createValueBinding(expression); | |
ValueExpression valueExpression = expressionFactory.createValueExpression( | |
facesContext.getELContext(), expression, Object.class); | |
if(uiInput != null) | |
{ | |
uiInput.setValueBinding(name, valueBinding); | |
uiInput.setValueExpression(name, valueExpression); | |
} | |
} | |
protected void createRequestScopedBean(String name, Object instance) | |
{ | |
createValueBinding(null, "value", "#{" + name + "}"); | |
facesContext.getExternalContext().getRequestMap().put(name, instance); | |
} | |
@SuppressWarnings({"UnusedDeclaration", "unchecked"}) | |
protected <T> T resolveBean(String name, Class<T> targetClass) | |
{ | |
return (T) ExtValUtils.getELHelper().getBean(name); | |
} | |
} | |