You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2001/10/30 12:14:31 UTC
cvs commit: jakarta-commons-sandbox/messenger/src/webapp/web/jms time.jsp
jstrachan 01/10/30 03:14:31
Modified: messenger TODO.txt build.xml
messenger/src/conf subscribe.xml
messenger/src/java/org/apache/commons/messagelet
ManagerServlet.java
messenger/src/java/org/apache/commons/messagelet/impl
HttpMessageletRequestImpl.java
HttpServletRequestImpl.java
MessageletRequestImpl.java ServletRequestImpl.java
messenger/src/webapp/conf subscriptions.xml
messenger/src/webapp/web/jms time.jsp
Added: messenger/src/java/org/apache/commons/messagelet/impl
HttpSessionImpl.java
MessageHttpServletDispatcher.java RequestUtil.java
Log:
Added support for using HttpServlets, such as JSP, to dispatch JMS messages to for further processing
Revision Changes Path
1.4 +5 -0 jakarta-commons-sandbox/messenger/TODO.txt
Index: TODO.txt
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/TODO.txt,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TODO.txt 2001/10/26 14:34:57 1.3
+++ TODO.txt 2001/10/30 11:14:30 1.4
@@ -1,6 +1,11 @@
Project To Do List
==================
+* When using JSP to process JMS messages it might be nice to provide
+ the Messenger and original Message as request Attributes that the JSP
+ could use directly, without requiring to cast the request and response.
+
+
* Allow the replyTo destination and Messenger to be overridden
in the XML deployment configuration for Messagelets and Servlets.
1.22 +2 -2 jakarta-commons-sandbox/messenger/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/build.xml,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- build.xml 2001/10/30 08:55:47 1.21
+++ build.xml 2001/10/30 11:14:30 1.22
@@ -1,4 +1,4 @@
-<!-- $Id: build.xml,v 1.21 2001/10/30 08:55:47 jstrachan Exp $ -->
+<!-- $Id: build.xml,v 1.22 2001/10/30 11:14:30 jstrachan Exp $ -->
<project name="messenger" default="test" basedir=".">
<!-- patternset describing files to be copied from the doc directory -->
@@ -219,7 +219,7 @@
srcdir="${source.src.java}"
classpath="${classpath}"
debug="false"
- deprecation="true"
+ deprecation="false"
optimize="true"/>
</target>
1.3 +2 -0 jakarta-commons-sandbox/messenger/src/conf/subscribe.xml
Index: subscribe.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/conf/subscribe.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- subscribe.xml 2001/10/12 16:37:08 1.2
+++ subscribe.xml 2001/10/30 11:14:31 1.3
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<subscriptions>
+ <!-- An example of how subscriptions can look... -->
+
<subscription messenger="queue" destination="my.queue" selector="b='12'">
<!-- the output will reply to the original message -->
1.8 +13 -4 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/ManagerServlet.java
Index: ManagerServlet.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/ManagerServlet.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ManagerServlet.java 2001/10/26 11:52:16 1.7
+++ ManagerServlet.java 2001/10/30 11:14:31 1.8
@@ -5,7 +5,7 @@
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*
- * $Id: ManagerServlet.java,v 1.7 2001/10/26 11:52:16 jstrachan Exp $
+ * $Id: ManagerServlet.java,v 1.8 2001/10/30 11:14:31 jstrachan Exp $
*/
package org.apache.commons.messagelet;
@@ -23,6 +23,7 @@
import javax.servlet.ServletResponse;
import org.apache.commons.messagelet.impl.MessageServletDispatcher;
+import org.apache.commons.messagelet.impl.MessageHttpServletDispatcher;
import org.apache.commons.messagelet.impl.Subscription;
import org.apache.commons.messagelet.impl.SubscriptionDigester;
import org.apache.commons.messagelet.impl.SubscriptionList;
@@ -34,7 +35,7 @@
* and use of MessageListener beans for a given ServletContext.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
- * @version $Revision: 1.7 $
+ * @version $Revision: 1.8 $
*/
public class ManagerServlet extends GenericServlet {
@@ -42,7 +43,10 @@
private static final String KEY_SUBSCRIPTIONLIST = SubscriptionList.class.getName();
private static final String KEY_CONNECTIONS = "connections";
private static final String KEY_SUBSCRIPTIONS = "subscriptions";
-
+
+ /** Should HTTP servlets be used or generic servlets. If true then JSP can be dispatched to easily */
+ private static final boolean USE_HTTP_SERVLETS = true;
+
public ManagerServlet() {
}
@@ -134,7 +138,12 @@
MessageListener listener = null;
String servlet = subscription.getServlet();
if ( servlet != null ) {
- listener = new MessageServletDispatcher( servlet );
+ if ( USE_HTTP_SERVLETS ) {
+ listener = new MessageHttpServletDispatcher( servlet );
+ }
+ else {
+ listener = new MessageServletDispatcher( servlet );
+ }
}
else {
listener = subscription.getMessageListener();
1.2 +4 -76 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpMessageletRequestImpl.java
Index: HttpMessageletRequestImpl.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpMessageletRequestImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HttpMessageletRequestImpl.java 2001/10/29 22:32:47 1.1
+++ HttpMessageletRequestImpl.java 2001/10/30 11:14:31 1.2
@@ -5,7 +5,7 @@
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*
- * $Id: HttpMessageletRequestImpl.java,v 1.1 2001/10/29 22:32:47 jstrachan Exp $
+ * $Id: HttpMessageletRequestImpl.java,v 1.2 2001/10/30 11:14:31 jstrachan Exp $
*/
package org.apache.commons.messagelet.impl;
@@ -35,14 +35,12 @@
* the request as if it were a HTTP request.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
*/
public class HttpMessageletRequestImpl extends HttpServletRequestWrapper implements MessageletRequest {
/** The Message which caused this request */
private Message message;
- /** The parameters of this request or null if they have not been parsed yet */
- private Map parameters;
/** The stream to read the body of the current Message */
private ServletInputStream stream;
@@ -52,7 +50,6 @@
public void setMessage(Message message) throws JMSException {
this.message = message;
- this.parameters = null;
this.stream = createInputStream();
}
@@ -76,79 +73,10 @@
return new BufferedReader( new InputStreamReader( stream ) );
}
-
- /**
- * Return the value of the specified request parameter, if any; otherwise,
- * return <code>null</code>. If there is more than one value defined,
- * return only the first one.
- *
- * @param name Name of the desired request parameter
- */
- public String getParameter(String name) {
-
- parseParameters();
- String values[] = (String[]) parameters.get(name);
- if (values != null)
- return (values[0]);
- else
- return (null);
-
- }
-
-
- /**
- * Returns a <code>Map</code> of the parameters of this request.
- * Request parameters are extra information sent with the request.
- * For HTTP servlets, parameters are contained in the query string
- * or posted form data.
- *
- * @return A <code>Map</code> containing parameter names as keys
- * and parameter values as map values.
- */
- public Map getParameterMap() {
- parseParameters();
- return parameters;
- }
-
-
- /**
- * Return the names of all defined request parameters for this request.
- */
- public Enumeration getParameterNames() {
- parseParameters();
- return new IteratorEnumeration(parameters.keySet().iterator());
- }
-
-
- /**
- * Return the defined values for the specified request parameter, if any;
- * otherwise, return <code>null</code>.
- *
- * @param name Name of the desired request parameter
- */
- public String[] getParameterValues(String name) {
- parseParameters();
- String values[] = (String[]) parameters.get(name);
- if (values != null)
- return (values);
- else
- return (null);
- }
-
-
+
+
// Implementation methods
//-------------------------------------------------------------------------
-
-
- /**
- * Parse the parameters of this request, if it has not already occurred.
- */
- protected void parseParameters() {
- if (parameters == null) {
- Map map = new HashMap();
- parameters = Collections.unmodifiableMap( map );
- }
- }
protected ServletInputStream createInputStream() throws JMSException {
if ( message instanceof TextMessage ) {
1.2 +42 -6 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpServletRequestImpl.java
Index: HttpServletRequestImpl.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpServletRequestImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HttpServletRequestImpl.java 2001/10/29 22:32:47 1.1
+++ HttpServletRequestImpl.java 2001/10/30 11:14:31 1.2
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpServletRequestImpl.java,v 1.1 2001/10/29 22:32:47 jstrachan Exp $
- * $Revision: 1.1 $
- * $Date: 2001/10/29 22:32:47 $
+ * $Header: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpServletRequestImpl.java,v 1.2 2001/10/30 11:14:31 jstrachan Exp $
+ * $Revision: 1.2 $
+ * $Date: 2001/10/30 11:14:31 $
*
* ====================================================================
*
@@ -96,7 +96,7 @@
*
* @author Craig R. McClanahan
* @author James Strachan
- * @version $Revision: 1.1 $ $Date: 2001/10/29 22:32:47 $
+ * @version $Revision: 1.2 $ $Date: 2001/10/30 11:14:31 $
*/
public class HttpServletRequestImpl extends ServletRequestImpl implements HttpServletRequest {
@@ -190,7 +190,7 @@
/**
* The currently active session for this request.
*/
- protected HttpSession session = null;
+ protected HttpSessionImpl session = null;
/**
@@ -198,6 +198,11 @@
*/
protected Principal userPrincipal = null;
+
+ /**
+ * The parameters
+ */
+ private Map parameters = null;
// --------------------------------------------------------- Public Methods
@@ -332,6 +337,7 @@
public void setQueryString(String query) {
this.queryString = query;
+ this.parameters = null;
}
@@ -574,6 +580,30 @@
/**
+ * Returns a <code>Map</code> of the parameters of this request.
+ * Request parameters are extra information sent with the request.
+ * For HTTP servlets, parameters are contained in the query string
+ * or posted form data.
+ *
+ * @return A <code>Map</code> containing parameter names as keys
+ * and parameter values as map values.
+ */
+ public Map getParameterMap() {
+ if ( parameters == null ) {
+ parameters = new HashMap();
+ if ( queryString != null ) {
+ try {
+ RequestUtil.parseParameters(parameters, queryString, getCharacterEncoding());
+ }
+ catch (UnsupportedEncodingException e) {
+ servletContext.log( "Could not parse query string: " + queryString, e);
+ }
+ }
+ }
+ return parameters;
+ }
+
+ /**
* Return the path information associated with this Request.
*/
public String getPathInfo() {
@@ -709,8 +739,14 @@
* @param create Create a new session if one does not exist
*/
public HttpSession getSession(boolean create) {
- return (null);
-
+ // Return the current session if it exists and is valid
+ if ((session != null) && !session.isValid())
+ session = null;
+
+ if ( create && session == null) {
+ session = new HttpSessionImpl( servletContext );
+ }
+ return session;
}
1.4 +2 -75 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/MessageletRequestImpl.java
Index: MessageletRequestImpl.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/MessageletRequestImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- MessageletRequestImpl.java 2001/10/29 22:32:47 1.3
+++ MessageletRequestImpl.java 2001/10/30 11:14:31 1.4
@@ -5,7 +5,7 @@
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*
- * $Id: MessageletRequestImpl.java,v 1.3 2001/10/29 22:32:47 jstrachan Exp $
+ * $Id: MessageletRequestImpl.java,v 1.4 2001/10/30 11:14:31 jstrachan Exp $
*/
package org.apache.commons.messagelet.impl;
@@ -34,14 +34,12 @@
* a JMS Message source.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
- * @version $Revision: 1.3 $
+ * @version $Revision: 1.4 $
*/
public class MessageletRequestImpl extends ServletRequestWrapper implements MessageletRequest {
/** The Message which caused this request */
private Message message;
- /** The parameters of this request or null if they have not been parsed yet */
- private Map parameters;
/** The stream to read the body of the current Message */
private ServletInputStream stream;
@@ -51,7 +49,6 @@
public void setMessage(Message message) throws JMSException {
this.message = message;
- this.parameters = null;
this.stream = createInputStream();
}
@@ -75,80 +72,10 @@
return new BufferedReader( new InputStreamReader( stream ) );
}
-
- /**
- * Return the value of the specified request parameter, if any; otherwise,
- * return <code>null</code>. If there is more than one value defined,
- * return only the first one.
- *
- * @param name Name of the desired request parameter
- */
- public String getParameter(String name) {
-
- parseParameters();
- String values[] = (String[]) parameters.get(name);
- if (values != null)
- return (values[0]);
- else
- return (null);
-
- }
-
-
- /**
- * Returns a <code>Map</code> of the parameters of this request.
- * Request parameters are extra information sent with the request.
- * For HTTP servlets, parameters are contained in the query string
- * or posted form data.
- *
- * @return A <code>Map</code> containing parameter names as keys
- * and parameter values as map values.
- */
- public Map getParameterMap() {
- parseParameters();
- return parameters;
- }
-
-
- /**
- * Return the names of all defined request parameters for this request.
- */
- public Enumeration getParameterNames() {
- parseParameters();
- return new IteratorEnumeration(parameters.keySet().iterator());
- }
-
-
- /**
- * Return the defined values for the specified request parameter, if any;
- * otherwise, return <code>null</code>.
- *
- * @param name Name of the desired request parameter
- */
- public String[] getParameterValues(String name) {
- parseParameters();
- String values[] = (String[]) parameters.get(name);
- if (values != null)
- return (values);
- else
- return (null);
- }
-
-
// Implementation methods
//-------------------------------------------------------------------------
- /**
- * Parse the parameters of this request, if it has not already occurred.
- */
- protected void parseParameters() {
- if (parameters == null) {
- Map map = new HashMap();
- parameters = Collections.unmodifiableMap( map );
- }
- }
-
protected ServletInputStream createInputStream() throws JMSException {
if ( message instanceof TextMessage ) {
TextMessage textMessage = (TextMessage) message;
1.3 +30 -8 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/ServletRequestImpl.java
Index: ServletRequestImpl.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/ServletRequestImpl.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ServletRequestImpl.java 2001/10/29 22:32:47 1.2
+++ ServletRequestImpl.java 2001/10/30 11:14:31 1.3
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/ServletRequestImpl.java,v 1.2 2001/10/29 22:32:47 jstrachan Exp $
- * $Revision: 1.2 $
- * $Date: 2001/10/29 22:32:47 $
+ * $Header: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/ServletRequestImpl.java,v 1.3 2001/10/30 11:14:31 jstrachan Exp $
+ * $Revision: 1.3 $
+ * $Date: 2001/10/30 11:14:31 $
*
* ====================================================================
*
@@ -92,7 +92,7 @@
*
* @author Craig R. McClanahan
* @author James Strachan
- * @version $Revision: 1.2 $ $Date: 2001/10/29 22:32:47 $
+ * @version $Revision: 1.3 $ $Date: 2001/10/30 11:14:31 $
*/
public class ServletRequestImpl implements ServletRequest {
@@ -464,8 +464,10 @@
*/
public String getCharacterEncoding() {
- return (this.characterEncoding);
-
+ if (characterEncoding== null) {
+ characterEncoding= "ISO-8859-1";
+ }
+ return (this.characterEncoding);
}
@@ -628,8 +630,6 @@
if (reader == null) {
String encoding = getCharacterEncoding();
- if (encoding == null)
- encoding = "ISO-8859-1";
InputStreamReader isr =
new InputStreamReader(createInputStream(), encoding);
reader = new BufferedReader(isr);
@@ -795,8 +795,30 @@
// Save the validated encoding
this.characterEncoding = enc;
+ }
+
+ /**
+ * Log a message to the current ServletContext
+ *
+ * @param message Message to be logged
+ */
+ protected void log(String message) {
+
+ servletContext.log(message);
}
+
+ /**
+ * Log a message to the current ServletContext
+ *
+ * @param message Message to be logged
+ * @param throwable Associated exception
+ */
+ protected void log(String message, Throwable throwable) {
+
+ servletContext.log(message, throwable);
+
+ }
}
1.1 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpSessionImpl.java
Index: HttpSessionImpl.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/HttpSessionImpl.java,v 1.1 2001/10/30 11:14:31 jstrachan Exp $
* $Revision: 1.1 $
* $Date: 2001/10/30 11:14:31 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.commons.messagelet.impl;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.apache.commons.collections.IteratorEnumeration;
/**
* Based on the Catalina StandardSession class.
* Standard implementation of the <b>HttpSession</b> interface. This object is
* serializable, so that it can be stored in persistent storage or transferred
* to a different JVM for distributable session support.
* <p>
*
* @author Craig R. McClanahan
* @author Sean Legassick
* @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
* @version $Revision: 1.1 $ $Date: 2001/10/30 11:14:31 $
*/
public class HttpSessionImpl implements HttpSession, Serializable {
// ----------------------------------------------------- Instance Variables
/**
* The dummy attribute value serialized when a NotSerializableException is
* encountered in <code>writeObject()</code>.
*/
private static final String NOT_SERIALIZED =
"___NOT_SERIALIZABLE_EXCEPTION___";
/**
* The collection of user data attributes associated with this Session.
*/
private HashMap attributes = new HashMap();
/**
* The authentication type used to authenticate our cached Principal,
* if any. NOTE: This value is not included in the serialized
* version of this object.
*/
private transient String authType = null;
/**
* The time this session was created, in milliseconds since midnight,
* January 1, 1970 GMT.
*/
private long creationTime = 0L;
/**
* The debugging detail level for this component. NOTE: This value
* is not included in the serialized version of this object.
*/
private transient int debug = 0;
/**
* We are currently processing a session expiration, so bypass
* certain IllegalStateException tests. NOTE: This value is not
* included in the serialized version of this object.
*/
private transient boolean expiring = false;
/**
* The session identifier of this Session.
*/
private String id = null;
/**
* The last accessed time for this Session.
*/
private long lastAccessedTime = creationTime;
/**
* The session event listeners for this Session.
*/
private transient ArrayList listeners = new ArrayList();
/**
* The maximum time interval, in seconds, between client requests before
* the servlet container may invalidate this session. A negative time
* indicates that the session should never time out.
*/
private int maxInactiveInterval = -1;
/**
* Flag indicating whether this session is new or not.
*/
private boolean isNew = false;
/**
* Flag indicating whether this session is valid or not.
*/
private boolean isValid = false;
/**
* Internal notes associated with this session by Catalina components
* and event listeners. <b>IMPLEMENTATION NOTE:</b> This object is
* <em>not</em> saved and restored across session serializations!
*/
private transient HashMap notes = new HashMap();
/**
* The authenticated Principal associated with this session, if any.
* <b>IMPLEMENTATION NOTE:</b> This object is <i>not</i> saved and
* restored across session serializations!
*/
private transient Principal principal = null;
/**
* The property change support for this component. NOTE: This value
* is not included in the serialized version of this object.
*/
private transient PropertyChangeSupport support =
new PropertyChangeSupport(this);
/**
* The current accessed time for this session.
*/
private long thisAccessedTime = creationTime;
/**
* The ServletContext
*/
protected ServletContext servletContext;
/**
* Is this session distributable. If so then
* its values must be Serializable.
*/
private boolean distributable = false;
public HttpSessionImpl(ServletContext servletContext) {
this.servletContext = servletContext;
}
// ----------------------------------------------------- Session Properties
/**
* Return the authentication type used to authenticate our cached
* Principal, if any.
*/
public String getAuthType() {
return (this.authType);
}
/**
* Set the authentication type used to authenticate our cached
* Principal, if any.
*
* @param authType The new cached authentication type
*/
public void setAuthType(String authType) {
String oldAuthType = this.authType;
this.authType = authType;
support.firePropertyChange("authType", oldAuthType, this.authType);
}
/**
* Set the creation time for this session. This method is called by the
* Manager when an existing Session instance is reused.
*
* @param time The new creation time
*/
public void setCreationTime(long time) {
this.creationTime = time;
this.lastAccessedTime = time;
this.thisAccessedTime = time;
}
/**
* Return the session identifier for this session.
*/
public String getId() {
return (this.id);
}
/**
* Set the session identifier for this session.
*
* @param id The new session identifier
*/
public void setId(String id) {
this.id = id;
// Notify interested session event listeners
///fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
}
/**
* Return the last time the client sent a request associated with this
* session, as the number of milliseconds since midnight, January 1, 1970
* GMT. Actions that your application takes, such as getting or setting
* a value associated with the session, do not affect the access time.
*/
public long getLastAccessedTime() {
return (this.lastAccessedTime);
}
/**
* Return the maximum time interval, in seconds, between client requests
* before the servlet container will invalidate the session. A negative
* time indicates that the session should never time out.
*
* @exception IllegalStateException if this method is called on
* an invalidated session
*/
public int getMaxInactiveInterval() {
if (!isValid) {
throw new IllegalStateException( "Cannot call getMaxInactiveInterval on an invalidated session" );
}
return (this.maxInactiveInterval);
}
/**
* Set the maximum time interval, in seconds, between client requests
* before the servlet container will invalidate the session. A negative
* time indicates that the session should never time out.
*
* @param interval The new maximum interval
*/
public void setMaxInactiveInterval(int interval) {
this.maxInactiveInterval = interval;
}
/**
* Set the <code>isNew</code> flag for this session.
*
* @param isNew The new value for the <code>isNew</code> flag
*/
public void setNew(boolean isNew) {
this.isNew = isNew;
}
/**
* Return the authenticated Principal that is associated with this Session.
* This provides an <code>Authenticator</code> with a means to cache a
* previously authenticated Principal, and avoid potentially expensive
* <code>Realm.authenticate()</code> calls on every request. If there
* is no current associated Principal, return <code>null</code>.
*/
public Principal getPrincipal() {
return (this.principal);
}
/**
* Set the authenticated Principal that is associated with this Session.
* This provides an <code>Authenticator</code> with a means to cache a
* previously authenticated Principal, and avoid potentially expensive
* <code>Realm.authenticate()</code> calls on every request.
*
* @param principal The new Principal, or <code>null</code> if none
*/
public void setPrincipal(Principal principal) {
Principal oldPrincipal = this.principal;
this.principal = principal;
support.firePropertyChange("principal", oldPrincipal, this.principal);
}
/**
* Return the <code>isValid</code> flag for this session.
*/
public boolean isValid() {
return (this.isValid);
}
/**
* Set the <code>isValid</code> flag for this session.
*
* @param isValid The new value for the <code>isValid</code> flag
*/
public void setValid(boolean isValid) {
this.isValid = isValid;
}
// ------------------------------------------------- Session Public Methods
/**
* Update the accessed time information for this session. This method
* should be called by the context when a request comes in for a particular
* session, even if the application does not reference it.
*/
public void access() {
this.isNew = false;
this.lastAccessedTime = this.thisAccessedTime;
this.thisAccessedTime = System.currentTimeMillis();
}
/**
* Perform the internal processing required to invalidate this session,
* without triggering an exception if the session has already expired.
*/
public void expire() {
// Mark this session as "being expired" if needed
if (expiring)
return;
expiring = true;
setValid(false);
// Unbind any objects associated with this session
String keys[] = keys();
for (int i = 0; i < keys.length; i++)
removeAttribute(keys[i]);
// Notify interested session event listeners
//fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
// We have completed expire of this session
expiring = false;
}
/**
* Perform the internal processing required to passivate
* this session.
*/
public void passivate() {
// Notify ActivationListeners
HttpSessionEvent event = null;
String keys[] = keys();
for (int i = 0; i < keys.length; i++) {
Object attribute = getAttribute(keys[i]);
if (attribute instanceof HttpSessionActivationListener) {
if (event == null)
event = new HttpSessionEvent(this);
// FIXME: Should we catch throwables?
((HttpSessionActivationListener)attribute).sessionWillPassivate(event);
}
}
}
/**
* Perform internal processing required to activate this
* session.
*/
public void activate() {
// Notify ActivationListeners
HttpSessionEvent event = null;
String keys[] = keys();
for (int i = 0; i < keys.length; i++) {
Object attribute = getAttribute(keys[i]);
if (attribute instanceof HttpSessionActivationListener) {
if (event == null)
event = new HttpSessionEvent(this);
// FIXME: Should we catch throwables?
((HttpSessionActivationListener)attribute).sessionDidActivate(event);
}
}
}
/**
* Return the object bound with the specified name to the internal notes
* for this session, or <code>null</code> if no such binding exists.
*
* @param name Name of the note to be returned
*/
public Object getNote(String name) {
synchronized (notes) {
return (notes.get(name));
}
}
/**
* Return an Iterator containing the String names of all notes bindings
* that exist for this session.
*/
public Iterator getNoteNames() {
synchronized (notes) {
return (notes.keySet().iterator());
}
}
/**
* Release all object references, and initialize instance variables, in
* preparation for reuse of this object.
*/
public void recycle() {
// Reset the instance variables associated with this Session
attributes.clear();
setAuthType(null);
creationTime = 0L;
expiring = false;
id = null;
lastAccessedTime = 0L;
maxInactiveInterval = -1;
setPrincipal(null);
isNew = false;
isValid = false;
}
/**
* Remove any object bound to the specified name in the internal notes
* for this session.
*
* @param name Name of the note to be removed
*/
public void removeNote(String name) {
synchronized (notes) {
notes.remove(name);
}
}
/**
* Bind an object to a specified name in the internal notes associated
* with this session, replacing any existing binding for this name.
*
* @param name Name to which the object should be bound
* @param value Object to be bound to the specified name
*/
public void setNote(String name, Object value) {
synchronized (notes) {
notes.put(name, value);
}
}
/**
* Return a string representation of this object.
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("StandardSession[");
sb.append(id);
sb.append("]");
return (sb.toString());
}
// ------------------------------------------------ Session Package Methods
/**
* Read a serialized version of the contents of this session object from
* the specified object input stream, without requiring that the
* StandardSession itself have been serialized.
*
* @param stream The object input stream to read from
*
* @exception ClassNotFoundException if an unknown class is specified
* @exception IOException if an input/output error occurs
*/
void readObjectData(ObjectInputStream stream)
throws ClassNotFoundException, IOException {
readObject(stream);
}
/**
* Write a serialized version of the contents of this session object to
* the specified object output stream, without requiring that the
* StandardSession itself have been serialized.
*
* @param stream The object output stream to write to
*
* @exception IOException if an input/output error occurs
*/
void writeObjectData(ObjectOutputStream stream)
throws IOException {
writeObject(stream);
}
// ------------------------------------------------- HttpSession Properties
/**
* Return the time when this session was created, in milliseconds since
* midnight, January 1, 1970 GMT.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public long getCreationTime() {
if (!isValid) {
throw new IllegalStateException( "Cannot call getCreationTime() on invalidated session" );
}
return (this.creationTime);
}
/**
* Return the ServletContext to which this session belongs.
*/
public ServletContext getServletContext() {
return servletContext;
}
/**
* Return the session context with which this session is associated.
*
* @deprecated As of Version 2.1, this method is deprecated and has no
* replacement. It will be removed in a future version of the
* Java Servlet API.
*/
public HttpSessionContext getSessionContext() {
return null;
}
// ----------------------------------------------HttpSession Public Methods
/**
* Return the object bound with the specified name in this session, or
* <code>null</code> if no object is bound with that name.
*
* @param name Name of the attribute to be returned
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public Object getAttribute(String name) {
if (!isValid) {
throw new IllegalStateException( "Cannot call getAttribute() on invalidated session" );
}
synchronized (attributes) {
return (attributes.get(name));
}
}
/**
* Return an <code>Enumeration</code> of <code>String</code> objects
* containing the names of the objects bound to this session.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public Enumeration getAttributeNames() {
if (!isValid) {
throw new IllegalStateException( "Cannot call getAttributeNames() on invalidated session" );
}
synchronized (attributes) {
return (new IteratorEnumeration(attributes.keySet().iterator()));
}
}
/**
* Return the object bound with the specified name in this session, or
* <code>null</code> if no object is bound with that name.
*
* @param name Name of the value to be returned
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>getAttribute()</code>
*/
public Object getValue(String name) {
return (getAttribute(name));
}
/**
* Return the set of names of objects bound to this session. If there
* are no such objects, a zero-length array is returned.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>getAttributeNames()</code>
*/
public String[] getValueNames() {
if (!isValid) {
throw new IllegalStateException( "Cannot call getValueNames() on invalidated session" );
}
return (keys());
}
/**
* Invalidates this session and unbinds any objects bound to it.
*
* @exception IllegalStateException if this method is called on
* an invalidated session
*/
public void invalidate() {
if (!isValid) {
throw new IllegalStateException( "Cannot call invalidate() on invalidated session" );
}
// Cause this session to expire
expire();
}
/**
* Return <code>true</code> if the client does not yet know about the
* session, or if the client chooses not to join the session. For
* example, if the server used only cookie-based sessions, and the client
* has disabled the use of cookies, then a session would be new on each
* request.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public boolean isNew() {
if (!isValid) {
throw new IllegalStateException( "Cannot call isNew() on invalidated session" );
}
return (this.isNew);
}
/**
* Bind an object to this session, using the specified name. If an object
* of the same name is already bound to this session, the object is
* replaced.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueBound()</code> on the object.
*
* @param name Name to which the object is bound, cannot be null
* @param value Object to be bound, cannot be null
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>setAttribute()</code>
*/
public void putValue(String name, Object value) {
setAttribute(name, value);
}
/**
* Remove the object bound with the specified name from this session. If
* the session does not have an object bound with this name, this method
* does nothing.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueUnbound()</code> on the object.
*
* @param name Name of the object to remove from this session.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public void removeAttribute(String name) {
// Validate our current state
if (!expiring && !isValid) {
throw new IllegalStateException( "Cannot call removeAttribute() on an invalidated session" );
}
// Remove this attribute from our collection
Object value = null;
boolean found = false;
synchronized (attributes) {
found = attributes.containsKey(name);
if (found) {
value = attributes.get(name);
attributes.remove(name);
} else {
return;
}
}
/*
// Call the valueUnbound() method if necessary
HttpSessionBindingEvent event =
new HttpSessionBindingEvent((HttpSession) this, name, value);
if ((value != null) &&
(value instanceof HttpSessionBindingListener))
((HttpSessionBindingListener) value).valueUnbound(event);
// Notify interested application event listeners
StandardContext context = (StandardContext) manager.getContainer();
Object listeners[] = context.getApplicationListeners();
if (listeners == null)
return;
for (int i = 0; i < listeners.length; i++) {
if (!(listeners[i] instanceof HttpSessionAttributeListener))
continue;
HttpSessionAttributeListener listener =
(HttpSessionAttributeListener) listeners[i];
try {
context.fireContainerEvent("beforeSessionAttributeRemoved",
listener);
listener.attributeRemoved(event);
context.fireContainerEvent("afterSessionAttributeRemoved",
listener);
} catch (Throwable t) {
context.fireContainerEvent("afterSessionAttributeRemoved",
listener);
// FIXME - should we do anything besides log these?
log( "Exception firing attribute event", t);
}
}
*/
}
/**
* Remove the object bound with the specified name from this session. If
* the session does not have an object bound with this name, this method
* does nothing.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueUnbound()</code> on the object.
*
* @param name Name of the object to remove from this session.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>removeAttribute()</code>
*/
public void removeValue(String name) {
removeAttribute(name);
}
/**
* Bind an object to this session, using the specified name. If an object
* of the same name is already bound to this session, the object is
* replaced.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueBound()</code> on the object.
*
* @param name Name to which the object is bound, cannot be null
* @param value Object to be bound, cannot be null
*
* @exception IllegalArgumentException if an attempt is made to add a
* non-serializable object in an environment marked distributable.
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public void setAttribute(String name, Object value) {
// Name cannot be null
if (name == null) {
throw new IllegalArgumentException( "Attribute name cannot be null" );
}
// Null value is the same as removeAttribute()
if (value == null) {
removeAttribute(name);
return;
}
// Validate our current state
if (!isValid) {
throw new IllegalStateException( "You cannot call this method on an invalidated session" );
}
if (distributable &&
!(value instanceof Serializable)) {
throw new IllegalArgumentException( "Attribute value must be Serializable" );
}
// Replace or add this attribute
Object unbound = null;
synchronized (attributes) {
unbound = attributes.get(name);
attributes.put(name, value);
}
// Call the valueUnbound() method if necessary
if ((unbound != null) &&
(unbound instanceof HttpSessionBindingListener)) {
((HttpSessionBindingListener) unbound).valueUnbound
(new HttpSessionBindingEvent((HttpSession) this, name));
}
// Call the valueBound() method if necessary
HttpSessionBindingEvent event = null;
if (unbound != null)
event = new HttpSessionBindingEvent
((HttpSession) this, name, unbound);
else
event = new HttpSessionBindingEvent
((HttpSession) this, name, value);
if (value instanceof HttpSessionBindingListener)
((HttpSessionBindingListener) value).valueBound(event);
// Notify interested application event listeners
/*
StandardContext context = (StandardContext) manager.getContainer();
Object listeners[] = context.getApplicationListeners();
if (listeners == null)
return;
for (int i = 0; i < listeners.length; i++) {
if (!(listeners[i] instanceof HttpSessionAttributeListener))
continue;
HttpSessionAttributeListener listener =
(HttpSessionAttributeListener) listeners[i];
try {
if (unbound != null) {
context.fireContainerEvent("beforeSessionAttributeReplaced",
listener);
listener.attributeReplaced(event);
context.fireContainerEvent("afterSessionAttributeReplaced",
listener);
} else {
context.fireContainerEvent("beforeSessionAttributeAdded",
listener);
listener.attributeAdded(event);
context.fireContainerEvent("afterSessionAttributeAdded",
listener);
}
} catch (Throwable t) {
if (unbound != null)
context.fireContainerEvent("afterSessionAttributeReplaced",
listener);
else
context.fireContainerEvent("afterSessionAttributeAdded",
listener);
// FIXME - should we do anything besides log these?
log( "Exception firing attribute event", t);
}
}
*/
}
// -------------------------------------------- HttpSession Private Methods
/**
* Read a serialized version of this session object from the specified
* object input stream.
* <p>
* <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
* is not restored by this method, and must be set explicitly.
*
* @param stream The input stream to read from
*
* @exception ClassNotFoundException if an unknown class is specified
* @exception IOException if an input/output error occurs
*/
private void readObject(ObjectInputStream stream)
throws ClassNotFoundException, IOException {
// Deserialize the scalar instance variables (except Manager)
authType = null; // Transient only
creationTime = ((Long) stream.readObject()).longValue();
lastAccessedTime = ((Long) stream.readObject()).longValue();
maxInactiveInterval = ((Integer) stream.readObject()).intValue();
isNew = ((Boolean) stream.readObject()).booleanValue();
isValid = ((Boolean) stream.readObject()).booleanValue();
thisAccessedTime = ((Long) stream.readObject()).longValue();
principal = null; // Transient only
setId((String) stream.readObject());
if (debug >= 2)
log("readObject() loading session " + id);
// Deserialize the attribute count and attribute values
if (attributes == null)
attributes = new HashMap();
int n = ((Integer) stream.readObject()).intValue();
boolean isValidSave = isValid;
isValid = true;
for (int i = 0; i < n; i++) {
String name = (String) stream.readObject();
Object value = (Object) stream.readObject();
if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
continue;
if (debug >= 2)
log(" loading attribute '" + name +
"' with value '" + value + "'");
synchronized (attributes) {
attributes.put(name, value);
}
}
isValid = isValidSave;
}
/**
* Write a serialized version of this session object to the specified
* object output stream.
* <p>
* <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
* in the serialized representation of this Session. After calling
* <code>readObject()</code>, you must set the associated Manager
* explicitly.
* <p>
* <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
* will be unbound from the session, with appropriate actions if it
* implements HttpSessionBindingListener. If you do not want any such
* attributes, be sure the <code>distributable</code> property of the
* associated Manager is set to <code>true</code>.
*
* @param stream The output stream to write to
*
* @exception IOException if an input/output error occurs
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
// Write the scalar instance variables (except Manager)
stream.writeObject(new Long(creationTime));
stream.writeObject(new Long(lastAccessedTime));
stream.writeObject(new Integer(maxInactiveInterval));
stream.writeObject(new Boolean(isNew));
stream.writeObject(new Boolean(isValid));
stream.writeObject(new Long(thisAccessedTime));
stream.writeObject(id);
if (debug >= 2)
log("writeObject() storing session " + id);
// Accumulate the names of serializable and non-serializable attributes
String keys[] = keys();
ArrayList saveNames = new ArrayList();
ArrayList saveValues = new ArrayList();
ArrayList unbinds = new ArrayList();
for (int i = 0; i < keys.length; i++) {
Object value = null;
synchronized (attributes) {
value = attributes.get(keys[i]);
}
if (value == null)
continue;
else if (value instanceof Serializable) {
saveNames.add(keys[i]);
saveValues.add(value);
} else
unbinds.add(keys[i]);
}
// Serialize the attribute count and the Serializable attributes
int n = saveNames.size();
stream.writeObject(new Integer(n));
for (int i = 0; i < n; i++) {
stream.writeObject((String) saveNames.get(i));
try {
stream.writeObject(saveValues.get(i));
if (debug >= 2)
log(" storing attribute '" + saveNames.get(i) +
"' with value '" + saveValues.get(i) + "'");
} catch (NotSerializableException e) {
log( "Session is not serializable for attribute name: " + saveNames.get(i) + " and session id: " + id, e);
stream.writeObject(NOT_SERIALIZED);
if (debug >= 2)
log(" storing attribute '" + saveNames.get(i) +
"' with value NOT_SERIALIZED");
unbinds.add(saveNames.get(i));
}
}
// Unbind the non-Serializable attributes
Iterator names = unbinds.iterator();
while (names.hasNext()) {
removeAttribute((String) names.next());
}
}
// -------------------------------------------------------- Private Methods
/**
* Notify all session event listeners that a particular event has
* occurred for this Session. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
public void fireSessionEvent(String type, Object data) {
/*
if (listeners.size() < 1)
return;
SessionEvent event = new SessionEvent(this, type, data);
SessionListener list[] = new SessionListener[0];
synchronized (listeners) {
list = (SessionListener[]) listeners.toArray(list);
}
for (int i = 0; i < list.length; i++)
((SessionListener) list[i]).sessionEvent(event);
*/
}
/**
* Return the names of all currently defined session attributes
* as an array of Strings. If there are no defined attributes, a
* zero-length array is returned.
*/
private String[] keys() {
String results[] = new String[0];
synchronized (attributes) {
return ((String[]) attributes.keySet().toArray(results));
}
}
/**
* Log a message to the current ServletContext
*
* @param message Message to be logged
*/
protected void log(String message) {
servletContext.log(message);
}
/**
* Log a message to the current ServletContext
*
* @param message Message to be logged
* @param throwable Associated exception
*/
protected void log(String message, Throwable throwable) {
servletContext.log(message, throwable);
}
}
1.1 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/MessageHttpServletDispatcher.java
Index: MessageHttpServletDispatcher.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*
* $Id: MessageHttpServletDispatcher.java,v 1.1 2001/10/30 11:14:31 jstrachan Exp $
*/
package org.apache.commons.messagelet.impl;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.JMSException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.commons.messagelet.MessageDrivenObjectSupport;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerListener;
/** <p><code>MessageHttpServletDispatcher</code> dispatches JMS Messages
* into a HttpServlet for procesing.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
* @version $Revision: 1.1 $
*/
public class MessageHttpServletDispatcher extends MessageDrivenObjectSupport implements MessengerListener {
/**
* The HttpServletRequest object we will pass to the servlet engine
*/
private HttpMessageletRequestImpl request;
/**
* The HttpServletResponse object we will pass to the servlet engine
*/
private HttpMessageletResponseImpl response;
/**
* The reply to messenger
*/
private Messenger messenger;
/** Holds value of property path. */
private String path;
public MessageHttpServletDispatcher() {
//request.setResponse(response);
//response.setRequest(request);
}
public MessageHttpServletDispatcher(String path) {
this();
this.path = path;
}
public void init() throws ServletException {
request = new HttpMessageletRequestImpl( createHttpServletRequest() );
response = new HttpMessageletResponseImpl( new HttpServletResponseImpl() );
}
// MessengerListener methods
//-------------------------------------------------------------------------
public void setMessenger(Messenger messenger) {
response.setReplyMessenger( messenger );
}
/**
* Process the incoming JMS Message.
*
* @param message is the message to be processed
*/
public void onMessage(Message message) {
try {
response.setReplyToDestination( message.getJMSReplyTo() );
}
catch (JMSException e) {
log( "Could not find JMS replyTo destination", e );
response.setReplyToDestination( null );
}
// Ask our Container to process this request
try {
// initialise the request
request.setMessage( message );
response.reset();
// dispatch the servlet
getServletContext().getRequestDispatcher( getPath() ).include(request, response);
// finish up the response, sending a reply if necessary
response.finish();
}
catch (Throwable e) {
handleException( message, e );
}
}
// Properties
//-------------------------------------------------------------------------
/** Getter for property path.
* @return Value of property path.
*/
public String getPath() {
return path;
}
/** Setter for property path.
* @param path New value of property path.
*/
public void setPath(String path) {
this.path = path;
//request.setRequestURI(path);
}
// Implementation methods
//-------------------------------------------------------------------------
protected void handleException(Message message, Throwable t) {
log( "Caught exception processing message: " + message, t);
}
protected HttpServletRequestImpl createHttpServletRequest() {
HttpServletRequestImpl request = new HttpServletRequestImpl( getServletContext() );
request.setRequestURI( path );
int idx = path.indexOf( '?' );
if ( idx >= 0 ) {
request.setQueryString( path.substring( idx + 1 ) );
request.setPathInfo( path.substring( 0, idx ) );
}
return request;
}
}
1.1 jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/RequestUtil.java
Index: RequestUtil.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons-sandbox/messenger/src/java/org/apache/commons/messagelet/impl/RequestUtil.java,v 1.1 2001/10/30 11:14:31 jstrachan Exp $
* $Revision: 1.1 $
* $Date: 2001/10/30 11:14:31 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.commons.messagelet.impl;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import javax.servlet.http.Cookie;
/**
* General purpose request parsing and encoding utility methods.
*
* @author Craig R. McClanahan
* @author Tim Tye
* @version $Revision: 1.1 $ $Date: 2001/10/30 11:14:31 $
*/
public final class RequestUtil {
/**
* The DateFormat to use for generating readable dates in cookies.
*/
private static SimpleDateFormat format =
new SimpleDateFormat(" EEEE, dd-MMM-yy kk:mm:ss zz");
static {
format.setTimeZone(TimeZone.getTimeZone("GMT"));
}
/**
* Encode a cookie as per RFC 2109. The resulting string can be used
* as the value for a <code>Set-Cookie</code> header.
*
* @param cookie The cookie to encode.
* @return A string following RFC 2109.
*/
public static String encodeCookie(Cookie cookie) {
StringBuffer buf = new StringBuffer( cookie.getName() );
buf.append("=");
buf.append(cookie.getValue());
if (cookie.getComment() != null) {
buf.append("; Comment=\"");
buf.append(cookie.getComment());
buf.append("\"");
}
if (cookie.getDomain() != null) {
buf.append("; Domain=\"");
buf.append(cookie.getDomain());
buf.append("\"");
}
long age = cookie.getMaxAge();
if (cookie.getMaxAge() >= 0) {
buf.append("; Max-Age=\"");
buf.append(cookie.getMaxAge());
buf.append("\"");
}
if (cookie.getPath() != null) {
buf.append("; Path=\"");
buf.append(cookie.getPath());
buf.append("\"");
}
if (cookie.getSecure()) {
buf.append("; Secure");
}
if (cookie.getVersion() > 0) {
buf.append("; Version=\"");
buf.append(cookie.getVersion());
buf.append("\"");
}
return (buf.toString());
}
/**
* Filter the specified message string for characters that are sensitive
* in HTML. This avoids potential attacks caused by including JavaScript
* codes in the request URL that is often reported in error messages.
*
* @param message The message string to be filtered
*/
public static String filter(String message) {
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
/**
* Normalize a relative URI path that may have relative values ("/./",
* "/../", and so on ) it it. <strong>WARNING</strong> - This method is
* useful only for normalizing application-generated paths. It does not
* try to perform security checks for malicious input.
*
* @param path Relative path to be normalized
*/
public static String normalize(String path) {
if (path == null)
return null;
// Create a place for the normalized path
String normalized = path;
if (normalized.equals("/."))
return "/";
// Add a leading "/" if necessary
if (!normalized.startsWith("/"))
normalized = "/" + normalized;
// Resolve occurrences of "//" in the normalized path
while (true) {
int index = normalized.indexOf("//");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 1);
}
// Resolve occurrences of "/./" in the normalized path
while (true) {
int index = normalized.indexOf("/./");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 2);
}
// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}
// Return the normalized path that we have completed
return (normalized);
}
/**
* Parse the character encoding from the specified content type header.
* If the content type is null, or there is no explicit character encoding,
* <code>null</code> is returned.
*
* @param contentType a content type header
*/
public static String parseCharacterEncoding(String contentType) {
if (contentType == null)
return (null);
int start = contentType.indexOf("charset=");
if (start < 0)
return (null);
String encoding = contentType.substring(start + 8);
int end = encoding.indexOf(';');
if (end >= 0)
encoding = encoding.substring(0, end);
encoding = encoding.trim();
if ((encoding.length() > 2) && (encoding.startsWith("\""))
&& (encoding.endsWith("\"")))
encoding = encoding.substring(1, encoding.length() - 1);
return (encoding.trim());
}
/**
* Parse a cookie header into an array of cookies according to RFC 2109.
*
* @param header Value of an HTTP "Cookie" header
*/
public static Cookie[] parseCookieHeader(String header) {
if ((header == null) || (header.length() < 1))
return (new Cookie[0]);
ArrayList cookies = new ArrayList();
while (header.length() > 0) {
int semicolon = header.indexOf(';');
if (semicolon < 0)
semicolon = header.length();
if (semicolon == 0)
break;
String token = header.substring(0, semicolon);
if (semicolon < header.length())
header = header.substring(semicolon + 1);
else
header = "";
try {
int equals = token.indexOf('=');
if (equals > 0) {
String name = URLDecode(token.substring(0, equals).trim());
String value = URLDecode(token.substring(equals+1).trim());
cookies.add(new Cookie(name, value));
}
} catch (Throwable e) {
;
}
}
return ((Cookie[]) cookies.toArray(new Cookie[cookies.size()]));
}
/**
* Append request parameters from the specified String to the specified
* Map. It is presumed that the specified Map is not accessed from any
* other thread, so no synchronization is performed.
* <p>
* <strong>IMPLEMENTATION NOTE</strong>: URL decoding is performed
* individually on the parsed name and value elements, rather than on
* the entire query string ahead of time, to properly deal with the case
* where the name or value includes an encoded "=" or "&" character
* that would otherwise be interpreted as a delimiter.
*
* @param map Map that accumulates the resulting parameters
* @param data Input string containing request parameters
* @param urlParameters true if we're parsing parameters on the URL
*
* @exception IllegalArgumentException if the data is malformed
*/
public static void parseParameters(Map map, String data, String encoding)
throws UnsupportedEncodingException {
if ((data != null) && (data.length() > 0)) {
int len = data.length();
byte[] bytes = new byte[len];
data.getBytes(0, len, bytes, 0);
parseParameters(map, bytes, encoding);
}
}
/**
* Decode and return the specified URL-encoded String.
* When the byte array is converted to a string, the system default
* character encoding is used... This may be different than some other
* servers.
*
* @param str The url-encoded string
*
* @exception IllegalArgumentException if a '%' character is not followed
* by a valid 2-digit hexadecimal number
*/
public static String URLDecode(String str) {
return URLDecode(str, null);
}
/**
* Decode and return the specified URL-encoded String.
*
* @param str The url-encoded string
* @param enc The encoding to use; if null, the default encoding is used
* @exception IllegalArgumentException if a '%' character is not followed
* by a valid 2-digit hexadecimal number
*/
public static String URLDecode(String str, String enc) {
if (str == null)
return (null);
int len = str.length();
byte[] bytes = new byte[len];
str.getBytes(0, len, bytes, 0);
return URLDecode(bytes, enc);
}
/**
* Decode and return the specified URL-encoded byte array.
*
* @param bytes The url-encoded byte array
* @exception IllegalArgumentException if a '%' character is not followed
* by a valid 2-digit hexadecimal number
*/
public static String URLDecode(byte[] bytes) {
return URLDecode(bytes, null);
}
/**
* Decode and return the specified URL-encoded byte array.
*
* @param bytes The url-encoded byte array
* @param enc The encoding to use; if null, the default encoding is used
* @exception IllegalArgumentException if a '%' character is not followed
* by a valid 2-digit hexadecimal number
*/
public static String URLDecode(byte[] bytes, String enc) {
if (bytes == null)
return (null);
int len = bytes.length;
int ix = 0;
int ox = 0;
while (ix < len) {
byte b = bytes[ix++]; // Get byte to test
if (b == '+') {
b = (byte)' ';
} else if (b == '%') {
b = (byte) ((convertHexDigit(bytes[ix++]) << 4)
+ convertHexDigit(bytes[ix++]));
}
bytes[ox++] = b;
}
if (enc != null) {
try {
return new String(bytes, 0, ox, enc);
} catch (Exception e) {
e.printStackTrace();
}
}
return new String(bytes, 0, ox);
}
/**
* Convert a byte character value to hexidecimal digit value.
*
* @param b the character value byte
*/
private static byte convertHexDigit( byte b ) {
if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
return 0;
}
/**
* Put name value pair in map.
*
* @param b the character value byte
*
* Put name and value pair in map. When name already exist, add value
* to array of values.
*/
private static void putMapEntry( Map map, String name, String value) {
String[] newValues = null;
String[] oldValues = (String[]) map.get(name);
if (oldValues == null) {
newValues = new String[1];
newValues[0] = value;
} else {
newValues = new String[oldValues.length + 1];
System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
newValues[oldValues.length] = value;
}
map.put(name, newValues);
}
/**
* Append request parameters from the specified String to the specified
* Map. It is presumed that the specified Map is not accessed from any
* other thread, so no synchronization is performed.
* <p>
* <strong>IMPLEMENTATION NOTE</strong>: URL decoding is performed
* individually on the parsed name and value elements, rather than on
* the entire query string ahead of time, to properly deal with the case
* where the name or value includes an encoded "=" or "&" character
* that would otherwise be interpreted as a delimiter.
*
* NOTE: byte array data is modified by this method. Caller beware.
*
* @param map Map that accumulates the resulting parameters
* @param data Input string containing request parameters
* @param encoding Encoding to use for converting hex
*
* @exception UnsupportedEncodingException if the data is malformed
*/
public static void parseParameters(Map map, byte[] data, String encoding)
throws UnsupportedEncodingException {
if (data != null && data.length > 0) {
int pos = 0;
int ix = 0;
int ox = 0;
String key = null;
String value = null;
while (ix < data.length) {
byte c = data[ix++];
switch ((char) c) {
case '&':
value = new String(data, 0, ox, encoding);
if (key != null) {
putMapEntry(map, key, value);
key = null;
}
ox = 0;
break;
case '=':
key = new String(data, 0, ox, encoding);
ox = 0;
break;
case '+':
data[ox++] = (byte)' ';
break;
case '%':
data[ox++] = (byte)((convertHexDigit(data[ix++]) << 4)
+ convertHexDigit(data[ix++]));
break;
default:
data[ox++] = c;
}
}
//The last value does not end in '&'. So save it now.
if (key != null) {
value = new String(data, 0, ox, encoding);
putMapEntry(map, key, value);
}
}
}
}
1.6 +1 -1 jakarta-commons-sandbox/messenger/src/webapp/conf/subscriptions.xml
Index: subscriptions.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/webapp/conf/subscriptions.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- subscriptions.xml 2001/10/26 14:27:26 1.5
+++ subscriptions.xml 2001/10/30 11:14:31 1.6
@@ -14,7 +14,7 @@
</subscription>
<subscription messenger="queue" destination="echo.jsp">
- <servlet>/jms/time.jsp</servlet>
+ <servlet>/jms/time.jsp?a=1&b=2</servlet>
</subscription>
</subscriptions>
1.2 +5 -5 jakarta-commons-sandbox/messenger/src/webapp/web/jms/time.jsp
Index: time.jsp
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/messenger/src/webapp/web/jms/time.jsp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- time.jsp 2001/10/26 11:52:17 1.1
+++ time.jsp 2001/10/30 11:14:31 1.2
@@ -1,5 +1,5 @@
-<%
- System.out.println( "Evaluating the time.jsp file at: " + new java.util.Date() );
-%>
-
-<time><%= new java.util.Date() %></time>
+<echo>
+ <time><%= new java.util.Date() %></time>
+ <a><%= request.getParameter( "a" )%></a>
+ <b><%= request.getParameter( "b" )%></b>
+</echo>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>