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;
2122// java.util23import java.util.Collection;
24import java.util.Iterator;
2526// javax.servlet27import javax.servlet.ServletException;
28import javax.servlet.ServletConfig;
29import javax.servlet.http.HttpServlet;
30import javax.servlet.http.HttpSession;
31import javax.servlet.http.HttpServletRequest;
32import javax.servlet.http.HttpServletResponse;
3334// java.net35import java.net.URL;
36import java.util.HashMap;
37import java.net.MalformedURLException;
3839import org.apache.log4j.Logger;
4041/***42 *43 * <p>This is the default implementation of the <code>WebPageService</code> interface.</p>44 *45 * <p>46 * It is a service that provides Web Page facade and delegation47 * services for clients to transparently access resources existing on web48 * pages from requests originating from the portal server.</p>49 *50 * <p>Since the WebPage service is giving the appearance of a single session to 51 * the client, the service needs to manage the synchronization of sessions,52 * including single-sign-on, and security authorization permissions between the53 * the portal server and one or more sites.</p> 54 *55 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>56 * @version $Id: JetspeedWebPageService.java,v 1.4 2004/02/23 03:46:26 jford Exp $ 57 */5859publicclassJetspeedWebPageService60 implements WebPageService61 {
62// the session keys used to store network element proxy sessions63publicfinalstatic String SESSION_MAP = "wps.SessionMap";
64publicfinalstatic String URL_SESSION_MAP = "wps.URLSessionMap";
6566publicfinalstatic String INIT_PROPERTIES_PARAM = "properties";
6768/***69 * service state70 *71 */7273// the name of the host that this server is running on74private String host = null;
7576// cache of sites cached and managed by the Proxy.77// objects are of type org.apache.jetspeed.services.httpProxy.Site78private HashMap sites = new HashMap();
7980// active sessions that the Proxy is working with81// the objects are of type org.apache.jetspeed.services.httpProxy.SessionMap82// this cache is updated on servlet unbound events83private HashMap sessions = new HashMap();
8485// has this service been initialized yet86privateboolean init = false;
8788// the log file singleton instance89static Logger log = Logger.getLogger(JetspeedWebPageService.class);
9091// last error92private String lastError = "Jetspeed WebPage Service has not been initialized.";
9394/***95 * The primary method invoked when the a Jetspeed GET is executed.96 *97 * @param servlet the Servlet. 98 * @param request Servlet request.99 * @param response Servlet response.100 * @exception IOException a servlet exception.101 * @exception ServletException a servlet exception.102 */103publicvoid get(HttpServlet servlet,
104 HttpServletRequest request,
105 HttpServletResponse response)
106 throws ServletException, IOException
107 {
108ProxyRunData rundata = newProxyRunData(servlet, request, response, false);
109 dispatch(rundata);
110 }
111112/***113 * The primary method invoked when the a Jetspeed POST is executed.114 *115 * @param servlet the Servlet. 116 * @param request Servlet request.117 * @param response Servlet response.118 * @exception IOException a servlet exception.119 * @exception ServletException a servlet exception.120 */121publicvoid post(HttpServlet servlet,
122 HttpServletRequest request,
123 HttpServletResponse response)
124 throws ServletException, IOException
125 {
126ProxyRunData rundata = newProxyRunData(servlet, request, response, true);
127 dispatch(rundata);
128 }
129130131/***132 * The common dispatcher for both GETs and PUTs133 *134 * @param data the request specific state.135 * @exception IOException a servlet exception.136 * @exception ServletException a servlet exception.137 */138privatevoid dispatch(ProxyRunData data)
139 throws ServletException, IOException
140 {
141// Turn this on for Debugging142//HttpProxyDebug.snoopParams(data.getRequest(), System.err);143//HttpProxyDebug.snoopHeaders(data.getRequest(), System.err); 144145// get the proxy host for this server146 getHost(data.getRequest());
147148//149// get the full Network Element IP and Resource parameters from request150//151Configuration config = Configuration.getInstance();
152 String sid = data.getRequest().getParameter(config.getSID());
153 String url = data.getRequest().getParameter(config.getURL());
154155if (null == sid)
156 {
157if (null == url)
158 {
159thrownew ServletException("Bad Request. No proxy-parameters passed in request.");
160 }
161 proxyByURL(url, data);
162return;
163 }
164165// 166// found the proxy query parameter denoting proxy-by-network-element-id167//168169// maps a Site unique id to a Site object170Site site = getSite(sid);
171if (null == site)
172 {
173// logon failed, return error screen here:174thrownew ServletException("The Requested Site ID is currently not configured on this system: " + sid);
175 }
176177// 178// check the status of the site179// if it isn't online, exit out with exception180// 181if (site.getStatus() != Configuration.STATUS_ONLINE)
182 {
183thrownew ServletException("The Requested Site ("184 + site.getURL()
185 + ") is not available. Status = "186 + WebPageHelper.getAvailabilityStatus(site.getStatus()) );
187 }
188189// 190// get the path to the requested resource191//192 String resource = getResourcePath(site.getURL(), data.getRequest());
193194boolean loggedOn = true;
195196197// get the ession Map for this Portal Session198// we get the session with 'false' since we don't want to create a new199// session. The session should be already created 200 HttpSession session = data.getRequest().getSession(false);
201if (null == session)
202 {
203 session = data.getRequest().getSession(true);
204 }
205206// 207// look up the session map from the current servlet session208//209 String sessionID = session.getId();
210SessionMap smap = (SessionMap)sessions.get(sessionID);
211SiteSession jss = null;
212if (null == smap)
213 {
214// get the user from the session215/*216 User user = (User)session.getAttribute(config.getUserSessionKey());217 String username;218 if (user != null)219 {220 username = user.getUserName();221 }222 */223// it wasn't found, create a new map 224 String username = "";
225 smap = newSessionMap(sessionID, username);
226227228// add the map to the servlet session for callbacks on unbound229 session.setAttribute(SESSION_MAP, smap);
230// add the map to my collection of sessions231 sessions.put(sessionID, smap);
232233// and create the network element session234 jss = newJetspeedSiteSession(site, this.host, username);
235236// and then put the session into the network element map237 smap.put(site.getURL(), jss);
238239// always logon when creating a new session240 loggedOn = jss.logon(data);
241242 } else243 {
244// found the session map, lets get the session245 jss = (JetspeedSiteSession)smap.get(site.getURL());
246if (null == jss)
247 {
248// get the user from the session249/*250 User user = (User)session.getAttribute(config.getUserSessionKey());251 String username;252 if (user != null) 253 {254 username = user.getUserName();255 }256 */257258// no session exists, so create one259 String username = "";
260 jss = newJetspeedSiteSession(site, this.host, username);
261 smap.put(site.getURL(), jss);
262263// and then always logon when creating a new ne session 264 loggedOn = jss.logon(data);
265 }
266 }
267if (loggedOn)
268 {
269// debug TODO: remove this eventually270if (data.getRequest().getParameter("logon-test") != null)
271return;
272273if (WebPageCache.isCacheableResource(resource))
274 {
275if (WebPageCache.getResourceFromCache(resource, site.getID(), site.getURL(), this.host, data))
276 {
277 smap.incCacheCount();
278 jss.incCacheCount();
279 }
280else281 {
282 smap.incHitCount();
283 jss.incHitCount();
284 }
285return;
286 }
287288 smap.incHitCount();
289 jss.incHitCount();
290 jss.proxy(resource, data);
291 }
292 }
293294/***295 * Builds the proxy url which is used when rewriting other URLs296 * 297 *298 * @param req Servlet request.299 */300privatevoid getHost(HttpServletRequest request)
301 {
302// TODO: try to get this to work! 303// URL.setURLStreamHandlerFactory(new sun.net.www.protocol.http.handler( );304305if (null != this.host)
306return;
307308 StringBuffer root = new StringBuffer();
309 String scheme = request.getScheme();
310 root.append(scheme);
311 root.append( "://");
312int port = request.getServerPort();
313314 String hostname = request.getServerName();
315 String ip = WebPageHelper.getIP(hostname);
316if (null == ip)
317 root.append(hostname);
318else319 root.append(ip);
320321if ( (port > 0) &&
322 ((scheme.equals("http") && port != 80) ||
323 (scheme.equals("https") && port != 443)
324 )
325 )
326 {
327 root.append(":");
328 root.append(port);
329 }
330 root.append( request.getServletPath() );
331this.host = root.toString();
332 }
333334/***335 * Given a Site id, maps to base URL for that site and returns the Site object336 * 337 *338 * @param sid the string Site ID339 * @return the Site object.340 */341publicSite getSite(String sid) throws ServletException
342 {
343return(Site)sites.get(sid);
344 }
345346/***347 * Creates the full path the requested resource on the site from a relative path in request.348 *349 * @param url the base url for the site.350 * @param request the Servlet request.351 * @return the full path to the resource.352 */353public String getResourcePath(String url, HttpServletRequest request)
354 {
355 String path = request.getParameter(Configuration.getInstance().getPath());
356if (path == null)
357return"";
358359 String fullPath = WebPageHelper.concatURLs(url, path);
360361return fullPath.replace('@', '&');
362 }
363364365/***366 * Given a URL, begin a Jetspeed session with that host367 * It is here for future use.368 *369 * @param url the URL of the host to proxy.370 * @param data the runData371 * @return a new session372 */373privateSiteSession proxyByURL(String url,
374ProxyRunData data)
375 throws ServletException, IOException
376 {
377 String newURL = url.replace('@', '&');
378 String base = getTargetBase(newURL);
379380// get the Session Map for this session381// we get the session with 'false' since we don't want to create a new382// session. The session should be already created 383 HttpSession session = data.getRequest().getSession(false);
384if (null == session)
385 {
386 session = data.getRequest().getSession(true);
387 }
388389 String sessionID = session.getId();
390SessionMap smap = (SessionMap)sessions.get(sessionID);
391392SiteSession pxSession = null;
393if (null == smap)
394 {
395// create the map 396 smap = newSessionMap(sessionID, "NA"); // username not relevant....397398 session.setAttribute(URL_SESSION_MAP, smap);
399 sessions.put(sessionID, smap);
400401Site site = newSecuredSite(base, base);
402 pxSession = newJetspeedSiteSession(site, base, this.host);
403 smap.put(base, pxSession); // map(targetBaseHostName, Session)404 }
405else406 {
407 pxSession = (JetspeedSiteSession)smap.get(base);
408if (null == pxSession)
409 {
410Site site = newSecuredSite(base, base);
411 pxSession = newJetspeedSiteSession(site, base, this.host);
412 smap.put(base, pxSession); // map(targetBaseHostName, Session)413 }
414 }
415416if (WebPageCache.isCacheableResource(newURL))
417 {
418419if (WebPageCache.getResourceFromCache(newURL, -1, base, this.host, data))
420 {
421 smap.incCacheCount();
422 pxSession.incCacheCount();
423 }
424else425 {
426 smap.incHitCount();
427 pxSession.incHitCount();
428 }
429return (JetspeedSiteSession)pxSession;
430 }
431432 smap.incHitCount();
433 pxSession.incHitCount();
434 pxSession.proxy(newURL, data);
435return(JetspeedSiteSession)pxSession;
436 }
437438/***439 * Maps a full URL path to a resource to a base path440 * given: http://localhost:8080/jetspeed/search/index.html441 * returns: http://localhost:8080/jetspeed/442 *443 * @param url the full URL of the resource.444 * @return the base host application string445 */446public String getTargetBase(String url) throws ServletException
447 {
448try449 {
450 URL u = new URL(url);
451 StringBuffer base = new StringBuffer();
452 String protocol = u.getProtocol();
453 base.append(protocol);
454 base.append( "://");
455int port = u.getPort();
456 base.append(u.getHost());
457if ( (port > 0) &&
458 ((protocol.equals("http") && port != 80) ||
459 (protocol.equals("https") && port != 443)
460 )
461 )
462 {
463 base.append(":");
464 base.append(port);
465 }
466467// we need to separate the filename from the resource, since468// URL.getPath() and .getFile() return the same string469 String path = u.getFile();
470471if (null != path)
472 {
473474int dot = path.lastIndexOf('.');
475int slash = path.lastIndexOf('/');
476if (dot > slash && slash != -1)
477 { // its a file478 path = path.substring(0, slash);
479 }
480// 481482 base.append(path);
483484if ('/' != base.charAt(base.length()-1))
485 base.append('/');
486 } else487 base.append("/");
488489return base.toString();
490 } catch (MalformedURLException e)
491 {
492thrownew ServletException(e.toString());
493 }
494 }
495496497/***498 * One time initialization of the proxy service499 *500 * @param config the servlet configuration. 501 * @exception IOException a servlet exception.502 * @exception ServletException a servlet exception.503 */504publicboolean init(ServletConfig config)
505 throws ServletException, IOException
506 {
507508 String paramFile = config.getInitParameter(INIT_PROPERTIES_PARAM);
509if (null == paramFile)
510 {
511 lastError = "Jetspeed HTTP Proxy Init Property Not Found:" + INIT_PROPERTIES_PARAM;
512 log.error(lastError);
513return false;
514 }
515516 String fullPath = config.getServletContext().getRealPath(paramFile);
517518Configuration pc = Configuration.getInitialInstance(fullPath);
519if (null == pc)
520 {
521return false;
522 }
523524 lastError = "";
525 init = true;
526returntrue;
527 }
528529/***530 * Returns true if the service was initialized successfully.531 *532 * @retun true if the service was initialized successfully.533 */534publicboolean isInit()
535 {
536return init;
537 }
538539/***540 * One time de-initialization of the proxy service541 *542 */543publicvoid destroy()
544 {
545try546 {
547//548// first logout of all Network Element Sessions549//550 Iterator it = sessions.values().iterator();
551while (it.hasNext())
552 {
553SessionMap map = (SessionMap)it.next();
554 Iterator itElements = map.values().iterator();
555while (itElements.hasNext())
556 {
557SiteSession has = (SiteSession)itElements.next();
558try559 {
560 has.logout(null);
561 }
562catch (Exception e)
563 {
564// continue logging out even if one fails565 log.error("Shutdown-Logout of Session: " + e);
566 }
567 }
568 }
569570 } catch ( Exception ex )
571 {
572 log.error( ex );
573 }
574 }
575576/***577 * Returns a snapshot collection of all the active and inactive sessions.578 *579 * @return the collection of sessions.580 */581public Collection getSessions()
582 {
583return sessions.values();
584 }
585586/***587 * Returns a session, give a string id key identifying that session.588 *589 * @param id The ID of the session.590 * @return The corresponding session.591 */592publicSessionMap getSession(String id)
593 {
594return (SessionMap)sessions.get(id);
595 }
596597/***598 * Returns a snapshot collection of all the managed sites in the system.599 *600 * @return the collection of sites.601 */602public Collection getSites()
603 {
604return sites.values();
605 }
606607608/***609 * Returns the error string from failed initialized.610 *611 * @return the error string from last error.612 */613public String getErrorString()
614 {
615return lastError;
616 }
617618619 }
620621622623624