001: /**
002: * $Id: Compressor.java,v 1.12 2005/09/21 10:52:13 dg154973 Exp $
003: * Copyright 2003 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and iPlanet
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.wireless.taglibs.dispatcher;
014:
015: /**
016: * This class implements a per-session URL (de)compression facility.
017: * <p>Typical usage will look something like:
018: * <ul>
019: * <li>A Compressor object will be created and associated with
020: * a SSOToken using the <i>getCompressor()</i> method.
021: * <li>A URL will be passed to the <i>compressURL()</i> method. This
022: * method will produce a unique identifier for that URL and will
023: * cache an appropriate association within the Compressor object.
024: * The identifier will be combined, as a parameter, with a URL
025: * that references a dispatch servlet.
026: * <li>When a request is received by the dispatch servlet, the
027: * URL identifier is retrieved, and the uncompressed URL is
028: * retrieved from the cache using the <i>retrieveURL()</i> method.
029: * The dispatch servlet presumably forwards to this URL.
030: * </ul>
031: * <p>The Compressor class is configured by the following properties
032: * from the MAConfigProperties class:
033: * <ul>
034: * <li><b>ma.dispatch.servlet.name</b>: The name of the dispatch servlet that
035: * will be referenced by URL generated by <i>compressURL()</i>. Defaults
036: * to "ma".
037: * <li><b>ma.dispatch.parm.name</b>: The name of the parameter that will
038: * contain the URL identifier in the URL generated by the <i>compressURL()</i>
039: * method. Defaults to "uI".
040: * <li><b>ma.dispatch.error.page</b>: If anything goes wrong during a call
041: * to <i>retrieveURL()</i>, the URL defined by this property will be
042: * returned. Defaults to "/jsp/default/errorpage.jsp".
043: * <li><b>ma.compressor.max.url</b>: Defines the maximum number of URLs
044: * that a Compressor object may cache. Defaults to 4096.
045: * <li><b>ma.compressor.enable</b>: If true, the <i>compressURL()</i> method
046: * will compress the URL, otherwise, it will return the original URL.
047: * Defaults to true.
048: * </ul>
049: */
050: import java.util.*;
051: import java.util.logging.Logger;
052: import java.util.logging.Level;
053: import javax.servlet.jsp.*;
054: import javax.servlet.http.*;
055:
056: import com.iplanet.sso.*;
057: import com.sun.portal.wireless.util.*;
058: import com.sun.portal.wireless.taglibs.base.Util;
059: import com.sun.portal.log.common.PortalLogger;
060:
061: public class Compressor {
062:
063: // Create a logger for this class
064: private static Logger debugLogger = PortalLogger
065: .getLogger(Compressor.class);
066:
067: private static HashMap compressorCache = new HashMap(100);
068: private static String dispatchServletName;
069: private static String dispatchParmName;
070: private static String dispatchErrorPage;
071: private static boolean compressorEnable;
072: private static int maxUrlCount;
073:
074: private HashMap urlToNumberCache;
075: private HashMap numberToUrlCache;
076: private SSOToken token = null;
077: private int urlCounter = 0;
078: private int cacheCounter = 0;
079:
080: static {
081: dispatchServletName = MAConfigProperties.get(
082: "ma.dispatch.servlet.name", "ma");
083: dispatchParmName = MAConfigProperties.get(
084: "ma.dispatch.parm.name", "uI");
085: dispatchErrorPage = MAConfigProperties.get(
086: "ma.dispatch.error.page", "/jsp/default/errorpage.jsp");
087: try {
088: maxUrlCount = Integer.parseInt(MAConfigProperties.get(
089: "ma.compressor.max.url", "4096"));
090: } catch (Exception e) {
091: maxUrlCount = 4096;
092: }
093: String compressorEnableString = MAConfigProperties.get(
094: "ma.compressor.enable", "true");
095: compressorEnable = Boolean.valueOf(compressorEnableString)
096: .booleanValue();
097: }
098:
099: private Compressor(SSOToken ssoToken) {
100: urlToNumberCache = new HashMap(100);
101: numberToUrlCache = new HashMap(100);
102: token = ssoToken;
103: }
104:
105: /**
106: * Returns a Compressor object associated with the specified SSOToken.
107: *
108: * @param ssoToken
109: * @return Compressor
110: */
111: static public Compressor getCompressor(SSOToken ssoToken) {
112: SSOTokenID tokenID = ssoToken.getTokenID();
113: String hashKey = tokenID.toString();
114: Compressor compressor;
115:
116: synchronized (compressorCache) {
117: compressor = (Compressor) compressorCache.get(hashKey);
118: if (compressor == null) {
119: compressor = new Compressor(ssoToken);
120: compressorCache.put(hashKey, compressor);
121: CompressorReaper reaper = new CompressorReaper(hashKey,
122: compressorCache);
123: try {
124: ssoToken.addSSOTokenListener(reaper);
125: } catch (Exception e) {
126: }
127: }
128: }
129: return compressor;
130: }
131:
132: /**
133: * Returns a compressed URL.
134: * <p>The URL formed by this method is of the form:
135: * <preformat>
136: * /<ma.dispatch.servlet.name>?<ma.dispatch.parm.name>=<2-digit-cache-defeat><4-digit-url-number>
137: * </preformat>
138: * <p>The URL is web app relative.
139: *
140: * @param urlString
141: * @return String
142: */
143: public String compressURL(String urlString) {
144: String urlNumber;
145:
146: if (!compressorEnable) {
147: StringBuffer result = new StringBuffer(128);
148: result.append("/").append(dispatchServletName).append("?");
149: int paramIndex = urlString.indexOf("?");
150: if (paramIndex != -1) {
151: String target = urlString.substring(0, paramIndex);
152: String targetParams = urlString
153: .substring(paramIndex + 1);
154: result.append(targetParams).append("&target=")
155: .append(target);
156: } else {
157: result.append("target=").append(urlString);
158: }
159: return result.toString();
160: }
161:
162: synchronized (urlToNumberCache) {
163: urlNumber = (String) urlToNumberCache.get(urlString);
164: if (urlNumber == null) {
165: urlNumber = getUrlCounterString();
166: String oldUrlString = (String) numberToUrlCache
167: .get(urlNumber);
168: if (oldUrlString != null) {
169: urlToNumberCache.remove(oldUrlString);
170: }
171: urlToNumberCache.put(urlString, urlNumber);
172: numberToUrlCache.put(urlNumber, urlString);
173: }
174: }
175: return "/" + dispatchServletName + "?" + dispatchParmName + "="
176: + getCacheCounterString() + urlNumber;
177: }
178:
179: public static String getDispatcherServletName() {
180: return (dispatchServletName);
181: }
182:
183: /**
184: * Returns the URL referenced by the identifier defined by the parameter
185: * contained within the request.
186: *
187: * @param request
188: * @return String
189: */
190: public String retrieveURL(HttpServletRequest request) {
191: String urlString;
192: String urlNumber = request.getParameter(dispatchParmName);
193:
194: if (urlNumber == null) {
195: debugLogger.log(Level.FINE, "PSMA_CSPWTD0001",
196: dispatchParmName);
197: return dispatchErrorPage;
198: }
199:
200: urlNumber = urlNumber.substring(2);
201: synchronized (urlToNumberCache) {
202: urlString = (String) numberToUrlCache.get(urlNumber);
203: }
204:
205: if (urlString == null) {
206: debugLogger.fine("PSMA_CSPWTD0002");
207: urlString = dispatchErrorPage;
208: }
209:
210: return urlString;
211: }
212:
213: /**
214: * Indicates whether or not compression is enabled.
215: *
216: * @return boolean
217: */
218: public boolean isCompressionEnabled() {
219: return compressorEnable;
220: }
221:
222: /**
223: * generate 4 digit hex url counter...
224: *
225: * @return hex counter value.
226: */
227: private String getUrlCounterString() {
228: String count = Integer.toHexString(urlCounter++ % maxUrlCount);
229: switch (count.length()) {
230: case 4:
231: return count;
232: case 3:
233: return "0" + count;
234: case 2:
235: return "00" + count;
236: case 1:
237: return "000" + count;
238: default:
239: return count;
240: }
241: }
242:
243: /**
244: * generate 2 digit hex url counter...
245: *
246: * @return hex counter value.
247: */
248: private String getCacheCounterString() {
249: String count = Integer.toHexString(cacheCounter++ % 256);
250: switch (count.length()) {
251: case 2:
252: return count;
253: case 1:
254: return "0" + count;
255: default:
256: return count;
257: }
258: }
259:
260: }
|