001: /**
002: * Copyright 2003 Sun Microsystems, Inc. All
003: * rights reserved. Use of this product is subject
004: * to license terms. Federal Acquisitions:
005: * Commercial Software -- Government Users
006: * Subject to Standard License Terms and
007: * Conditions.
008: *
009: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
010: * are trademarks or registered trademarks of Sun Microsystems,
011: * Inc. in the United States and other countries.
012: */package com.sun.portal.wsrp.consumer.common;
013:
014: import java.util.*;
015: import java.util.logging.Level;
016: import java.util.logging.Logger;
017:
018: import com.sun.portal.container.*;
019: import com.sun.portal.wsrp.common.*;
020: import com.sun.portal.wsrp.common.*;
021: import com.sun.portal.wsrp.consumer.common.*;
022: import com.sun.portal.wsrp.common.stubs.*;
023: import com.sun.portal.log.common.PortalLogger;
024:
025: import javax.servlet.http.HttpServletRequest;
026:
027: import java.net.*;
028:
029: /**
030: * This class rewrites all URLs in the content sent by the producer
031: * using rules listed in the 10.2 section of the WSRP spec and
032: * information provided in its constructor. It is used by both the
033: * Markup Manager and the ResourceProxyServlet servlet.
034: */
035: //
036: // secure thing
037: // fragment
038: // test recursive resource rewriting
039: // javadoc
040: // use namespace
041: // use cookie thing
042: //
043:
044: public class WSRPConsumerRewriter {
045:
046: //
047: // These keys are put by the consumer
048: // for proxy servlet to pick
049: //
050:
051: public static String PROXY_SERVLET_MAPPING = "/wsrpconsumer/resourceproxy";
052: public static final String PROXY_RESOURCE_URL = "wsrp_url";
053: public static final String PROXY_RESOURCE_REWRITE = "wsrp_rewrite";
054: public static final String PROXY_COOKIE_KEY = "cookie_key";
055: public static final String PROXY_PORTAL_SERVER_URL = "portal_server_url";
056: public static final String PROXY_NAMESPACE = "namespace";
057:
058: //
059: //
060: //
061: private ChannelURLFactory _channelURLFactory;
062: private String _portalServerURLPrefix;
063: private String _cookieKey;
064: private String _namespace;
065:
066: private static Logger logger = PortalLogger
067: .getLogger(WSRPConsumerRewriter.class);
068:
069: /**
070: * Constructor (used by MarkupManager)
071: * @param channelURLFactory Factory that would help create render/action urls.
072: * @param portalServerURLPrefix Pure prefix to the portal
073: * @param cookieKey Key that ProducerSessionManager used to store the markup stub.
074: * @param namespace Unique namespace to be used to replace wsrp_rewrite_
075: */
076: public WSRPConsumerRewriter(ChannelURLFactory channelURLFactory,
077: String portalServerURLPrefix, String cookieKey,
078: String namespace) {
079:
080: _channelURLFactory = channelURLFactory;
081: _portalServerURLPrefix = portalServerURLPrefix;
082: _cookieKey = cookieKey;
083: _namespace = namespace;
084:
085: }
086:
087: /**
088: * Constructor (used by ResourceProxyServlet)
089: * @param portalServerURLPrefix Pure prefix to the portal
090: * @param cookieKey Key that ProducerSessionManager used to store the markup stub.
091: * @param namespace Unique namespace to be used to replace wsrp_rewrite_
092: */
093: public WSRPConsumerRewriter(String portalServerURLPrefix,
094: String cookieKey, String namespace) {
095:
096: _portalServerURLPrefix = portalServerURLPrefix;
097: _cookieKey = cookieKey;
098: _namespace = namespace;
099: }
100:
101: /**
102: * The main method that is called to rewrite the contents.
103: *
104: * @param content
105: * @return rewritten content
106: */
107: public String rewrite(String content, HttpServletRequest request)
108: throws WSRPConsumerRewriterException {
109:
110: int currentStart = 0;
111: int endTokenPosition = 0;
112: int beginTokenPosition = 0;
113: StringBuffer buffer = new StringBuffer(content.length() + 100);
114:
115: //_debug.debugMessage("ORIGINAL CONTENT:");
116: //_debug.debugMessage(content);
117:
118: if (logger.isLoggable(Level.FINEST))
119: logger.log(Level.FINEST, "PSWS_CSPWCC0002");
120:
121: //
122: // Goal is to replace anthing starting with wsrp_rewrite_
123: // or strings enclosed in wsrp_rewrite? and /wsrp_rewrite
124: //
125:
126: while (currentStart < content.length()) {
127:
128: //
129: // Look for the begining of WSRPSpecKeys.COMMON (wsrp_rewrite)
130: //
131: beginTokenPosition = searchToken(content,
132: WSRPSpecKeys.COMMON, currentStart);
133:
134: //
135: // Break out if wsrp_rewrite is not found or
136: // it is the last word in the markup
137: //
138: if ((beginTokenPosition == -1)
139: || (beginTokenPosition
140: + WSRPSpecKeys.COMMON.length() == content
141: .length())) {
142: // no more tokens
143: //_debug.debugMessage("no more tokens");
144: break;
145: }
146:
147: //
148: // Let's see if the token is wsrp_rewrite? or wsrp_rewrite_ or
149: // just a string starting with wsrp_rewrite.
150: //
151:
152: String token = content.substring(beginTokenPosition,
153: beginTokenPosition + WSRPSpecKeys.COMMON.length()
154: + 1);
155:
156: if (token.equals(WSRPSpecKeys.NAMESPACE)) {
157: //
158: // Let's copy from currentStart till the start of
159: // WSRPSpecKeys.NAMESPACE in result string stream
160: //
161:
162: buffer.append(content.substring(currentStart,
163: beginTokenPosition));
164: buffer.append(_namespace);
165: currentStart = beginTokenPosition
166: + WSRPSpecKeys.NAMESPACE.length();
167: continue;
168: } else if (token.equals(WSRPSpecKeys.URL_REWRITE_START)) {
169:
170: //
171: // Look for the end token /wsrp_rewrite
172: //
173:
174: endTokenPosition = searchToken(content,
175: WSRPSpecKeys.URL_REWRITE_END, currentStart);
176:
177: if (endTokenPosition != -1) {
178:
179: //
180: // Let's copy from currentStart till the start of
181: // WSRPSpecKeys.URL_REWRITE_START in result string stream
182: //
183:
184: buffer.append(content.substring(currentStart,
185: beginTokenPosition));
186:
187: //
188: // Get the string in between the start and end
189: //
190:
191: String wsrpBasedURL = content
192: .substring(beginTokenPosition
193: + WSRPSpecKeys.URL_REWRITE_START
194: .length(), endTokenPosition);
195:
196: //
197: // Create a new URL based on ChannelURL
198: // that can understood by our portal
199: //
200:
201: if (logger.isLoggable(Level.FINEST))
202: logger.log(Level.FINEST, "PSWS_CSPWCC0003",
203: wsrpBasedURL);
204:
205: String providerBasedURL = getProviderBasedURL(
206: wsrpBasedURL, request);
207:
208: if (logger.isLoggable(Level.FINEST))
209: logger.log(Level.FINEST, "PSWS_CSPWCC0004",
210: providerBasedURL);
211:
212: //
213: // Let's copy the new URL
214: //
215:
216: if (providerBasedURL != null) {
217: buffer.append(providerBasedURL);
218: }
219:
220: //
221: // ready to back again
222: //
223:
224: currentStart = endTokenPosition
225: + WSRPSpecKeys.URL_REWRITE_END.length();
226: } else {
227: throw new WSRPConsumerRewriterException(
228: "Invalid WSRP tokens in the content. "
229: + " Couldn't find ending token /wsrp_rewrite.");
230: }
231: } else {
232: //
233: // Let's copy from currentStart till the start of
234: // WSRPSpecKeys.COMMON in result string stream
235: //
236:
237: buffer.append(content.substring(currentStart,
238: beginTokenPosition));
239: buffer.append(WSRPSpecKeys.COMMON);
240: currentStart = beginTokenPosition
241: + WSRPSpecKeys.COMMON.length();
242: }
243: }
244:
245: buffer.append(content.substring(currentStart));
246:
247: //_debug.debugMessage("Rewritten CONTENT:");
248: //_debug.debugMessage(buffer.toString());
249:
250: return buffer.toString();
251:
252: }
253:
254: /**
255: * Given a URL sort of string from the content
256: * that follows rules defined in the spec, this method
257: * converts it into a real url that would either point
258: * to the provider as render/action url or to the resource
259: * proxy servlet.
260: *
261: * @param wsrpBasedURL
262: * @return Returns a real url.
263: */
264: private String getProviderBasedURL(String wsrpBasedURL,
265: HttpServletRequest request)
266: throws WSRPConsumerRewriterException {
267:
268: String finalURL = null;
269: Map allMap = getParamMapFromURIStyleString(wsrpBasedURL);
270: String wsrp_urlType = (String) allMap
271: .get(WSRPSpecKeys.URL_TYPE);
272: String wsrp_secureURL = (String) allMap
273: .get(WSRPSpecKeys.SECURE_URL);
274:
275: //
276: // First make sure we are in the secure/unsecure mode as desired.
277: // if not return the security related error URL
278: //
279:
280: if ((wsrp_secureURL != null)
281: && (wsrp_secureURL.equals(Boolean.TRUE.toString()) && !request
282: .isSecure())) {
283: return _channelURLFactory.getSecurityErrorURL();
284: }
285:
286: //
287: // We are ok security wise and can proceed
288: // OK to process
289: //
290:
291: if (WSRPSpecKeys.URL_TYPE_RENDER.equals(wsrp_urlType)
292: || WSRPSpecKeys.URL_TYPE_BLOCKING_ACTION
293: .equals(wsrp_urlType)) {
294:
295: //
296: // As described in the constructors, the rewriter can be called
297: // by the proxy servlet too. According to Alejandro/Spec,
298: // content to be rewritten by proxy must not have render/performBlocking
299: // kinds of urls. It can only rewrite resource urls.
300: //
301: if (_channelURLFactory == null) {
302: throw new WSRPConsumerRewriterException(
303: " Content to be written by proxy has "
304: + " render/blockingaction urls.");
305: }
306:
307: //
308: // ready to proceed
309: //
310: String portletMode = (String) allMap.get(WSRPSpecKeys.MODE);
311:
312: String windowState = (String) allMap
313: .get(WSRPSpecKeys.WINDOW_STATE);
314:
315: String fragmentID = (String) allMap
316: .get(WSRPSpecKeys.FRAGMENT_ID);
317:
318: ChannelURL channelURL = _channelURLFactory
319: .createChannelURL();
320: channelURL.setChannelMode(WSRPToContainerMap
321: .mapChannelModeToContainer(portletMode));
322: channelURL.setWindowState(WSRPToContainerMap
323: .mapWindowStateToContainer(windowState));
324: channelURL.setURLType(WSRPToContainerMap
325: .mapURLTypeToContainer(wsrp_urlType));
326:
327: channelURL.setParameters((Map) allMap.get("parameters"));
328:
329: finalURL = channelURL.toString();
330: if (fragmentID != null && fragmentID.length() > 0) {
331: finalURL = finalURL + "#" + fragmentID;
332: }
333:
334: } else if (WSRPSpecKeys.URL_TYPE_RESOURCE.equals(wsrp_urlType)) {
335: String wsrp_url = (String) allMap.get(WSRPSpecKeys.URL);
336: String wsrp_requiresRewrite = (String) allMap
337: .get(WSRPSpecKeys.REQUIRES_REWRITE);
338:
339: StringBuffer proxyURL = new StringBuffer();
340: if (wsrp_url != null) {
341: proxyURL.append(_portalServerURLPrefix
342: + PROXY_SERVLET_MAPPING + "?"
343: + PROXY_RESOURCE_URL + "="
344: + URLEncoder.encode(wsrp_url));
345: if (wsrp_requiresRewrite != null) {
346: proxyURL.append("&" + PROXY_RESOURCE_REWRITE + "="
347: + wsrp_requiresRewrite);
348: if (_namespace != null) {
349: proxyURL.append("&" + PROXY_NAMESPACE + "="
350: + _namespace);
351: }
352: proxyURL
353: .append("&"
354: + PROXY_PORTAL_SERVER_URL
355: + "="
356: + URLEncoder
357: .encode(_portalServerURLPrefix));
358: }
359: if (_cookieKey != null) {
360: proxyURL.append("&" + PROXY_COOKIE_KEY + "="
361: + _cookieKey);
362: }
363:
364: }
365:
366: finalURL = proxyURL.toString();
367: }
368:
369: return finalURL;
370:
371: }
372:
373: /**
374: * Calls Boyer algorithm to look for a string token.
375: *
376: * @param content
377: * @param pattern
378: * @param start
379: */
380: private int searchToken(String content, String pattern, int start) {
381: return Boyer.indexOf(content, pattern, start);
382: }
383:
384: /**
385: * Converts a url sort of string as
386: * defined in the WSRP spec, to a name-value map.
387: *
388: * @param wsrpurl
389: */
390: private Map getParamMapFromURIStyleString(String wsrpurl) {
391:
392: //
393: // First covert all the & to &
394: // url decode too
395: String tempStr = decodeAmpersand(wsrpurl);
396: //String paramString = URLDecoder.decode(tempStr);
397: String paramString = tempStr;
398:
399: //_debug.debugMessage("After all decoding::" + paramString);
400:
401: //
402: // Create a hashmap where value is the List
403: //
404: Map allMap = new HashMap();
405: Map paramMap = new HashMap();
406:
407: StringTokenizer paramtokenizer = new StringTokenizer(
408: paramString, "&");
409:
410: while (paramtokenizer.hasMoreTokens()) {
411: String keyValue = paramtokenizer.nextToken();
412:
413: StringTokenizer keyTokenizer = new StringTokenizer(
414: keyValue, "=");
415:
416: if (keyTokenizer.countTokens() == 2) {
417: String key = keyTokenizer.nextToken();
418: String value = URLDecoder.decode(keyTokenizer
419: .nextToken());
420: if (WSRPSpecKeys.isReservedKey(key)) {
421: allMap.put(key, value);
422: } else {
423:
424: List valueList = (List) paramMap.get(key);
425: if (valueList == null) {
426: valueList = new ArrayList();
427: }
428: valueList.add(value);
429: paramMap.put(key, valueList);
430: }
431: }
432:
433: }
434:
435: //
436: // Covert the original hashmap to a new map
437: // where the value is String[]
438: //
439:
440: Map paramMapWithArray = new HashMap(paramMap.size());
441: Iterator iter = paramMap.keySet().iterator();
442: while (iter.hasNext()) {
443: String key = (String) iter.next();
444: List listValue = (List) paramMap.get(key);
445: String[] values = new String[listValue.size()];
446: listValue.toArray(values);
447: paramMapWithArray.put(key, values);
448: }
449: allMap.put("parameters", paramMapWithArray);
450:
451: return allMap;
452: }
453:
454: private final static String AMP = "&";
455: private final static String AMP1 = "&";
456: private final static String AMP2 = "&";
457:
458: /**
459: * Take care of ampersand.
460: *
461: * @param url
462: */
463: private String decodeAmpersand(String url) {
464: url = decode(url, AMP1, AMP);
465: url = decode(url, AMP2, AMP);
466: return url;
467: }
468:
469: private String decode(String url, String from, String to) {
470: int i;
471: while ((i = url.indexOf(from)) >= 0) {
472: url = url.substring(0, i) + to
473: + url.substring(i + from.length());
474: }
475: return url;
476: }
477:
478: /**************************************************************************
479: * TEMPLATES
480: **************************************************************************/
481: public Templates getTemplates(HttpServletRequest request) {
482:
483: Templates templates = new Templates();
484:
485: //
486: // For unsecure templates, we don't care what mode
487: // we are running in.
488: //
489: templates.setDefaultTemplate(null);
490: templates.setRenderTemplate(_channelURLFactory
491: .getRenderTemplate());
492: templates.setBlockingActionTemplate(_channelURLFactory
493: .getActionTemplate());
494: templates.setResourceTemplate(getResourceTemplate());
495:
496: if (request.isSecure()) {
497: templates.setSecureRenderTemplate(_channelURLFactory
498: .getRenderTemplate());
499: templates
500: .setSecureBlockingActionTemplate(_channelURLFactory
501: .getActionTemplate());
502: templates.setSecureResourceTemplate(getResourceTemplate());
503: templates.setSecureDefaultTemplate(null);
504: } else {
505: //
506: // If we are not running in secure mode,
507: // give the error url and fake tokens.
508: // error url goes back to WindowProvider
509: // which gives a localized error back indicating
510: // that we are not running in secure mode.
511: //
512: StringBuffer buf = new StringBuffer();
513:
514: buf.append(_channelURLFactory.getSecurityErrorURL());
515: buf.append("&");
516: buf.append("wsrp-urlType={wsrp-urlType}");
517: buf.append("&windowstate={wsrp-windowState}");
518: buf.append("&channelMode={wsrp-mode}");
519: buf
520: .append("&wsrp-navigationalState={wsrp-navigationalState}");
521: buf
522: .append("&wsrp-interactionState={wsrp-interactionState}");
523: buf.append("&wsrp-url={wsrp-url}");
524: buf.append("&wsrp-requiresRewrite={wsrp-requiresRewrite}");
525:
526: templates.setSecureDefaultTemplate(buf.toString());
527:
528: }
529:
530: return templates;
531: }
532:
533: private String getResourceTemplate() {
534:
535: StringBuffer proxyURL = new StringBuffer();
536:
537: proxyURL.append(_portalServerURLPrefix + PROXY_SERVLET_MAPPING
538: + "?" + PROXY_RESOURCE_URL + "=" + "{wsrp-url}");
539:
540: proxyURL.append("&" + PROXY_RESOURCE_REWRITE + "="
541: + "{wsrp-requiresRewrite}");
542: if (_namespace != null) {
543: proxyURL.append("&" + PROXY_NAMESPACE + "=" + _namespace);
544: }
545: proxyURL.append("&" + PROXY_PORTAL_SERVER_URL + "="
546: + URLEncoder.encode(_portalServerURLPrefix));
547:
548: if (_cookieKey != null) {
549: proxyURL.append("&" + PROXY_COOKIE_KEY + "=" + _cookieKey);
550: }
551:
552: return proxyURL.toString();
553: }
554: }
|