1/*2 * Copyright 2000-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 at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * 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 and14 * limitations under the License.15 */1617packageorg.apache.jetspeed.services.webpage;
1819// java.io20import java.io.IOException;
21import java.io.FileOutputStream;
22import java.io.InputStream;
23import java.io.ByteArrayOutputStream;
24import java.io.DataOutputStream;
2526// java.util27import java.util.Iterator;
28import java.util.Enumeration;
29import java.util.HashMap;
3031// javax.servlet32import javax.servlet.http.*;
3334// java.net35import java.net.URL;
36import java.net.URLConnection;
37import java.net.HttpURLConnection;
38import java.net.URLEncoder;
3940import org.apache.log4j.Logger;
4142/*43 * Abstract Base class for web page sessions.44 * Implements the primary dispatcher logic for getting and posting resources.45 *46 */4748publicabstractclassAbstractSiteSession implements SiteSession49 {
5051// the base url of the host being proxied52protected String targetBase;
5354// the base url the wps55protected String proxyBase;
5657// the cookies collection58protected HashMap cookies = new HashMap();
5960// counters61protectedint hitCount = 0;
62protectedint cacheCount = 0;
6364// the log file singleton instance65static Logger log = Logger.getLogger(AbstractSiteSession.class);
6667/***68 * Create a NetElementSession, which maintains sessions with one network element.69 * 70 * @param targetBase the target host's base URL71 * @param proxyBase the proxy server host URL base address. 72 */73publicAbstractSiteSession(String targetBase, String proxyBase)
74 {
75this.proxyBase = proxyBase;
76this.targetBase = targetBase;
77 }
7879/***80 * Given a URL, returns the content from that URL in a string. 81 * All HTTP hyperlinks(HREFs) are rewritten as proxied-referenced hyperlinks.82 * All relative references to web resources (images, stylesheets, ...) are 83 * rewritten as absolute references, but are not proxied.84 * Determines if we are logged on to the target site. If not,85 * calls logon(), which is a implementation specific 'POST' exchange86 *87 * @see logon(String, HttpServletRequest, HttpServletResponse) 88 *89 * @param url the proxied resource address.90 * @param data the rundata91 *92 * @exception IOException a servlet exception.93 */9495publicvoid dispatch(String url, ProxyRunData data)
96 throws IOException
97 {
98try99 {
100Configuration config = Configuration.getInstance();
101102 log.debug("=== Dispatching =" + url);
103104// open a pooled HTTP connection105//URL u = new URL(url);106 URL u = new URL(null, url, new sun.net.www.protocol.http.Handler() );
107 HttpURLConnection con = (HttpURLConnection)u.openConnection();
108109//if (con instanceof HttpURLConnection) 110 con.setDoInput(true);
111 con.setDoOutput(true);
112 con.setAllowUserInteraction(false);
113 con.setFollowRedirects(false);
114115if (data.getPosting()) {
116 con.setRequestMethod("POST");
117 }
118119// are there any cookies in our current session?120if (cookies.isEmpty())
121 {
122// there are no cookies, must be a new session, so lets logon123 log.debug("... no session id provided. Logging on...");
124125if (false == logon(data))
126return;
127128 }
129130// send the cookies (session ids) back to the NE131 Iterator it = cookies.values().iterator();
132 Cookie cookie;
133while (it.hasNext()) {
134 cookie = (Cookie)it.next();
135 String sessionID = WebPageHelper.buildCookieString(cookie);
136 con.setRequestProperty("Cookie", sessionID);
137 log.debug("... Sending Session ID: " + sessionID );
138 }
139140// we have to get the post parameters from the servlet container,141// and then re-encode them. i wish i could find out how to keep142// the servlet container from reading them, because now i have to143// parse them out, and then re-encode144if (data.getPosting()) {
145146// get the post params 147 StringBuffer postParams = new StringBuffer();
148int count = 0;
149 Enumeration e = data.getRequest().getParameterNames();
150while (e.hasMoreElements())
151 {
152153 String name = (String) e.nextElement();
154if (name.equals(config.getSID()) ||
155 name.equals(config.getURL())) {
156continue;
157 }
158159 String values[] = data.getRequest().getParameterValues(name);
160if (values != null)
161 {
162for (int i = 0; i < values.length; i++) {
163if (count > 0) {
164 postParams.append("&");
165 }
166 postParams.append(name);
167 postParams.append("=");
168 postParams.append(URLEncoder.encode(values[i]));
169 count++;
170 }
171 }
172 }
173 String postString = postParams.toString();
174 con.setRequestProperty("Content-length", String.valueOf(postString.length()) );
175// write directly to the output stream 176 DataOutputStream dos = new DataOutputStream(con.getOutputStream());
177178 log.debug("... POST: " + postString);
179 dos.writeBytes(postString);
180 dos.close();
181 }
182183int rc = con.getResponseCode();
184185// Get the Session Information from Headers186int contentType = WebPageHelper.getContentType(con.getHeaderField("content-type"), u.toString());
187 String location = con.getHeaderField("Location");
188189if ((rc == con.HTTP_MOVED_PERM || rc == con.HTTP_MOVED_TEMP) && null != location)
190 {
191 log.debug("+++ REDIRECT = " + location);
192 location = WebPageHelper.concatURLs(targetBase, location);
193 dispatch(location , data);
194return;
195 }
196197// get cookies set from server198 String cookieString = con.getHeaderField("Set-Cookie");
199if (null != cookieString)
200 {
201 log.debug("... new SessionID found: " + cookieString);
202 WebPageHelper.parseCookies(cookieString, this);
203 }
204205if (contentType == WebPageHelper.CT_IMAGE ||
206 contentType == WebPageHelper.CT_BINARY ||
207 contentType == WebPageHelper.CT_APPLICATION) {
208// wasn't in the cache, get it from host209 getBinaryContent(con, data.getResponse());
210return;
211 }
212213 rewriteContent(data, con, contentType, url);
214215 }
216catch (IOException ex)
217 {
218 log.error("*** PROXY DISPATCH EXCEPTION = " + ex);
219throw ex;
220 }
221222 }
223224/***225 * Gets the HTML content from the URL Connection stream and returns it226 * in a string227 *228 * @param con The URLConnection to read from.229 * @param resource The full URL of the resource.230 * @return The HTML Content from the stream.231 *232 * @exception IOException a servlet exception.233 */234public String getHTMLContent(URLConnection con,
235ProxyRunData data,
236 String resource) throws IOException
237 {
238239int CAPACITY = 4096;
240241 InputStream is = con.getInputStream();
242 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
243244Configuration config = Configuration.getInstance();
245 FileOutputStream fos = null;
246boolean logging = config.getEnableContentLog();
247if (logging)
248 {
249if (data != null)
250 {
251 String fileName = data.getServlet().getServletContext().getRealPath(
252 config.getLogLocation() );
253 fos = new FileOutputStream(fileName, true);
254 WebPageHelper.writeHeader(fos, resource);
255 }
256 }
257258//now process the InputStream...259260 byte[] bytes = new byte[CAPACITY];
261262int readCount = 0;
263int total = 0;
264265while( ( readCount = is.read( bytes )) > 0 )
266 {
267 buffer.write( bytes, 0, readCount);
268if (logging)
269 {
270 fos.write( bytes, 0, readCount);
271 }
272 total += readCount;
273 }
274if (logging)
275 {
276 fos.close();
277 }
278 is.close();
279280return buffer.toString();
281 }
282283/***284 * Gets the HTML content from the URL Connection stream and writes it to respones285 *286 * @param con The URLConnection to read from.287 *288 * @exception IOException a servlet exception.289 */290publicvoid getBinaryContent(URLConnection con,
291 HttpServletResponse response) throws IOException
292 {
293294int CAPACITY = 4096;
295296297 InputStream is = con.getInputStream();
298299// FileOutputStream fos = new FileOutputStream("/test.fw", true);300301//now process the InputStream...302303 byte[] bytes = new byte[CAPACITY];
304305int readCount = 0;
306while( ( readCount = is.read( bytes )) > 0 ) {
307308 response.getOutputStream().write(bytes, 0, readCount);
309//fos.write( bytes, 0, readCount);310 }
311312//fos.close();313 is.close();
314315 }
316317/***318 * Given a cookie, it first checks to see if that cookie is already319 * managed in this session. If it is, it means that the session has320 * timed out and that the network element has now created a new session.321 * In that case, replace the cookie, and re-establish the session (logon)322 * If its a new cookie, we will still need to logon, and and the cookie to323 * the managed cookies collection for this session.324 *325 * @param cookie new cookie returned from target server.326 * @return true when a new cookie added, false when updated.327 *328 */329publicboolean addCookieToSession(Cookie cookie)
330 {
331boolean added = (null == cookies.get(cookie.getName()));
332 cookies.put(cookie.getName(), cookie); // adds or updates 333return added;
334 }
335336/*337 * Gets the hitcount for this session.338 *339 * @return the hitcount for this session.340 */341publicint getHitCount()
342 {
343return hitCount;
344 }
345346/*347 * Increments the hitcount for this session.348 *349 */350publicvoid incHitCount()
351 {
352 hitCount++;
353 }
354355/*356 * Gets the cache count for this session.357 *358 * @return the cache count for this session.359 */360publicint getCacheCount()
361 {
362return cacheCount;
363 }
364365/*366 * Increments the hitcount for this session.367 *368 */369publicvoid incCacheCount()
370 {
371 cacheCount++;
372 }
373374375 }
376