001: /* Portlets.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Fri Apr 1 13:57:54 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.web.portlet;
020:
021: import java.util.Map;
022: import java.io.InputStream;
023: import java.io.IOException;
024: import java.net.URL;
025: import java.net.MalformedURLException;
026:
027: import javax.servlet.ServletContext;
028: import javax.servlet.RequestDispatcher;
029: import javax.portlet.PortletRequestDispatcher;
030: import javax.portlet.PortletContext;
031: import javax.portlet.RenderRequest;
032: import javax.portlet.RenderResponse;
033: import javax.portlet.PortletException;
034:
035: import org.zkoss.lang.D;
036: import org.zkoss.lang.SystemException;
037: import org.zkoss.util.logging.Log;
038:
039: import org.zkoss.web.servlet.Servlets;
040: import org.zkoss.web.util.resource.ExtendletContext;
041:
042: /**
043: * Utilities to handle portlet.
044: *
045: * @author tomyeh
046: */
047: public class Portlets {
048: private static final Log log = Log.lookup(Portlets.class);
049:
050: /**
051: * Includes the resource at the specified URI.
052: * It enhances RequestDispatcher to allow the inclusion with
053: * a parameter map -- acutually converting parameters to a query string
054: * and appending it to uri.
055: *
056: * <p>NOTE: don't include query parameters in uri.
057: *
058: * @param uri the URI to include. It is OK to relevant (without leading
059: * '/'). If starts with "/", the context path of request is assumed.
060: * To reference to foreign context, use "~ctx/" where ctx is the
061: * context path of the foreign context (without leading '/').
062: * @param params the parameter map; null to ignore
063: * @param mode one of {@link #OVERWRITE_URI}, {@link #IGNORE_PARAM},
064: * and {@link #APPEND_PARAM}. It defines how to handle if both uri
065: * and params contains the same parameter.
066: */
067: public static final void include(PortletContext ctx,
068: RenderRequest request, RenderResponse response, String uri,
069: Map params, int mode) throws IOException, PortletException {
070: final PortletRequestDispatcher disp = getRequestDispatcher(ctx,
071: uri, params, mode);
072: if (disp == null)
073: throw new PortletException(
074: "No dispatcher available to include " + uri);
075: disp.include(request, response);
076: }
077:
078: /** Returns the request dispatch of the specified URI.
079: *
080: * @param ctx the context used to resolve a foreign context.
081: * It is required only if uri starts with "~".
082: * @param uri the URI to include. It is OK to relevant (without leading
083: * '/'). If starts with "/", the context path of request is assumed.
084: * To reference to foreign context, use "~ctx/" where ctx is the
085: * context path of the foreign context (without leading '/').
086: * @param params the parameter map; null to ignore
087: * @param mode one of {@link #OVERWRITE_URI}, {@link #IGNORE_PARAM},
088: * and {@link #APPEND_PARAM}. It defines how to handle if both uri
089: * and params contains the same parameter.
090: */
091: public static final PortletRequestDispatcher getRequestDispatcher(
092: PortletContext ctx, String uri, Map params, int mode)
093: throws PortletException {
094: return new ParsedURI(ctx, uri).getRequestDispatcher(params,
095: mode);
096: }
097:
098: /** Returns the resource of the specified uri.
099: * Unlike PortletContext.getResource, it handles "~" like
100: * {@link #getRequestDispatcher} did.
101: */
102: public static final URL getResource(PortletContext ctx, String uri)
103: throws MalformedURLException {
104: return new ParsedURI(ctx, uri).getResource();
105: }
106:
107: /** Returns the resource stream of the specified uri.
108: * Unlike PortletContext.getResource, it handles "~" like
109: * {@link #getRequestDispatcher} did.
110: */
111: public static final InputStream getResourceAsStream(
112: PortletContext ctx, String uri) {
113: return new ParsedURI(ctx, uri).getResourceAsStream();
114: }
115:
116: /** Used to resolve "~" in URI. */
117: private static class ParsedURI {
118: /** The portlet context, null if _svlctx or _extctx is need. */
119: private PortletContext _prtctx;
120: /** External context if ~xxx/ is specified. */
121: private ServletContext _svlctx;
122: /** The extended context. */
123: private ExtendletContext _extctx;
124: private String _uri;
125:
126: private ParsedURI(final PortletContext ctx, final String uri) {
127: if (uri != null && uri.startsWith("~")) { //refer to foreign context
128: final int j = uri.indexOf('/', 1);
129: final String ctxroot;
130: if (j >= 0) {
131: ctxroot = "/" + uri.substring(1, j);
132: _uri = uri.substring(j);
133: } else {
134: ctxroot = "/" + uri.substring(1);
135: _uri = "/";
136: }
137:
138: final ServletContext svlctx = getServletContext(ctx);
139: _extctx = Servlets.getExtendletContext(svlctx, ctxroot
140: .substring(1));
141: if (_extctx == null) {
142: _svlctx = svlctx;
143: _svlctx = _svlctx.getContext(ctxroot);
144: if (_svlctx == null)
145: throw new SystemException(
146: "Context not found or not visible to "
147: + ctx + ": " + ctxroot);
148: }
149: } else {
150: _prtctx = ctx;
151: _uri = uri;
152: }
153: }
154:
155: private PortletRequestDispatcher getRequestDispatcher(
156: Map params, int mode) {
157: if (_extctx == null && _svlctx == null && _prtctx == null) //not found
158: return null;
159:
160: final String uri = generateURI(_uri, params, mode);
161: if (_prtctx != null)
162: return _prtctx.getRequestDispatcher(uri);
163:
164: final RequestDispatcher rd = _svlctx != null ? _svlctx
165: .getRequestDispatcher(uri) : _extctx
166: .getRequestDispatcher(uri);
167: return ServletPortletDispatcher.getInstance(rd);
168: }
169:
170: private URL getResource() throws MalformedURLException {
171: return _prtctx != null ? _prtctx.getResource(_uri)
172: : _svlctx != null ? _svlctx.getResource(_uri)
173: : _extctx != null ? _extctx
174: .getResource(_uri) : null;
175: }
176:
177: private InputStream getResourceAsStream() {
178: return _prtctx != null ? _prtctx.getResourceAsStream(_uri)
179: : _svlctx != null ? _svlctx
180: .getResourceAsStream(_uri)
181: : _extctx != null ? _extctx
182: .getResourceAsStream(_uri) : null;
183: }
184: }
185:
186: private static final ServletContext getServletContext(
187: PortletContext ctx) {
188: return PortletServletContext.getInstance(ctx);
189: }
190:
191: /** Whether to overwrite uri if both uri and params contain the same
192: * parameter.
193: * Used by {@link #generateURI}
194: */
195: public static final int OVERWRITE_URI = Servlets.OVERWRITE_URI;
196: /** Whether to ignore params if both uri and params contain the same
197: * parameter.
198: * Used by {@link #generateURI}
199: */
200: public static final int IGNORE_PARAM = Servlets.IGNORE_PARAM;
201: /** Whether to append params if both uri and params contain the same
202: * parameter. In other words, they both appear as the final query string.
203: * Used by {@link #generateURI}
204: */
205: public static final int APPEND_PARAM = Servlets.APPEND_PARAM;
206:
207: /** Generates URI by appending the parameters.
208: * @param params the parameters to apend to the query string
209: * @param mode one of {@link #OVERWRITE_URI}, {@link #IGNORE_PARAM},
210: * and {@link #APPEND_PARAM}. It defines how to handle if both uri
211: * and params contains the same parameter.
212: * mode is used only if both uri contains query string and params is
213: * not empty.
214: */
215: public static final String generateURI(String uri, Map params,
216: int mode) {
217: return Servlets.generateURI(uri, params, mode);
218: }
219: }
|