Java tutorial
/* * Copyright 2004-2009 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.struts.portlet; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.GenericPortlet; import javax.portlet.PortletException; import javax.portlet.PortletRequest; import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.LRUMap; import org.apache.struts.action.ActionServlet; import org.seasar.framework.container.filter.S2ContainerFilter; import org.seasar.framework.container.hotdeploy.HotdeployFilter; import org.seasar.framework.util.StringUtil; import org.seasar.struts.portlet.config.ProcessActionConfig; import org.seasar.struts.portlet.filter.PortletRoutingFilter; import org.seasar.struts.portlet.servlet.SAStrutsActionRequest; import org.seasar.struts.portlet.servlet.SAStrutsActionResponse; import org.seasar.struts.portlet.servlet.SAStrutsConfig; import org.seasar.struts.portlet.servlet.SAStrutsFilterChain; import org.seasar.struts.portlet.util.PortletUtil; /** * This is SAStruts Portlet class. SAStrutsPortlet emulates a servlet * environment and passes a portlet request to SAStruts as a servlet request. * * @author shinsuke * */ public class SAStrutsPortlet extends GenericPortlet { /** * Name of a parameter for a help page */ protected static final String HELP_PAGE = "helpPage"; /** * Name of a parameter for a edit page */ protected static final String EDIT_PAGE = "editPage"; /** * Name of a parameter for a view page */ protected static final String VIEW_PAGE = "viewPage"; /** * Name of a content type */ protected static final String CONTENT_TYPE = "contentType"; protected static final String MAX_CACHE_SIZE = "maxCacheSize"; protected static final String ENCODING = "encoding"; protected static final String PREVIOUS_PORTLET_MODE = "previousPortletMode"; protected String defaultViewPage; protected String defaultEditPage; protected String defaultHelpPage; protected String contentType; protected SAStrutsConfig saStrutsConfig; protected SAStrutsFilterChain saStrutsFilterChain; protected int maxCacheSize; protected String encoding; @Override public void init() throws PortletException { defaultViewPage = getViewPage(); defaultEditPage = getEditPage(); defaultHelpPage = getHelpPage(); contentType = getContentType(); maxCacheSize = getMaxCacheSize(); encoding = getCharacterEncoding(); saStrutsConfig = new SAStrutsConfig(getPortletConfig()); } protected SAStrutsFilterChain createFilterChain(Servlet servlet) { SAStrutsFilterChain filterChain = new SAStrutsFilterChain(servlet); // S2ContainerFilter Filter s2ContainerFilter = new S2ContainerFilter(); filterChain.addFilter(s2ContainerFilter); // HotdeployFilter Filter hotdeployFilter = new HotdeployFilter(); filterChain.addFilter(hotdeployFilter); // RoutingFilter Filter routingFilter = new PortletRoutingFilter(); filterChain.addFilter(routingFilter); return filterChain; } protected ActionServlet createActionServlet() throws PortletException { ActionServlet actionServlet = (ActionServlet) getPortletContext().getAttribute(PortletUtil.ACTION_SERVLET); if (actionServlet == null) { throw new PortletException("ActionServlet is null."); } return actionServlet; } @Override public void destroy() { saStrutsConfig = null; saStrutsFilterChain = null; } protected String getViewPage() { return getPortletConfig().getInitParameter(VIEW_PAGE); } protected String getEditPage() { return getPortletConfig().getInitParameter(EDIT_PAGE); } protected String getHelpPage() { return getPortletConfig().getInitParameter(HELP_PAGE); } protected String getContentType() { return getPortletConfig().getInitParameter(CONTENT_TYPE); } protected String getCharacterEncoding() { String encoding = getPortletConfig().getInitParameter(ENCODING); if (encoding == null) { encoding = "UTF-8"; } return encoding; } protected int getMaxCacheSize() { int size = 5; String value = getPortletConfig().getInitParameter(MAX_CACHE_SIZE); if (value != null) { try { size = Integer.parseInt(value); } catch (NumberFormatException e) { } } return size; } @Override protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException, IOException { renderRequest(request, response, defaultEditPage); } @Override protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException, IOException { renderRequest(request, response, defaultHelpPage); } @Override protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { renderRequest(request, response, defaultViewPage); } @Override public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException { String requestPath = request.getParameter(PortletUtil.REQUEST_URL); if (requestPath == null) { // nothing return; } Integer accessId = PortletUtil.getAccessId(request); request.setAttribute(PortletUtil.PORTLET_REQUEST, request); request.setAttribute(PortletUtil.PORTLET_RESPONSE, response); request.setAttribute(PortletUtil.PORTLET_CONFIG, getPortletConfig()); ProcessActionConfig processActionConfig = null; while (processRequest(request, response, requestPath, accessId)) { request.removeAttribute(PortletRoutingFilter.DONE); request.removeAttribute(PortletUtil.FORWARD_PATH); requestPath = (String) request.getAttribute(PortletUtil.REQUEST_URL); accessId = PortletUtil.incrementAccessId(request); } } protected boolean processRequest(ActionRequest request, ActionResponse response, String requestPath, Integer accessId) throws PortletException, IOException { if (requestPath == null || accessId == null) { return false; } PortletUtil.setSAStrutsStarted(request); try { ProcessActionConfig processActionConfig = new ProcessActionConfig(requestPath, request.getContextPath(), encoding); Map parameterMap = new HashMap(); parameterMap.putAll(request.getParameterMap()); processActionConfig.setParameterMap(parameterMap); SAStrutsActionRequest saStrutsActionRequest = new SAStrutsActionRequest(request, saStrutsConfig, processActionConfig); SAStrutsActionResponse saActionResponse = new SAStrutsActionResponse(request, response, getPortletContext()); // execute process(saStrutsActionRequest, saActionResponse); // foward path String forwardPath = (String) request.getAttribute(PortletUtil.FORWARD_PATH); if (forwardPath != null) { processActionConfig.setForwardPath(forwardPath); } else { forwardPath = processActionConfig.getForwardPath(); } // error status if (request.getAttribute(PortletUtil.ERROR_STATUS) != null) { processActionConfig.getAttributeMap().put(PortletUtil.ERROR_STATUS, request.getAttribute(PortletUtil.ERROR_STATUS)); Object msg = request.getAttribute(PortletUtil.ERROR_MESSAGE); if (msg != null) { processActionConfig.getAttributeMap().put(PortletUtil.ERROR_MESSAGE, msg); } } // set processActionConfig putProcessActionConfig(request, accessId, processActionConfig); if (processActionConfig == null) { return false; } if (request.getAttribute(PortletUtil.REDIRECT) != null) { return false; } else { // set accessId response.setRenderParameter(PortletUtil.ACCESS_ID, accessId.toString()); } if (forwardPath == null) { return false; } int idx = forwardPath.indexOf("?"); if (idx > 0) { forwardPath = forwardPath.substring(0, idx); } if (forwardPath.endsWith(".do")) { String requestUrl = processActionConfig.getContextPath() + processActionConfig.getForwardPath(); request.setAttribute(PortletUtil.REQUEST_URL, requestUrl.replaceAll("^/+", "/")); return true; } return false; } finally { PortletUtil.setSAStrutsFinished(request); } } protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException, PortletException { if (saStrutsFilterChain == null) { saStrutsFilterChain = createFilterChain(createActionServlet()); } saStrutsFilterChain.reset(); try { saStrutsFilterChain.doFilter(request, response); } catch (ServletException e) { throw new PortletException(e); } } protected void renderRequest(RenderRequest request, RenderResponse response, String defaultPage) throws PortletException, IOException { PortletUtil.setSAStrutsStarted(request); try { Integer accessId = getAccessId(request); ProcessActionConfig processActionConfig = createProcessActionConfig(request, accessId, defaultPage, request.getContextPath()); request.setAttribute(PortletUtil.PROCESS_ACTION_CONFIG, processActionConfig); // check error from processAction Integer sc = (Integer) processActionConfig.getAttributeMap().get(PortletUtil.ERROR_STATUS); if (sc != null) { response.setContentType("text/html"); sendError(response, sc, (String) processActionConfig.getAttributeMap().get(PortletUtil.ERROR_MESSAGE)); return; } String requestPath = getRequestPath(request); // without contextPath PortletRequestDispatcher portletRequestDispatcher = getPortletContext() .getRequestDispatcher(requestPath); portletRequestDispatcher.include(request, response); String cType = (String) request.getAttribute(PortletUtil.CONTENT_TYPE); if (cType == null) { cType = contentType; if (cType == null) { cType = "text/html"; } } response.setContentType(cType); sc = (Integer) request.getAttribute(PortletUtil.ERROR_STATUS); if (sc != null) { sendError(response, sc, (String) request.getAttribute(PortletUtil.ERROR_MESSAGE)); } else { response.getWriter().print(request.getAttribute(PortletUtil.PORTLET_CONTENT)); response.flushBuffer(); } // update processActionConfig putProcessActionConfig(request, PortletUtil.getAccessId(request), processActionConfig); PortletUtil.incrementAccessId(request); } finally { PortletUtil.setSAStrutsFinished(request); } } protected void sendError(RenderResponse response, Integer sc, String msg) throws IOException { StringBuilder sb = new StringBuilder("HTTP Status "); sb.append(sc); if (msg != null) { sb.append(" - "); sb.append(msg); } response.getWriter().print(sb.toString()); response.flushBuffer(); } protected ProcessActionConfig createProcessActionConfig(RenderRequest request, Integer accessId, String requestUrl, String contextPath) { ProcessActionConfig processActionConfig = getProcessActionConfig(request, accessId); if (processActionConfig != null && processActionConfig.getForwardPath() != null) { StringBuilder buf = new StringBuilder(processActionConfig.getServletPath()); if (processActionConfig.getQueryString() != null) { buf.append("?"); buf.append(processActionConfig.getQueryString()); } request.setAttribute(PortletUtil.REQUEST_URL, buf.toString()); request.setAttribute(PortletUtil.FORWARD_PATH, processActionConfig.getForwardPath()); } else if (processActionConfig != null) { request.setAttribute(PortletUtil.REQUEST_URL, processActionConfig.getServletPath()); } else { StringBuilder buf = new StringBuilder(); if (!StringUtil.isEmpty(contextPath)) { buf.append(contextPath); } buf.append(requestUrl); processActionConfig = new ProcessActionConfig(buf.toString(), contextPath, encoding); request.setAttribute(PortletUtil.REQUEST_URL, requestUrl); } return processActionConfig; } protected String getRequestPath(PortletRequest request) { String requestPath = (String) request.getAttribute(PortletUtil.REQUEST_URL); if (requestPath == null) { requestPath = request.getParameter(PortletUtil.REQUEST_URL); if (requestPath == null) { return null; } } return requestPath; } protected void putProcessActionConfig(PortletRequest request, Integer accessId, ProcessActionConfig processActionConfig) { PortletSession portletSession = request.getPortletSession(); Map configMap = (Map) portletSession.getAttribute(PortletUtil.PROCESS_ACTION_CONFIG_MAP); if (configMap == null) { configMap = new LRUMap(maxCacheSize); portletSession.setAttribute(PortletUtil.PROCESS_ACTION_CONFIG_MAP, configMap); } configMap.put(accessId, processActionConfig); } protected ProcessActionConfig getProcessActionConfig(PortletRequest request, Integer accessId) { PortletSession portletSession = request.getPortletSession(); String currentPortletMode = request.getPortletMode().toString(); String previousPortletMode = (String) portletSession.getAttribute(PREVIOUS_PORTLET_MODE); // set portlet mode portletSession.setAttribute(PREVIOUS_PORTLET_MODE, currentPortletMode); if (isPortletModeChange(currentPortletMode, previousPortletMode)) { // portlet mode was changed. clear cache. portletSession.setAttribute(PortletUtil.PROCESS_ACTION_CONFIG_MAP, new LRUMap(maxCacheSize)); return null; } Map configMap = (Map) portletSession.getAttribute(PortletUtil.PROCESS_ACTION_CONFIG_MAP); if (configMap == null) { configMap = new LRUMap(maxCacheSize); portletSession.setAttribute(PortletUtil.PROCESS_ACTION_CONFIG_MAP, configMap); } return (ProcessActionConfig) configMap.get(accessId); } protected Integer getAccessId(PortletRequest request) { Integer accessId = PortletUtil.getAccessId(request); String accessIdString = request.getParameter(PortletUtil.ACCESS_ID); if (accessIdString != null) { try { accessId = Integer.valueOf(Integer.parseInt(accessIdString)); } catch (NumberFormatException e) { } } return accessId; } private boolean isPortletModeChange(String currentMode, String previousMode) { if (previousMode == null) { return false; } else if (!previousMode.equals(currentMode)) { return true; } return false; } }