Author: alexsmirnov
Date: 2008-11-20 15:25:42 -0500 (Thu, 20 Nov 2008)
New Revision: 11282
Added:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html
branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html
Removed:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html
branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/AbstractFacesTest.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebClient.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebConnection.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/TestException.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/EventInvoker.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationErrorEvent.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationEvent.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StaticServlet.java
Log:
Merge test project changes from the trunk.
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/AbstractFacesTest.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/AbstractFacesTest.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/AbstractFacesTest.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -22,37 +22,64 @@
import javax.faces.webapp.FacesServlet;
import javax.servlet.Filter;
+import junit.framework.TestCase;
+
import org.junit.After;
import org.junit.Before;
import org.richfaces.test.staging.FilterContainer;
-import org.richfaces.test.staging.RequestChain;
import org.richfaces.test.staging.ServletContainer;
import org.richfaces.test.staging.StagingConnection;
import org.richfaces.test.staging.StagingServer;
/**
+ * Base class for all JSF test cases.
* @author asmirnov
*
*/
-public abstract class AbstractFacesTest {
+public abstract class AbstractFacesTest extends TestCase {
private ClassLoader contextClassLoader;
+ /**
+ * Prepared test server instance. Populated by the default {@link #setUp()} method.
+ */
protected StagingServer facesServer;
+ /**
+ * Current virtual connection. This field populated by the {@link #setupWebContent()}
method only.
+ */
protected StagingConnection connection;
+ /**
+ * Current {@link FacesContext} instance. This field populated by the {@link
#setupWebContent()} method only.
+ */
protected FacesContext facesContext;
+ /**
+ * JSF {@link Lifecycle} instance. Populated by the default {@link #setUp()} method.
+ */
protected Lifecycle lifecycle;
+ /**
+ * JSF {@link Application} instance. Populated by the default {@link #setUp()} method.
+ */
protected Application application;
/**
+ * Setup staging server instance with JSF implementation. First, this method creates a
local test instance
+ * and calls the other template method in the next sequence:
+ * <ol>
+ * <li>{@link #setupFacesServlet()}</li>
+ * <li>{@link #setupFacesListener()}</li>
+ * <li>{@link #setupJsfInitParameters()}</li>
+ * <li>{@link #setupWebContent()}</li>
+ * </ol>
+ * After them, test server is initialized as well as fields {@link #lifecycle} and
{@link #application} populated.
+ * Also, if the resource "logging.properties" is exist in the test class
package, The Java {@link LogManager} will be configured with its content.
* @throws java.lang.Exception
*/
@Before
- public void setUpServer() throws Exception {
+ public void setUp() throws Exception {
contextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
this.getClass().getClassLoader());
@@ -74,6 +101,7 @@
facesServer = new StagingServer();
setupFacesServlet();
setupFacesListener();
+ setupJsfInitParameters();
setupWebContent();
facesServer.init();
ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
@@ -86,18 +114,22 @@
}
/**
- *
+ * This hook method called from the {@link #setUp()} should append JSF implementation
+ * listener to the test server. Default version applends
"com.sun.faces.config.ConfigureListener"
+ * or "org.apache.myfaces.webapp.StartupServletContextListener" for the
existed SUN RI or MyFaces implementation.
+ * This metod also calls appropriate {@link #setupSunFaces()} or {@link #setupMyFaces()}
methods.
*/
protected void setupFacesListener() {
EventListener listener = null;
try {
+ // Check Sun RI configuration listener class.
Class<? extends EventListener> listenerClass = contextClassLoader
.loadClass("com.sun.faces.config.ConfigureListener")
.asSubclass(EventListener.class);
listener = listenerClass.newInstance();
setupSunFaces();
} catch (ClassNotFoundException e) {
- // No JSF RI listener
+ // No JSF RI listener, check MyFaces.
Class<? extends EventListener> listenerClass;
try {
listenerClass = contextClassLoader
@@ -119,8 +151,10 @@
}
/**
- * @throws InstantiationException
- * @throws IllegalAccessException
+ * This template method called from {@link #setUp()} to create {@link FacesServlet}
instance.
+ * The default implementation also tests presense of the "org.ajax4jsf.Filter"
class.
+ * If this class is avalable, these instance appended to the Faces Servlet call chain.
+ * Default mapping to the FacesServlet instance is "*.jsf"
*/
protected void setupFacesServlet() {
ServletContainer facesServletContainer = new ServletContainer("*.jsf",
@@ -145,6 +179,13 @@
} catch (Exception e) {
throw new TestException(e);
}
+ }
+
+ /**
+ * This template method called from {@link #setUp()} to append appropriate init
parameters to the test server.
+ * The default implementation sets state saving method to the "server" and
default jsf page suffix to the ".xhtml"
+ */
+ protected void setupJsfInitParameters() {
facesServer.addInitParameter(
StateManager.STATE_SAVING_METHOD_PARAM_NAME,
StateManager.STATE_SAVING_METHOD_SERVER);
@@ -152,23 +193,45 @@
".xhtml");
}
+ /**
+ * This template method called from the {@link #setupFacesListener()} if MyFaces
implementation presents.
+ * The default implementation does nothing.
+ */
protected void setupMyFaces() {
// Do nothing by default.
}
+ /**
+ * This template method called from the {@link #setupFacesListener()} if Sun JSF
reference implementation presents.
+ * The default implementation sets the "com.sun.faces.validateXml"
"com.sun.faces.verifyObjects" init parameters to the "true"
+ */
protected void setupSunFaces() {
facesServer.addInitParameter("com.sun.faces.validateXml", "true");
facesServer.addInitParameter("com.sun.faces.verifyObjects",
"true");
}
+ /**
+ * This template method called from the {@link #setUp()} to populate virtual server
content.
+ * The default implementation do nothing.
+ */
protected void setupWebContent() {
}
+ /**
+ * Setup virtual server connection to run tests inside JSF lifecycle.
+ * The default implementation setups virtual request to the
"http://localhost/test.jsf" URL and creates {@link FacesContext} instance.
+ * Two template methods are called :
+ * <ol>
+ * <li>{@link #setupConnection()} to prepare request method, parameters, headers
and so</li>
+ * <li>{@link #setupView()} to create default view.</li>
+ * </ol>
+ * @throws Exception
+ */
protected void setupFacesRequest() throws Exception {
connection = facesServer.getConnection(new URL(
"http://localhost/test.jsf"));
- setupConnection(connection);
+ setupConnection();
connection.start();
FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
@@ -181,21 +244,31 @@
}
}
+ /**
+ * This template method called from the {@link #setupFacesRequest()} to create
components view tree in the virtual request.
+ * The default implementation is only creates {@link UIViewRoot} instance for view ID
"/test.xhtml".
+ * @return
+ */
protected UIViewRoot setupView() {
UIViewRoot viewRoot = (UIViewRoot)
application.createComponent(UIViewRoot.COMPONENT_TYPE);
viewRoot.setViewId("/test.xhtml");
return viewRoot;
}
- protected void setupConnection(StagingConnection connection) {
+ /**
+ * This template method called from the {@link #setupFacesRequest()} to setup additional
virtual connection parameters.
+ * The default implementation does nothing.
+ */
+ protected void setupConnection() {
}
/**
+ * Virtual server instance cleanup.
* @throws java.lang.Exception
*/
@After
- public void tearDownServer() throws Exception {
+ public void tearDown() throws Exception {
if (null != facesContext) {
facesContext.release();
facesContext = null;
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebClient.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebClient.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebClient.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -11,6 +11,10 @@
import com.gargoylesoftware.htmlunit.WebConnection;
/**
+ * Modified version of the HtmlUnit {@link WebClient}. This subclass uses {@link
LocalWebConnection} by default,
+ * to perform requests to the local saging server {@link StagingServer} instead of real
network request.
+ * It is also setup synchonous ajax controller {@link
WebClient#setAjaxController(com.gargoylesoftware.htmlunit.AjaxController)},
+ * to avoid thread syncronisation problem.
* @author asmirnov
*
*/
@@ -22,7 +26,8 @@
private transient WebConnection webConnection;
/**
- *
+ * Create WebConnection instance for the given {@link StagingServer}
+ * @param server test server instance.
*/
public LocalWebClient(StagingServer server) {
super();
@@ -31,6 +36,8 @@
}
/**
+ * Create WebConnection instance for the given {@link StagingServer} and browser
version.
+ * @param server test server instance.
* @param browserVersion
*/
public LocalWebClient(StagingServer server,BrowserVersion browserVersion) {
@@ -40,8 +47,10 @@
}
/**
+ * Overwride default webConnection.
* @return the webConnection
*/
+ @Override
public WebConnection getWebConnection() {
if (this.webConnection == null) {
this.webConnection = new LocalWebConnection(server);
@@ -53,6 +62,7 @@
/**
* @param webConnection the webConnection to set
*/
+ @Override
public void setWebConnection(WebConnection webConnection) {
this.webConnection = webConnection;
}
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebConnection.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebConnection.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebConnection.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -17,7 +17,16 @@
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebResponse;
+/**
+ * This implementation of the HtmlUnit {@link WebConnection} execute http requests on the
local
+ * staging server instead of the real network connection.
+ * @author asmirnov
+ *
+ */
public final class LocalWebConnection implements WebConnection {
+ /**
+ * test server instance
+ */
private final StagingServer localServer;
/**
@@ -27,9 +36,13 @@
this.localServer = localServer;
}
+ /* (non-Javadoc)
+ * @see
com.gargoylesoftware.htmlunit.WebConnection#getResponse(com.gargoylesoftware.htmlunit.WebRequestSettings)
+ */
public WebResponse getResponse(WebRequestSettings settings)
throws IOException {
StagingConnection connection = localServer.getConnection(settings.getUrl());
+ // Propagate web request settings to the local connection.
for (NameValuePair param : settings.getRequestParameters()) {
connection.addRequestParameter(param.getName(), param.getValue());
}
@@ -41,6 +54,8 @@
connection.setRequestBody(body);
connection.setRequestContentType(contentType);
connection.addRequestHeaders(settings.getAdditionalHeaders());
+ // HtmlUnit uses request parameters map for the form submit, but does not parse
+ // XMLHttpRequest content.
if(null != body &&
FormEncodingType.URL_ENCODED.getName().equals(contentType)){
connection.parseFormParameters(body);
}
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -6,10 +6,8 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
@@ -19,71 +17,169 @@
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebResponse;
-public final class LocalWebResponse implements WebResponse {
- private final WebRequestSettings settings;
+/**
+ * This implementation realise WebResponse wrapper for a staging server
+ * connection. This class is used by the {@link LocalWebClient}, but also can be used to
analise response rendering:
+ * <pre>
+ * ............
+ * @Test
+ * public void testRender() {
+ * setupFacesRequest();
+ * // Prepare view etc
+ * ..................
+ * lifecycle.render(facesContext);
+ * WebClient webClient = new LocalWebClient(facesServer);
+ * HtmlPage page = (HtmlPage) webClient.loadWebResponseInto(new
LocalWebResponse(connection), webClient.getCurrentWindow());
+ * // analyse response
+ * assertTrue(....)
+ * }
+ * </pre>
+ *
+ * @author asmirnov
+ *
+ */
+public class LocalWebResponse implements WebResponse {
+ private WebRequestSettings settings;
private final StagingConnection serverConnection;
- public LocalWebResponse(WebRequestSettings settings,StagingConnection serverConnection)
{
- this.settings = settings;
+ public LocalWebResponse(StagingConnection serverConnection) {
this.serverConnection = serverConnection;
}
+ public LocalWebResponse(WebRequestSettings settings,
+ StagingConnection connection) {
+ this(connection);
+ this.settings = settings;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getContentAsStream()
+ */
public InputStream getContentAsStream() throws IOException {
return new ByteArrayInputStream(getResponseBody());
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getContentAsString()
+ */
public String getContentAsString() {
return serverConnection.getContentAsString();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getContentCharSet()
+ */
public String getContentCharSet() {
- return serverConnection.getCharacterEncoding();
+ return serverConnection.getResponseCharacterEncoding();
}
public String getContentType() {
- return serverConnection.getContentType();
+ return serverConnection.getResponseContentType();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.gargoylesoftware.htmlunit.WebResponse#getLoadTimeInMilliSeconds()
+ */
public long getLoadTimeInMilliSeconds() {
return 0;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getRequestMethod()
+ */
public com.gargoylesoftware.htmlunit.HttpMethod getRequestMethod() {
- return
com.gargoylesoftware.htmlunit.HttpMethod.valueOf(serverConnection.getMethod().toString());
+ return com.gargoylesoftware.htmlunit.HttpMethod
+ .valueOf(serverConnection.getRequestMethod().toString());
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getRequestSettings()
+ */
public WebRequestSettings getRequestSettings() {
+ if (settings == null) {
+ settings = new WebRequestSettings(this.getUrl(), getRequestMethod());
+ }
return settings;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getResponseBody()
+ */
public byte[] getResponseBody() {
return serverConnection.getResponseBody();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.gargoylesoftware.htmlunit.WebResponse#getResponseHeaderValue(java
+ * .lang.String)
+ */
public String getResponseHeaderValue(String headerName) {
- // TODO Auto-generated method stub
+ String[] values = serverConnection.getResponseHeaders().get(headerName);
+ if(null != values && values.length >0){
+ return values[0];
+ }
return null;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getStatusCode()
+ */
public int getStatusCode() {
- return serverConnection.getStatus();
+ return serverConnection.getResponseStatus();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getStatusMessage()
+ */
public String getStatusMessage() {
return serverConnection.getErrorMessage();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getUrl()
+ */
public URL getUrl() {
return serverConnection.getUrl();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.gargoylesoftware.htmlunit.WebResponse#getResponseHeaders()
+ */
public List<NameValuePair> getResponseHeaders() {
ArrayList<NameValuePair> headers = new ArrayList<NameValuePair>(10);
- for (Entry<String, String[]> entry :
serverConnection.getResponseHeaders().entrySet()) {
+ for (Entry<String, String[]> entry : serverConnection
+ .getResponseHeaders().entrySet()) {
for (String value : entry.getValue()) {
- headers.add(new NameValuePair(entry.getKey(),value));
+ headers.add(new NameValuePair(entry.getKey(), value));
}
- };
+ }
+ ;
return headers;
}
}
\ No newline at end of file
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/TestException.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/TestException.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/TestException.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -3,17 +3,21 @@
*/
package org.richfaces.test;
+import org.richfaces.test.staging.StagingServer;
+
/**
+ * Internal runtame exception for the {@link StagingServer} engine.
* @author asmirnov
*
*/
+@SuppressWarnings("serial")
public class TestException extends RuntimeException {
/**
- *
+ * Default constructor.
*/
public TestException() {
- // TODO Auto-generated constructor stub
+ super();
}
/**
@@ -21,7 +25,6 @@
*/
public TestException(String message) {
super(message);
- // TODO Auto-generated constructor stub
}
/**
@@ -29,7 +32,6 @@
*/
public TestException(Throwable cause) {
super(cause);
- // TODO Auto-generated constructor stub
}
/**
@@ -38,7 +40,6 @@
*/
public TestException(String message, Throwable cause) {
super(message, cause);
- // TODO Auto-generated constructor stub
}
}
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/EventInvoker.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/EventInvoker.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/EventInvoker.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -5,6 +5,13 @@
import java.util.EventListener;
+/**
+ * Internal interface, used to invoke listeners of different types.
+
+ * @author asmirnov
+ *
+ * @param <T> listener type.
+ */
interface EventInvoker<T extends EventListener> {
public void invoke(T listener);
}
\ No newline at end of file
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationErrorEvent.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationErrorEvent.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationErrorEvent.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -3,6 +3,18 @@
import java.lang.reflect.Method;
import java.util.EventObject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * This event sent from the virtual server introspection method to the registered
+ * {@link InvocationListener} instance after any exception thrown from calls to {@link
HttpServletRequest} , {@link HttpServletResponse}, {@link HttpSession} and {@link
ServletContext} objects.
+
+ * @author asmirnov
+ *
+ */
+@SuppressWarnings("serial")
public class InvocationErrorEvent extends EventObject {
private Object target;
private Method method;
@@ -30,6 +42,9 @@
return args;
}
+ /**
+ * @return thrown exception.
+ */
public Throwable getE() {
return e;
}
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationEvent.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationEvent.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/InvocationEvent.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -3,6 +3,17 @@
import java.lang.reflect.Method;
import java.util.EventObject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * This event sent from the staging server introspection method to the registered
+ * {@link InvocationListener} instance after all calls to {@link HttpServletRequest} ,
{@link HttpServletResponse}, {@link HttpSession} and {@link ServletContext} objects.
+ * @author asmirnov
+ *
+ */
+@SuppressWarnings("serial")
public class InvocationEvent extends EventObject {
private Object target;
private Method method;
@@ -18,18 +29,30 @@
this.result = result;
}
+ /**
+ * @return target object instance.
+ */
public Object getTarget() {
return target;
}
+ /**
+ * @return {@link Method} that was called.
+ */
public Method getMethod() {
return method;
}
+ /**
+ * @return method arguments.
+ */
public Object[] getArgs() {
return args;
}
+ /**
+ * @return value returned from the invoked method.
+ */
public Object getResult() {
return result;
}
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -29,8 +29,9 @@
import org.richfaces.test.TestException;
/**
- * This class represent single connection to the server.
- *
+ * This class represent single connection ( request ) to the virtual server. These
instance should not be created directly, but by the {@link
StagingServer#getConnection(URL)}.
+ * method only.
+ * Since instance have been created, additional request parameters and headers can be
set.
* @author asmirnov
*
*/
@@ -70,9 +71,15 @@
private HttpServletResponse responseProxy;
- public StagingConnection(StagingServer localServer, URL url) {
+ /**
+ * Create connection instance.
+ * @param localServer virtual server instance.
+ * @param url request URL.
+ */
+ StagingConnection(StagingServer localServer, URL url) {
this.server = localServer;
this.url = url;
+ // TODO - context path support.
String path = url.getPath();
servlet = localServer.getServlet(path);
if (null == servlet) {
@@ -100,6 +107,11 @@
responseProxy = (HttpServletResponse) Proxy.newProxyInstance(loader, new
Class[]{HttpServletResponse.class}, server.getInvocationHandler(response));
}
+ /**
+ * Parse 'application/x-www-form-urlencoded' string with parameters name/value
pairs,
+ * as it expected after a form submit.
+ * @param queryString URL query string or POST content.
+ */
public void parseFormParameters(String queryString) {
String[] queryParams = queryString.split("&");
for (int i = 0; i < queryParams.length; i++) {
@@ -140,19 +152,24 @@
private void checkStarted() {
if (!isFinished()) {
- throw new IllegalStateException("request have not been started");
+ throw new TestException("request have not been started");
}
}
private void checkNotStarted() {
if (isStarted()) {
- throw new IllegalStateException("request was started, no parameters changes
allowed");
+ throw new TestException("request was started, no parameters changes
allowed");
}
}
+ /**
+ * Execute this connection request on the associated servlet or filter chain.
+ * @throws ServletException
+ * @throws IOException
+ */
public void execute() throws ServletException, IOException {
if (isStarted() || isFinished()) {
- throw new IllegalStateException(
+ throw new TestException(
"request have already been executed");
}
start();
@@ -160,13 +177,20 @@
finish();
}
+ /**
+ * Finish request to the this connection, inform server listeners about request status.
+ */
public void finish() {
server.requestFinished(request);
finished = true;
}
+ /**
+ * Start request to the this connection, inform server listeners about request status.
+ * No request parameters changes allowed after connection start.
+ */
public void start() {
- log.fine("start " + getMethod() + " request processing for file "
+ log.fine("start " + getRequestMethod() + " request processing for file
"
+ url.getFile());
log.fine("request parameters: " + requestParameters);
server.requestStarted(request);
@@ -174,15 +198,19 @@
}
/**
+ * Get request HTTP methos ( GET, POST etc ).
* @return the method
*/
- public HttpMethod getMethod() {
+ public HttpMethod getRequestMethod() {
return method;
}
/**
+ * Set request HTTP methos ( GET, POST etc ).
* @param method
* the method to set
+ * @throws TestException
+ * if connection have already been started.
*/
public void setRequestMethod(HttpMethod method) {
checkNotStarted();
@@ -190,12 +218,20 @@
}
/**
+ * Get request url.
* @return the url
*/
public URL getUrl() {
return url;
}
+ /**
+ * Append additional request parameter.
+ * @param name
+ * @param value
+ * @throws TestException
+ * if connection have already been started.
+ */
public void addRequestParameter(String name, String value) {
checkNotStarted();
String[] values = requestParameters.get(name);
@@ -211,7 +247,10 @@
}
/**
- * @return
+ * Get content of the response as String.
+ * @return content of the response writer or String created from the ServletOutputStream
with current response encoding.
+ * @throws TestException
+ * if connection have not been started or response has an unsupported
encoding.
*/
public String getContentAsString() {
checkStarted();
@@ -234,6 +273,12 @@
return content;
}
+ /**
+ * Get content of the response as byte array.
+ * @return content of the ServletOutputStream or convert String, collected by response
writer, with current response encoding.
+ * @throws TestException
+ * if connection have not been started or response has unsupported encoding.
+ */
public byte[] getResponseBody() {
checkStarted();
byte[] content = response.getStreamContent();
@@ -254,6 +299,7 @@
}
/**
+ * List of the {@link Cookie} used by the request or response ( There are same cookies
for both request and response ).
* @return the cookies
*/
public List<Cookie> getCookies() {
@@ -261,6 +307,7 @@
}
/**
+ * request object for the this connection.
* @return the request
*/
public HttpServletRequest getRequest() {
@@ -268,18 +315,127 @@
}
/**
+ * response object for the this connection.
* @return the response
*/
public HttpServletResponse getResponse() {
return responseProxy;
}
+ /**
+ * @return encoding used to write response.
+ * @throws TestException
+ * if connection have not been started .
+ */
+ public String getResponseCharacterEncoding() {
+ checkStarted();
+ return response.getCharacterEncoding();
+ }
+
+ /**
+ * @return content type ( eg 'text/html' ) of the response.
+ * @throws TestException
+ * if connection have not been started .
+ */
+ public String getResponseContentType() {
+ checkStarted();
+ return response.getContentType();
+ }
+
+ /**
+ * @return HTTP status code of the response.
+ * @throws TestException
+ * if connection have not been started .
+ */
+ public int getResponseStatus() {
+ checkStarted();
+ return response.getStatus();
+ }
+
+ /**
+ * @return HTTP error message.
+ * @throws TestException
+ * if connection have not been started .
+ */
+ public String getErrorMessage() {
+ checkStarted();
+ return response.getErrorMessage();
+ }
+
+ /**
+ * Set request Query string. This method does not parse query string, {@link
#parseFormParameters(String)} should be used.
+ * @param queryString
+ * the queryString to set
+ * @throws TestException
+ * if connection have already been started .
+ */
+ public void setQueryString(String queryString) {
+ checkNotStarted();
+ this.queryString = queryString;
+ }
+
+ /**
+ * @return the queryString
+ */
+ public String getQueryString() {
+ return queryString;
+ }
+
+ /**
+ * Get HTTP response headers.
+ * @return headers name-values map.
+ * @throws TestException
+ * if connection have not been started .
+ */
+ public Map<String, String[]> getResponseHeaders() {
+ checkStarted();
+ return response.getHeaders();
+ }
+
+ /**
+ * Set charset for the request body.
+ * @param charset
+ * @throws UnsupportedEncodingException
+ */
+ public void setRequestCharacterEncoding(String charset) throws
UnsupportedEncodingException {
+ checkNotStarted();
+ request.setCharacterEncoding(charset);
+ }
+
+ /**
+ * Set HTTP POST/PUT methods uploading content.
+ * @param body
+ */
+ public void setRequestBody(String body) {
+ checkNotStarted();
+ request.setRequestBody(body);
+ }
+
+ /**
+ * Set HTTP request content type ( eg 'application/x-www-form-urlencoded' or
'text/xml' ).
+ * @param contentType
+ */
+ public void setRequestContentType(String contentType) {
+ checkNotStarted();
+ request.setContentType(contentType);
+
+ }
+
+ /**
+ * Append additional HTTP request headers.
+ * @param headers
+ */
+ public void addRequestHeaders(Map<String, String> headers) {
+ checkNotStarted();
+ request.addHeaders(headers);
+ }
+
private class ConnectionRequest extends StagingHttpRequest {
-
+
public Cookie[] getCookies() {
return cookies.toArray(COOKIE);
}
-
+
/*
* (non-Javadoc)
*
@@ -288,7 +444,7 @@
public String getMethod() {
return method.toString();
}
-
+
/*
* (non-Javadoc)
*
@@ -297,7 +453,7 @@
public String getServletPath() {
return servletPath;
}
-
+
/*
* (non-Javadoc)
*
@@ -306,7 +462,7 @@
public String getPathInfo() {
return pathInfo;
}
-
+
/*
* (non-Javadoc)
*
@@ -315,7 +471,7 @@
public String getQueryString() {
return queryString;
}
-
+
/*
* (non-Javadoc)
*
@@ -324,7 +480,24 @@
public String getRequestURI() {
return url.getPath();
}
-
+
+ /* (non-Javadoc)
+ * @see org.richfaces.test.staging.StagingHttpRequest#getServerName()
+ */
+ @Override
+ public String getServerName() {
+ return url.getHost();
+ }
+
+
+ @Override
+ public int getLocalPort() {
+ int port = url.getPort();
+ if(port < 0){
+ port = super.getLocalPort();
+ }
+ return port;
+ }
/*
* (non-Javadoc)
*
@@ -337,7 +510,7 @@
}
return null;
}
-
+
/*
* (non-Javadoc)
*
@@ -347,7 +520,7 @@
public Map getParameterMap() {
return Collections.unmodifiableMap(requestParameters);
}
-
+
/*
* (non-Javadoc)
*
@@ -357,7 +530,7 @@
public Enumeration getParameterNames() {
return Collections.enumeration(requestParameters.keySet());
}
-
+
/*
* (non-Javadoc)
*
@@ -367,7 +540,7 @@
public String[] getParameterValues(String name) {
return requestParameters.get(name);
}
-
+
/*
* (non-Javadoc)
*
@@ -376,7 +549,7 @@
public HttpSession getSession() {
return server.getSession();
}
-
+
/*
* (non-Javadoc)
*
@@ -385,7 +558,7 @@
public HttpSession getSession(boolean create) {
return server.getSession(create);
}
-
+
@Override
public RequestDispatcher getRequestDispatcher(String path) {
RequestDispatcher dispatcher = null;
@@ -400,43 +573,43 @@
final RequestChain dispatchedServlet = server.getServlet(path);
if (null != dispatchedServlet) {
dispatcher = new RequestDispatcher() {
-
+
public void forward(ServletRequest request,
ServletResponse response) throws ServletException,
IOException {
response.reset();
dispatchedServlet.execute(request, response);
}
-
+
public void include(ServletRequest request,
ServletResponse response) throws ServletException,
IOException {
dispatchedServlet.execute(request, response);
}
-
+
};
}
return dispatcher;
}
-
+
@Override
protected void attributeAdded(String name, Object o) {
server.requestAttributeAdded(this, name, o);
-
+
}
-
+
@Override
protected void attributeRemoved(String name, Object removed) {
server.requestAttributeRemoved(this, name, removed);
-
+
}
-
+
@Override
protected void attributeReplaced(String name, Object o) {
server.requestAttributeReplaced(this, name, o);
-
+
}
-
+
}
private class ConnectionResponse extends StagingHttpResponse {
@@ -449,73 +622,9 @@
*/
public void addCookie(Cookie cookie) {
cookies.add(cookie);
-
+
}
-
+
}
- public String getCharacterEncoding() {
- checkStarted();
- return response.getCharacterEncoding();
- }
-
- public String getContentType() {
- checkStarted();
- return response.getContentType();
- }
-
- public int getStatus() {
- checkStarted();
- return response.getStatus();
- }
-
- public String getErrorMessage() {
- checkStarted();
- return response.getErrorMessage();
- }
-
- /**
- * @param queryString
- * the queryString to set
- */
- public void setQueryString(String queryString) {
- checkNotStarted();
- this.queryString = queryString;
- }
-
- /**
- * @return the queryString
- */
- public String getQueryString() {
- return queryString;
- }
-
- /**
- * @return
- */
- public Map<String, String[]> getResponseHeaders() {
- checkStarted();
- return response.getHeaders();
- }
-
- public void setRequestCharacterEncoding(String charset) throws
UnsupportedEncodingException {
- checkNotStarted();
- request.setCharacterEncoding(charset);
- }
-
- public void setRequestBody(String body) {
- checkNotStarted();
- request.setRequestBody(body);
- }
-
- public void setRequestContentType(String contentType) {
- checkNotStarted();
- request.setContentType(contentType);
-
- }
-
- public void addRequestHeaders(Map<String, String> headers) {
- request.addHeaders(headers);
- }
-
}
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -15,6 +15,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -31,6 +32,8 @@
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
@@ -41,9 +44,17 @@
import org.richfaces.test.TestException;
/**
- * This class implements limited Http servlet container 2.5 functionality. It
- * supports only calls only, java code configuration, just one web application
- * etc...
+ * This class implements limited Http servlet container 2.5 functionality. It is designed
for a test purposes only ,so that has a limitations:
+ * <ul>
+ * <li>supports local calls only.</li>
+ * <li>java code only configuration ( no xml files processed ).</li>
+ * <li>just one web application, 'deployed' in the root
context.</li>
+ * <li>only one client session</li>
+ * <li>communicates by the local java calls only, no network connection</li>
+ * <li>no JSP compilator support ( but it is possible to register pre-compiled
pages as servlets)</li>
+ * <li>...</li>
+ * </ul>
+ * It is main part of the test framework.
*
*/
public class StagingServer {
@@ -58,6 +69,8 @@
private static final Class<HttpSessionAttributeListener>
SESSION_ATTRIBUTE_LISTENER_CLASS = HttpSessionAttributeListener.class;
+ private static final Logger log = ServerLogger.SERVER.getLogger();
+
private List<RequestChain> servlets = new ArrayList<RequestChain>();
private RequestChain defaultServlet;
@@ -70,20 +83,21 @@
private final Map<String, String> mimeTypes = new HashMap<String,
String>();
-
private InvocationListener invocationListener;
-
private StagingServletContext context;
-
+
private ServletContext contextProxy;
-
private ServerHttpSession session;
private HttpSession sessionProxy;
-
+ /**
+ * This inner class links ServletContext calls to the server instance.
+ * @author asmirnov
+ *
+ */
private class LocalContext extends StagingServletContext {
/*
@@ -100,6 +114,9 @@
return mimeTypes.get(file);
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingServletContext#valueBound(javax.servlet.ServletContextAttributeEvent)
+ */
@Override
protected void valueBound(ServletContextAttributeEvent event) {
// inform listeners.
@@ -111,6 +128,9 @@
}
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingServletContext#valueReplaced(javax.servlet.ServletContextAttributeEvent)
+ */
@Override
protected void valueReplaced(ServletContextAttributeEvent event) {
// inform listeners.
@@ -122,6 +142,9 @@
}
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingServletContext#valueUnbound(javax.servlet.ServletContextAttributeEvent)
+ */
@Override
protected void valueUnbound(ServletContextAttributeEvent event) {
// inform listeners.
@@ -133,24 +156,33 @@
}
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingServletContext#getServerResource(java.lang.String)
+ */
@Override
- /*
- * @param path
- *
- * @return
- */
protected ServerResource getServerResource(String path) {
return serverRoot.getResource(new ServerResourcePath(path));
}
}
+ /**
+ * This inner class links session object calls to the server instance.
+ * @author asmirnov
+ *
+ */
private class ServerHttpSession extends StagingHttpSession {
+ /* (non-Javadoc)
+ * @see javax.servlet.http.HttpSession#getServletContext()
+ */
public ServletContext getServletContext() {
return context;
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingHttpSession#valueBound(javax.servlet.http.HttpSessionBindingEvent)
+ */
@Override
protected void valueBound(
final HttpSessionBindingEvent sessionBindingEvent) {
@@ -163,6 +195,9 @@
});
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingHttpSession#valueUnbound(javax.servlet.http.HttpSessionBindingEvent)
+ */
@Override
protected void valueUnbound(
final HttpSessionBindingEvent sessionBindingEvent) {
@@ -175,6 +210,9 @@
});
}
+ /* (non-Javadoc)
+ * @see
org.richfaces.test.staging.StagingHttpSession#valueReplaced(javax.servlet.http.HttpSessionBindingEvent)
+ */
@Override
protected void valueReplaced(
final HttpSessionBindingEvent sessionBindingEvent) {
@@ -203,7 +241,7 @@
/**
* Append executable server object ( {@link Filter} or {@link Servlet}
- * container.
+ * to the server.
*
* @param servlet
*/
@@ -228,7 +266,8 @@
*
* @param path
* request path relative to web application context.
- * @return
+ * @return Appropriate Filter or Servlet executable object to serve given request. If no
servlet was registered for the given path,
+ * try to send requested object directly.
*/
public RequestChain getServlet(String path) {
RequestChain result = null;
@@ -239,9 +278,11 @@
}
}
if (null == result) {
+ // Is requested object exist in the virtual content ?
try {
URL resource = context.getResource(path);
if (null != resource) {
+ // Serve it directly.
result = defaultServlet;
}
} catch (MalformedURLException e) {
@@ -251,29 +292,55 @@
return result;
}
+ /**
+ * Add web application init parameter.
+ * @param name
+ * @param value
+ */
public void addInitParameter(String name, String value) {
initParameters.put(name, value);
}
- void addMimeType(String extension, String mimeType) {
+ /**
+ * Add default mime type for serve files with given extension.
+ * @param extension
+ * @param mimeType
+ */
+ public void addMimeType(String extension, String mimeType) {
mimeTypes.put(extension, mimeType);
}
+ /**
+ * Add java resource to the virtual web application content. This method makes all
parent directories as needed.
+ * @param path path to the file in the virtual web server.
+ * @param resource path to the resource in the classpath, as required by the {@link
ClassLoader#getResource(String)}.
+ */
public void addResource(String path, String resource) {
ServerResourcePath resourcePath = new ServerResourcePath(path);
serverRoot.addResource(resourcePath, new ClasspathServerResource(
resource));
}
+ /**
+ * Add resource to the virtual veb application content. This method makes all parent
directories as needed.
+ * @param path path to the file in the virtual web server.
+ * @param resource {@code URL} to the file content.
+ */
public void addResource(String path, URL resource) {
serverRoot.addResource(new ServerResourcePath(path),
new UrlServerResource(resource));
}
+ /**
+ * Add all resources from the directory to the virtual web application content.
+ * @param path name of the target directory in the virtual web application. If no such
directory exists, it will be created, as well as all parent directories as needed.
+ * @param resource {@code URL} to the source directory or any file in the source
directory. Only 'file' or 'jar' protocols are supported. If this parameter
points to a file, it will be converted to a enclosing directory.
+ */
public void addResourcesFromDirectory(String path, URL resource) {
ServerResourcePath resourcePath = new ServerResourcePath(path);
ServerResource baseDirectory = serverRoot.getResource(resourcePath);
if (null == baseDirectory) {
+ // Create target directory.
baseDirectory = new ServerResourcesDirectory();
serverRoot.addResource(resourcePath, baseDirectory);
}
@@ -287,6 +354,11 @@
}
}
+ /**
+ * Internal method used by the {@link #addResourcesFromDirectory(String, URL)} to
process 'file' protocol.
+ * @param resource source directory.
+ * @param baseDirectory target virtual directory.
+ */
protected void addResourcesFromFile(URL resource,
ServerResource baseDirectory) {
File file = new File(resource.getPath());
@@ -300,6 +372,11 @@
}
}
+ /**
+ * Internal method used by the {@link #addResourcesFromDirectory(String, URL)} to
process 'jar' protocol.
+ * @param resource URL to the any object in the source directory.
+ * @param baseDirectory target virtual directory.
+ */
protected void addResourcesFromJar(URL resource,
ServerResource baseDirectory) {
try {
@@ -330,6 +407,7 @@
}
/**
+ * Internal reccursive method process directory content and all subdirectories.
* @param baseDirectory
* @param file
* @throws MalformedURLException
@@ -353,11 +431,26 @@
}
}
+ /**
+ * Add web-application wide listenes, same as it is defined by the
+ * <listener> element in the web.xml file for a real server.
+ * Supported listener types:
+ * <ul>
+ * <li>{@link ServletContextListener}</li>
+ * <li>{@link ServletContextAttributeListener}</li>
+ * <li>{@link HttpSessionListener}</li>
+ * <li>{@link HttpSessionAttributeListener}</li>
+ * <li>{@link ServletRequestListener}</li>
+ * <li>{@link ServletRequestAttributeListener}</li>
+ * </ul>
+ * @param listener web listener instance.
+ */
public void addWebListener(EventListener listener) {
contextListeners.add(listener);
}
/**
+ * Getter method for 'interceptor' events listener.
* @return the invocationListener
*/
public InvocationListener getInvocationListener() {
@@ -365,52 +458,90 @@
}
/**
- * @param invocationListener the invocationListener to set
+ * Set listener which gets events on all calls to any methods of the {@link
ServletContext}, {@link HttpSession}, {@link HttpServletRequest}, {@link
HttpServletResponse} instances
+ * in the virtual server. this interceptor can be used to check internal calls in the
tests .
+ * @param invocationListener
+ * the invocationListener to set
*/
public void setInvocationListener(InvocationListener invocationListener) {
this.invocationListener = invocationListener;
}
/**
+ * Create instance of the {@link InvocationHandler} for the proxy objects. This handler
fire events to the
+ * registered {@link InvocationListener} ( if present ) after target object method
call.
* @return the invocationHandler
*/
- public InvocationHandler getInvocationHandler(final Object target) {
+ InvocationHandler getInvocationHandler(final Object target) {
return new InvocationHandler() {
-
+
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
InvocationListener listener = getInvocationListener();
try {
Object result = method.invoke(target, args);
- if(null != listener){
- listener.afterInvoke(new InvocationEvent(target,method,args,result));
+ if (null != listener) {
+ listener.afterInvoke(new InvocationEvent(target,
+ method, args, result));
}
return result;
} catch (Throwable e) {
- if(null != listener){
- listener.processException(new InvocationErrorEvent(target,method,args,e));
+ if (null != listener) {
+ listener.processException(new InvocationErrorEvent(
+ target, method, args, e));
}
throw e;
}
}
-
+
};
-
+
}
+ /**
+ * Get virtual server session object. Create new one if necessary.
+ * @return instance of the virtual server session.
+ */
public HttpSession getSession() {
return getSession(true);
}
+ /**
+ *
+ * Returns the current <code>HttpSession</code>
+ * associated with this server or, if there is no
+ * current session and <code>create</code> is true, returns
+ * a new session. Staging server supports only one session per instance,
+ * different clients for the same server instance does not supported.
+ *
+ * <p>If <code>create</code> is <code>false</code>
+ * and the request has no valid <code>HttpSession</code>,
+ * this method returns <code>null</code>.
+ *
+ *
+ * @param create <code>true</code> to create
+ * a new session for this request if necessary;
+ * <code>false</code> to return <code>null</code>
+ * if there's no current session
+ *
+ *
+ * @return the <code>HttpSession</code> associated
+ * with this server instance or <code>null</code> if
+ * <code>create</code> is <code>false</code>
+ * and the server has no session
+ *
+ */
public synchronized HttpSession getSession(boolean create) {
if (null == this.session && create) {
this.session = new ServerHttpSession();
// Create proxy objects.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
- if(null == loader){
+ if (null == loader) {
loader = this.getClass().getClassLoader();
}
- this.sessionProxy = (HttpSession) Proxy.newProxyInstance(loader, new
Class[]{HttpSession.class}, getInvocationHandler(session));
+ this.sessionProxy = (HttpSession) Proxy.newProxyInstance(loader,
+ new Class[] { HttpSession.class },
+ getInvocationHandler(session));
// inform session listeners.
final HttpSessionEvent event = new HttpSessionEvent(session);
fireEvent(SESSION_LISTENER_CLASS,
@@ -423,6 +554,11 @@
return sessionProxy;
}
+ /**
+ * Virtual server initialization. This method creates instances of the {@link
ServletContext}, {@link JspFactory},
+ * informs {@link ServletContextListener} ind inits all {@link Filter} and {@link
Servlet} instances.
+ * It should be called from test setUp method to prepare testing environment.
+ */
public void init() {
// Create context.
this.context = new LocalContext();
@@ -433,10 +569,14 @@
// Inform listeners
// Create proxy objects.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
- if(null == loader){
+ if (null == loader) {
loader = this.getClass().getClassLoader();
}
- this.contextProxy = (ServletContext) Proxy.newProxyInstance(loader, new
Class[]{ServletContext.class}, getInvocationHandler(context));
+ this.contextProxy = (ServletContext) Proxy.newProxyInstance(loader,
+ new Class[] { ServletContext.class },
+ getInvocationHandler(context));
+ // Create default servlet
+ defaultServlet = new ServletContainer(null, new StaticServlet());
final ServletContextEvent event = new ServletContextEvent(context);
fireEvent(CONTEXT_LISTENER_CLASS,
new EventInvoker<ServletContextListener>() {
@@ -450,13 +590,17 @@
// init servlet
servlet.init(this.context);
}
- defaultServlet = new ServletContainer(null, new StaticServlet());
defaultServlet.init(getContext());
} catch (ServletException e) {
throw new TestException(e);
}
}
+ /**
+ * Stop wirtual server. This method informs {@link ServletContextListener} ind inits all
{@link Filter} and {@link Servlet} instances, as well remove all internal objects.
+ * It should be called from the testt thearDown method to clean up testing environment.
+ *
+ */
public void destroy() {
// Destroy session
if (null != this.session) {
@@ -489,15 +633,30 @@
}
+ /**
+ * Get virtual connection to the given URL. Even thought for an http request to the
+ * external servers, only local connection to the virtual server will be created.
+ * @param url request url.
+ * @return local connection to the appropriate servlet in the virtual server.
+ * @throws {@link TestException} if no servlet found to process given URL.
+ */
public StagingConnection getConnection(URL url) {
return new StagingConnection(this, url);
}
+ /**
+ * Get instance of virtual web application context.
+ * @return context instance.
+ */
public ServletContext getContext() {
return contextProxy;
}
- public void requestStarted(ServletRequest request) {
+ /**
+ * Inform {@link ServletRequestListener} instances. For internal use only.
+ * @param request started request.
+ */
+ void requestStarted(ServletRequest request) {
final ServletRequestEvent event = new ServletRequestEvent(context,
request);
fireEvent(REQUEST_LISTENER_CLASS,
@@ -509,7 +668,11 @@
});
}
- public void requestFinished(ServletRequest request) {
+ /**
+ * Inform {@link ServletRequestListener} instances. For internal use only.
+ * @param request finished request.
+ */
+ void requestFinished(ServletRequest request) {
final ServletRequestEvent event = new ServletRequestEvent(context,
request);
fireEvent(REQUEST_LISTENER_CLASS,
@@ -520,7 +683,7 @@
});
}
- public void requestAttributeAdded(ServletRequest request, String name,
+ void requestAttributeAdded(ServletRequest request, String name,
Object o) {
final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
context, request, name, o);
@@ -532,7 +695,7 @@
});
}
- public void requestAttributeRemoved(ServletRequest request, String name,
+ void requestAttributeRemoved(ServletRequest request, String name,
Object removed) {
final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
context, request, name, removed);
@@ -544,7 +707,7 @@
});
}
- public void requestAttributeReplaced(ServletRequest request, String name,
+ void requestAttributeReplaced(ServletRequest request, String name,
Object value) {
final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
context, request, name, value);
Modified:
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StaticServlet.java
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StaticServlet.java 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/java/org/richfaces/test/staging/StaticServlet.java 2008-11-20
20:25:42 UTC (rev 11282)
@@ -24,6 +24,12 @@
throws ServletException, IOException {
InputStream inputStream =
getServletContext().getResourceAsStream(req.getServletPath());
if(null != inputStream){
+ String fileName = req.getServletPath();
+ String mimeType = getServletContext().getMimeType(fileName);
+ if(null == mimeType){
+ mimeType = "text/plain";
+ }
+ resp.setContentType(mimeType);
ServletOutputStream outputStream = resp.getOutputStream();
int c;
while((c = inputStream.read())>0){
Copied: branches/jsf2.0/framework/jsf-test/src/main/javadoc (from rev 11281,
trunk/framework/jsf-test/src/main/javadoc)
Copied: branches/jsf2.0/framework/jsf-test/src/main/javadoc/org (from rev 11281,
trunk/framework/jsf-test/src/main/javadoc/org)
Copied: branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces (from rev 11281,
trunk/framework/jsf-test/src/main/javadoc/org/richfaces)
Copied: branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test (from rev
11281, trunk/framework/jsf-test/src/main/javadoc/org/richfaces/test)
Deleted:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html
===================================================================
--- trunk/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html 2008-11-20
20:25:42 UTC (rev 11282)
@@ -1,10 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
-<title>Insert title here</title>
-</head>
-<body>
-
-</body>
-</html>
\ No newline at end of file
Copied:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html (from
rev 11281, trunk/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html)
===================================================================
--- branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html
(rev 0)
+++
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html 2008-11-20
20:25:42 UTC (rev 11282)
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+
+</body>
+</html>
\ No newline at end of file
Property changes on:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/package.html
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging
(from rev 11281, trunk/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging)
Deleted:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html
===================================================================
---
trunk/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html 2008-11-20
20:04:55 UTC (rev 11281)
+++
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html 2008-11-20
20:25:42 UTC (rev 11282)
@@ -1,10 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
-<title>Insert title here</title>
-</head>
-<body>
-
-</body>
-</html>
\ No newline at end of file
Copied:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html
(from rev 11281,
trunk/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html)
===================================================================
---
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html
(rev 0)
+++
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html 2008-11-20
20:25:42 UTC (rev 11282)
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+
+</body>
+</html>
\ No newline at end of file
Property changes on:
branches/jsf2.0/framework/jsf-test/src/main/javadoc/org/richfaces/test/staging/package.html
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html
===================================================================
--- trunk/framework/jsf-test/src/main/javadoc/overview.html 2008-11-20 20:04:55 UTC (rev
11281)
+++ branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html 2008-11-20 20:25:42
UTC (rev 11282)
@@ -1,10 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
-<title>Insert title here</title>
-</head>
-<body>
-
-</body>
-</html>
\ No newline at end of file
Copied: branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html (from rev 11281,
trunk/framework/jsf-test/src/main/javadoc/overview.html)
===================================================================
--- branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html
(rev 0)
+++ branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html 2008-11-20 20:25:42
UTC (rev 11282)
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+
+</body>
+</html>
\ No newline at end of file
Property changes on: branches/jsf2.0/framework/jsf-test/src/main/javadoc/overview.html
___________________________________________________________________
Name: svn:mime-type
+ text/plain