package com.cfinkel.reports.web;
import com.cfinkel.reports.ReportSessionInfo;
import com.cfinkel.reports.exceptions.BadReportSyntaxException;
import com.cfinkel.reports.exceptions.InvalidInputException;
import com.cfinkel.reports.generatedbeans.ReportElement;
import com.cfinkel.reports.util.Util;
import com.cfinkel.reports.wrappers.Report;
import org.apache.log4j.Logger;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* $Author:charles $
* $Revision:10429 $
* $Date:2006-07-26 18:00:43 -0400 (Wed, 26 Jul 2006) $
**/
public class ReportController implements Filter {
private static final Logger log = Logger.getLogger(ReportController.class);
public void init (FilterConfig filterConfig) {
}
public void doFilter (ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession();
// get report path:
String reportPath = request.getServletPath().substring(
AppData.getReportsURL().length(),
request.getServletPath().length()
);
// allow js, images, and css to go through:
if (reportPath.startsWith("/js") || reportPath.startsWith("/css") || reportPath.startsWith("/images")
|| (reportPath.startsWith("/img")) ) {
chain.doFilter(request,response);
return;
}
//set response content:
GlobalController.setHtmlResponseContent(request,response);
if (reportPath.length() == 0 ||
(Util.equalsAnyIgnoreCase(reportPath,"/","") ) ) {
// forward to welcome page:
RequestDispatcher rd = request.getRequestDispatcher("/welcome.jsp");
rd.include(request,response);
return;
}
// lock for reads now:
AppData.getReportsLock().readLock().lock();
try {
Map<String, Report> reports = AppData.getReports();
Report report = reports.get(reportPath);
if (report == null) {
try {
report = createReport(reportPath);
// add report to app scope:
reports.put(reportPath,report);
} catch (JAXBException e) {
log.info("Error unmarshalling XML report", e);
if ((e.getLinkedException() != null) &&
(e.getLinkedException() instanceof FileNotFoundException)) {
RequestDispatcher rd = request.getRequestDispatcher("/report_not_found.jsp");
rd.include(request, response);
} else {
RequestDispatcher rd = request.getRequestDispatcher("/bad_syntax.jsp");
request.setAttribute("error", e);
rd.include(request, response);
}
return;
} catch (BadReportSyntaxException e) {
log.info("Bad Report Syntax", e);
RequestDispatcher rd = request.getRequestDispatcher("/invalid_xml.jsp");
request.setAttribute("error", e);
rd.include(request, response);
return;
}
}
ReportSessionInfo reportSessionInfo = getReportSessionInfo(report,session,reportPath);
request.setAttribute(AttributeNames.reportSessionInfo,reportSessionInfo);
// check if user has access to this report:
if (report.hasAccess(request)) {
try {
if (request.getParameter(ParameterNames.clearData) != null) {
reportSessionInfo.clearCachedData();
response.sendRedirect(request.getContextPath() + request.getServletPath());
return;
}
if ((request.getParameter(ParameterNames.run) != null) || report.getAllInputs().size() == 0) {
Map<String, List> reportData = reportSessionInfo.runReport(request.getParameterMap());
request.setAttribute(AttributeNames.reportData,reportData);
} else if (reportSessionInfo.isReportWasRunAndDataWasNotCleared()) {
Map<String, List> reportData = reportSessionInfo.runOnlyForNonCachedData();
request.setAttribute(AttributeNames.reportData,reportData);
}
} catch (InvalidInputException e) {
log.info("invalid input exception",e); // should not happen
throw new ServletException(e);
} catch (ParseException e) {
log.info("parse exception",e); // should not happen
throw new ServletException(e);
} catch (RuntimeException e) {
log.info("RuntimeException", e);
RequestDispatcher rd = request.getRequestDispatcher("/exception.jsp");
request.setAttribute("exception", e);
rd.include(request, response);
return;
}
// include jsp:
RequestDispatcher rd = request.getRequestDispatcher("/report.jsp");
rd.include(request, response);
} else {
// no access to report:
RequestDispatcher rd = request.getRequestDispatcher("/no_access.jsp");
rd.include(request, response);
}
}
catch (Exception e) {
log.error("Exception running report", e);
}
finally {
AppData.getReportsLock().readLock().unlock();
}
}
private Report createReport(String reportPath) throws JAXBException, BadReportSyntaxException {
JAXBContext jc = AppData.getJAXBContext();
Unmarshaller u = jc.createUnmarshaller();
ReportElement reportElement = (ReportElement) u.unmarshal
(new File(AppData.getReportsDirectory() + reportPath + ".xml"));
return new Report(reportElement, reportPath);
}
private ReportSessionInfo getReportSessionInfo(Report report, HttpSession session ,String reportPath) {
Map<String, ReportSessionInfo> reportSessionInfos;
if (session.getAttribute(AttributeNames.reportSessionInfos) == null) {
reportSessionInfos = new HashMap<String,ReportSessionInfo>();
session.setAttribute(AttributeNames.reportSessionInfos,reportSessionInfos);
} else {
reportSessionInfos = (Map<String, ReportSessionInfo>)session.getAttribute(AttributeNames.reportSessionInfos);
}
ReportSessionInfo reportSessionInfo;
if (reportSessionInfos.get(reportPath) == null) {
reportSessionInfo = new ReportSessionInfo(report);
reportSessionInfos.put(reportPath, reportSessionInfo);
} else {
reportSessionInfo = reportSessionInfos.get(reportPath);
}
return reportSessionInfo;
}
public void destroy () {
}
}