View Javadoc

1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.jetspeed.portal.portlets;
17  
18  import org.apache.ecs.ConcreteElement;
19  import org.apache.ecs.StringElement;
20  import org.apache.jetspeed.portal.portlets.AbstractPortlet;
21  import org.apache.turbine.util.RunData;
22  
23  import java.io.BufferedInputStream;
24  import java.io.ByteArrayOutputStream;
25  import java.io.InputStream;
26  import java.net.URL;
27  import java.net.URLConnection;
28  
29  
30  /***  
31   *   This portlet class is intended to be used for internal URLs that will 
32   *   not work properly if they are part of the same request as the Jetspeed/Turbine
33   *   controller servlet--Struts-mapped URLs are an example of these.
34   *   <br>
35   *   ServletProxyPortlet uses an application context-relative URL as an input parameter.  It uses data obtained from
36   *   <code>org.apache.turbine.util.RunData</code> to construct an absolute URL and append the session id to it. Using this
37   *   URL, it constructs a java.net.URL object, retrieves the content from it, and converts the content to a String.  Finally,
38   *   it returns an ECS StringElement created with this String for Jetspeed to render as a portlet.  Content is returned as-is;
39   *   no filtering is performed on the html before returning it.
40   *   <br/><br/>
41   *   This portlet accepts 3 parameters:<br/>
42   *
43   *   URL (required) 		  -- the web application-context relative URL (a query string may be used to pass parameters)<br/>
44   *   session_token (optional) -- token key used by the web server to pass the session id on the query string<br/>
45   *   protocol (optional)	  -- protocol to use to make the URL request
46   *
47   * @author <a href="mailto:joe.barefoot@motiva.com">Joe Barefoot</a>
48   */
49  
50  
51  public class ServletProxyPortlet extends AbstractPortlet
52  {
53      private final static int BUFFER_SIZE = 2048;
54  
55      /*** The name of the parameter to hold our application context-relative URL */
56      public static final String URL_PARAMETER_NAME = "URL";
57  	/*** The name of the parameter to hold the protocol to use (optional, default is http) **/
58  	public static final String PROTOCOL_PARAMETER_NAME = "protocol";
59  	/*** The name of the parameter to hold the token by which the session ID is passed on the query string (optional, default is jsessionid)
60  	 *  This is included to accomodate all web servers, as the token is usually different from one server to another.
61  	 */
62  	public static final String SESSION_TOKEN_PARAMETER_NAME = "session_token";
63  
64  	/*** The default protocol used to construct the URL -- http */
65  	public static final String DEFAULT_PROTOCOL = "http";
66  	/*** The default token to use to pass the session ID on the query String -- jsessionid */
67  	public static final String DEFAULT_SESSION_TOKEN = "jsessionid";
68  
69      /***  Gets content by proxy (java.net.URL) from an internal URL and returns it
70  	 *
71  	 * @param rundata The RunData object for the current request
72  	 * @return an ECS StringElement
73  	 */
74      public ConcreteElement getContent(RunData rundata)
75      {
76          String servletURL = processURL(rundata);
77  		if(servletURL == null)
78  		{
79  			return new StringElement("ServletInvokerPortlet:  Must specify a URL using the URL parameter");
80  		}
81          String content;
82  
83          //  This is probably not robust for large content returns, but should work okay within an application context with small amounts of content.
84          try
85          {
86  
87              URL url = new URL(servletURL);
88              URLConnection connection = url.openConnection();
89              InputStream stream = connection.getInputStream();
90              BufferedInputStream in = new BufferedInputStream(stream);
91              int length = 0;
92              byte[] buf = new byte[BUFFER_SIZE];
93              ByteArrayOutputStream out = new ByteArrayOutputStream();
94              while ((in != null) && ((length = in.read(buf)) != -1))
95              {
96                  // the data has already been read into buf
97                  out.write(buf, 0, length);
98              }
99              content = out.toString();
100             return new StringElement(content);
101         }
102         catch (Exception e)
103         {
104             String message = "ServletInvokerPortlet: Error invoking " + servletURL + ": " + e.getMessage();
105             return new StringElement(message);
106         }
107 
108     }
109 
110 	/***  Constructs a full URL to retrieve content from.  Override to append custom (default) query parameters, etc.
111 	 *
112 	 * @param rundata The RunData object for the current request
113 	 * @return  An absolute URL with the session ID appended
114 	 */
115     protected String processURL(RunData rundata)
116     {
117         String servletURL = getPortletConfig().getInitParameter(URL_PARAMETER_NAME);
118 		if( servletURL == null) // short-circuit
119 		{
120 			return null;
121 		}
122 		String protocol = getPortletConfig().getInitParameter(PROTOCOL_PARAMETER_NAME);
123 		if(protocol == null)
124 		{
125 			protocol = DEFAULT_PROTOCOL;
126 		}
127 		String token = getPortletConfig().getInitParameter(SESSION_TOKEN_PARAMETER_NAME);
128 		if(token == null)
129 		{
130 			token = DEFAULT_SESSION_TOKEN;
131 		}
132 
133 
134         String queryString = new String();
135         int queryIndex = servletURL.indexOf("?");
136         if(queryIndex > 0)
137         {
138             queryString = servletURL.substring(queryIndex);
139             servletURL = servletURL.substring(0, queryIndex);
140         }
141         servletURL = protocol + "://" + rundata.getServerName() + ":" + rundata.getServerPort() + rundata.getContextPath() + servletURL + ";" + token + "=" + rundata.getSession().getId() + queryString;
142         return servletURL;
143     }
144 
145 }