/*
*
* Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved.
*
* This file is part of jAPS software.
* jAPS is a free software;
* you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2.
*
* See the file License for the specific language governing permissions
* and limitations under the License
*
*
*
* Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved.
*
*/
package com.agiletec.aps.tags;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import com.agiletec.aps.system.ApsSystemUtils;
import com.agiletec.aps.system.RequestContext;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.services.page.IPage;
import com.agiletec.aps.system.services.page.Showlet;
import com.agiletec.aps.util.ApsProperties;
/**
* Tag for showlet "InternalServlet".
* Publish a function erogated throw a internal Servlet; the servlet is invoked by a path specificated
* by the tag attribute "actionPath" or by the showlet parameter of the same name.
* @author M.Casari - E.Santoboni
*/
public class InternalServletTag extends TagSupport {
/**
* Internal class that wrappers the response, extending the
* javax.servlet.http.HttpServletResponseWrapper class to
* define a proprietary output channel.
* It is used to retrieve the content response after having
* made an 'include' in the RequestDispatcher
*/
public class ResponseWrapper extends HttpServletResponseWrapper {
public ResponseWrapper(HttpServletResponse response) {
super(response);
_output = new CharArrayWriter();
}
@Override
public PrintWriter getWriter() {
return new PrintWriter(_output);
}
@Override
public void sendRedirect(String path) throws IOException {
this._redirectPath = path;
}
@Override
public void addCookie(Cookie cookie) {
super.addCookie(cookie);
this._cookieToAdd = cookie;
}
protected Cookie getCookieToAdd() {
return _cookieToAdd;
}
public boolean isRedirected() {
return (_redirectPath != null);
}
public String getRedirectPath() {
return _redirectPath;
}
@Override
public String toString() {
return _output.toString();
}
private String _redirectPath;
private CharArrayWriter _output;
private Cookie _cookieToAdd;
}
/**
* Invokes the showlet configured in the current page.
* @throws JspException in case of error that occurred in both this method
* or in one of the included JSPs
*/
@Override
public int doEndTag() throws JspException {
int result = super.doEndTag();
ServletRequest req = this.pageContext.getRequest();
RequestContext reqCtx = (RequestContext) req.getAttribute(RequestContext.REQCTX);
try {
IPage page = (IPage) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_PAGE);
ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse)this.pageContext.getResponse());
String output = this.buildShowletOutput(page, responseWrapper);
if (responseWrapper.isRedirected()) {
String redirect = responseWrapper.getRedirectPath();
reqCtx.addExtraParam(SystemConstants.EXTRAPAR_EXTERNAL_REDIRECT, redirect);
result = SKIP_PAGE;
} else {
this.pageContext.getOut().print(output);
}
} catch (Throwable t) {
String msg = "Error in showlet preprocessing";
ApsSystemUtils.logThrowable(t, this, "doEndTag", msg);
throw new JspException(msg, t);
}
return result;
}
protected String buildShowletOutput(IPage page, ResponseWrapper responseWrapper) throws JspException {
String output = null;
ServletRequest req = this.pageContext.getRequest();
RequestContext reqCtx = (RequestContext) req.getAttribute(RequestContext.REQCTX);
try {
Showlet showlet = (Showlet) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_SHOWLET);
this.includeShowlet(reqCtx, responseWrapper, showlet);
if (null != responseWrapper.getCookieToAdd()) {
reqCtx.getResponse().addCookie(responseWrapper.getCookieToAdd());
}
output = responseWrapper.toString();
responseWrapper.getWriter().close();
} catch (Throwable t) {
String msg = "Errore in preelaborazione showlets";
throw new JspException(msg, t);
}
return output;
}
protected void includeShowlet(RequestContext reqCtx, ResponseWrapper responseWrapper, Showlet showlet) throws ServletException, IOException {
HttpServletRequest request = reqCtx.getRequest();
try {
String actionPath = this.extractIntroActionPath(reqCtx, showlet);
String requestActionPath = request.getParameter(REQUEST_PARAM_ACTIONPATH);
String currentFrameActionPath = request.getParameter(REQUEST_PARAM_FRAMEDEST);
Integer currentFrame = (Integer) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_FRAME);
if (requestActionPath != null && currentFrameActionPath != null && currentFrame.toString().equals(currentFrameActionPath)) {
actionPath = requestActionPath;
}
RequestDispatcher requestDispatcher = request.getRequestDispatcher(actionPath);
requestDispatcher.include(request, responseWrapper);
} catch (Throwable t) {
ApsSystemUtils.logThrowable(t, this, "includeShowlet", "Error including showlet");
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/WEB-INF/aps/jsp/system/internalServlet_error.jsp");
requestDispatcher.include(request, responseWrapper);
}
}
/**
* Extract the init Action Path.
* Return the tag attribute (if set), else the showlet parameter.
* @param reqCtx The request context
* @param showlet The current showlet.
* @return The init Action Path
*/
protected String extractIntroActionPath(RequestContext reqCtx, Showlet showlet) {
String actionPath = this.getActionPath();
if (null == this.getActionPath()) {
ApsProperties config = showlet.getConfig();
if (showlet.getType().isLogic()) {
config = showlet.getType().getConfig();
}
if (null != config) {
actionPath = config.getProperty(CONFIG_PARAM_ACTIONPATH);
}
}
if (null == actionPath || actionPath.trim().length() == 0) {
IPage page = (IPage) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_PAGE);
throw new RuntimeException("Null init action path : page " + page.getCode());
}
return actionPath;
}
@Override
public void release() {
super.release();
this.setActionPath(null);
}
public String getActionPath() {
return _actionPath;
}
public void setActionPath(String actionPath) {
this._actionPath = actionPath;
}
private String _actionPath;
public static final String CONFIG_PARAM_ACTIONPATH = "actionPath";
public static final String REQUEST_PARAM_ACTIONPATH = "internalServletActionPath";
public static final String REQUEST_PARAM_FRAMEDEST = "internalServletFrameDest";
}