/* Portlets.java Purpose: Description: History: Fri Apr 1 13:57:54 2005, Created by tomyeh Copyright (C) 2005 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.web.portlet; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import javax.portlet.PortletContext; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zkoss.lang.SystemException; import org.zkoss.web.servlet.Servlets; import org.zkoss.web.util.resource.ExtendletContext; /** * Utilities to handle portlet. * * @author tomyeh */ public class Portlets { private static final Logger log = LoggerFactory.getLogger(Portlets.class); /** * Includes the resource at the specified URI. * It enhances RequestDispatcher to allow the inclusion with * a parameter map -- actually converting parameters to a query string * and appending it to uri. * * <p>NOTE: don't include query parameters in uri. * * @param uri the URI to include. It is OK to relevant (without leading * '/'). If starts with "/", the context path of request is assumed. * To reference to foreign context, use "~ctx/" where ctx is the * context path of the foreign context (without leading '/'). * @param params the parameter map; null to ignore * @param mode one of {@link #OVERWRITE_URI}, {@link #IGNORE_PARAM}, * and {@link #APPEND_PARAM}. It defines how to handle if both uri * and params contains the same parameter. */ public static final void include(PortletContext ctx, RenderRequest request, RenderResponse response, String uri, Map params, int mode) throws IOException, PortletException { final PortletRequestDispatcher disp = getRequestDispatcher(ctx, uri, params, mode); if (disp == null) throw new PortletException("No dispatcher available to include " + uri); disp.include(request, response); } /** Returns the request dispatch of the specified URI. * * @param ctx the context used to resolve a foreign context. * It is required only if uri starts with "~". * @param uri the URI to include. It is OK to relevant (without leading * '/'). If starts with "/", the context path of request is assumed. * To reference to foreign context, use "~ctx/" where ctx is the * context path of the foreign context (without leading '/'). * @param params the parameter map; null to ignore * @param mode one of {@link #OVERWRITE_URI}, {@link #IGNORE_PARAM}, * and {@link #APPEND_PARAM}. It defines how to handle if both uri * and params contains the same parameter. */ public static final PortletRequestDispatcher getRequestDispatcher(PortletContext ctx, String uri, Map params, int mode) throws PortletException { return new ParsedURI(ctx, uri).getRequestDispatcher(params, mode); } /** Returns the resource of the specified uri. * Unlike PortletContext.getResource, it handles "~" like * {@link #getRequestDispatcher} did. */ public static final URL getResource(PortletContext ctx, String uri) throws MalformedURLException { return new ParsedURI(ctx, uri).getResource(); } /** Returns the resource stream of the specified uri. * Unlike PortletContext.getResource, it handles "~" like * {@link #getRequestDispatcher} did. */ public static final InputStream getResourceAsStream(PortletContext ctx, String uri) { return new ParsedURI(ctx, uri).getResourceAsStream(); } /** Used to resolve "~" in URI. */ private static class ParsedURI { /** The portlet context, null if _svlctx or _extctx is need. */ private PortletContext _prtctx; /** External context if ~xxx/ is specified. */ private ServletContext _svlctx; /** The extended context. */ private ExtendletContext _extctx; private String _uri; private ParsedURI(final PortletContext ctx, final String uri) { if (uri != null && uri.length() > 0 && uri.charAt(0) == '~') { //refer to foreign context final int j = uri.indexOf('/', 1); final String ctxroot; if (j >= 0) { ctxroot = "/" + uri.substring(1, j); _uri = uri.substring(j); } else { ctxroot = "/" + uri.substring(1); _uri = "/"; } final ServletContext svlctx = getServletContext(ctx); _extctx = Servlets.getExtendletContext(svlctx, ctxroot.substring(1)); if (_extctx == null) { _svlctx = svlctx; _svlctx = _svlctx.getContext(ctxroot); if (_svlctx == null) throw new SystemException("Context not found or not visible to " + ctx + ": " + ctxroot); } } else { _prtctx = ctx; _uri = uri; } } private PortletRequestDispatcher getRequestDispatcher(Map params, int mode) { if (_extctx == null && _svlctx == null && _prtctx == null) //not found return null; final String uri = generateURI(_uri, params, mode); if (_prtctx != null) return _prtctx.getRequestDispatcher(uri); final RequestDispatcher rd = _svlctx != null ? _svlctx.getRequestDispatcher(uri) : _extctx.getRequestDispatcher(uri); return ServletPortletDispatcher.getInstance(rd); } private URL getResource() throws MalformedURLException { return _prtctx != null ? _prtctx.getResource(_uri) : _svlctx != null ? _svlctx.getResource(_uri) : _extctx != null ? _extctx.getResource(_uri) : null; } private InputStream getResourceAsStream() { return _prtctx != null ? _prtctx.getResourceAsStream(_uri) : _svlctx != null ? _svlctx.getResourceAsStream(_uri) : _extctx != null ? _extctx.getResourceAsStream(_uri) : null; } } private static final ServletContext getServletContext(PortletContext ctx) { return PortletServletContext.getInstance(ctx); } /** Whether to overwrite uri if both uri and params contain the same * parameter. * Used by {@link #generateURI} */ public static final int OVERWRITE_URI = Servlets.OVERWRITE_URI; /** Whether to ignore params if both uri and params contain the same * parameter. * Used by {@link #generateURI} */ public static final int IGNORE_PARAM = Servlets.IGNORE_PARAM; /** Whether to append params if both uri and params contain the same * parameter. In other words, they both appear as the final query string. * Used by {@link #generateURI} */ public static final int APPEND_PARAM = Servlets.APPEND_PARAM; /** Generates URI by appending the parameters. * @param params the parameters to append to the query string * @param mode one of {@link #OVERWRITE_URI}, {@link #IGNORE_PARAM}, * and {@link #APPEND_PARAM}. It defines how to handle if both uri * and params contains the same parameter. * mode is used only if both uri contains query string and params is * not empty. */ public static final String generateURI(String uri, Map params, int mode) { return Servlets.generateURI(uri, params, mode); } }