diff options
Diffstat (limited to 'pdf-as-web')
18 files changed, 533 insertions, 16 deletions
diff --git a/pdf-as-web/build.gradle b/pdf-as-web/build.gradle index 908a8d41..31c34ac6 100644 --- a/pdf-as-web/build.gradle +++ b/pdf-as-web/build.gradle @@ -28,6 +28,7 @@ dependencies { compile project (':signature-standards:sigs-pades') compile project (':pdf-as-pdfbox') compile project (':pdf-as-web-status') + compile project (':pdf-as-web-statistic-api') compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.1' compile group: 'opensymphony', name: 'sitemesh', version: '2.4.2' compile "commons-codec:commons-codec:1.9" diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java index 46430724..8404fa65 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java @@ -47,7 +47,8 @@ public class WebConfiguration implements IConfigurationConstants { public static final String MOBILE_BKU_URL = "bku.mobile.url"; public static final String ERROR_DETAILS = "error.showdetails"; public static final String PDF_AS_WORK_DIR = "pdfas.dir"; - + public static final String STATISTIC_BACKEND_LIST = "statistic.backends"; + public static final String MOA_SS_ENABLED = "moa.enabled"; public static final String SOAP_SIGN_ENABLED = "soap.sign.enabled"; public static final String SOAP_VERIFY_ENABLED = "soap.verify.enabled"; @@ -252,6 +253,19 @@ public class WebConfiguration implements IConfigurationConstants { return properties.getProperty(KEYSTORE_LIST + "." + keyIdentifier + "." + KEYSTORE_KEY_PASS); } + public static List<String> getStatisticBackends() { + List<String> statisticBackends = new ArrayList<String>(); + String commaList = properties.getProperty(STATISTIC_BACKEND_LIST); + if(commaList != null) { + String[] commaLists = commaList.split(","); + for(int i = 0; i < commaLists.length; i++) { + statisticBackends.add(commaLists[i].trim()); + } + return statisticBackends; + } + return null; + } + public static boolean getMOASSEnabled() { String value = properties.getProperty(MOA_SS_ENABLED); if (value != null) { diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java new file mode 100644 index 00000000..504cf472 --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java @@ -0,0 +1,59 @@ +package at.gv.egiz.pdfas.web.filter; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UserAgentFilter implements Filter { + + private static final Logger logger = LoggerFactory + .getLogger(UserAgentFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // TODO Auto-generated method stub + + } + + private static final ThreadLocal<String> requestUserAgent = new ThreadLocal<String>() { + + @Override + protected String initialValue() { + return "unkown"; + } + + }; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + if(request instanceof HttpServletRequest) { + logger.debug("Processing Parameters into Attributes"); + HttpServletRequest httpRequest = (HttpServletRequest)request; + requestUserAgent.set(httpRequest.getHeader("User-Agent")); + } + try { + chain.doFilter(request, response); + } finally { + requestUserAgent.remove(); + } + } + + @Override + public void destroy() { + } + + public static String getUserAgent() { + return requestUserAgent.get(); + } + +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java index 93faf99a..5f8bfdcb 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java @@ -75,6 +75,7 @@ import at.gv.egiz.pdfas.sigs.pades.PAdESSignerKeystore; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; import at.gv.egiz.pdfas.web.servlets.UIEntryPointServlet; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; import at.gv.egiz.sl.schema.CreateCMSSignatureResponseType; import at.gv.egiz.sl.schema.InfoboxAssocArrayPairType; import at.gv.egiz.sl.schema.InfoboxReadRequestType; @@ -90,6 +91,7 @@ public class PdfAsHelper { private static final String PDF_STATUS = "PDF_STATUS"; private static final String PDF_OUTPUT = "PDF_OUTPUT"; private static final String PDF_SL_CONNECTOR = "PDF_SL_CONNECTOR"; + private static final String PDF_STATISTICS = "PDF_STATISTICS"; private static final String PDF_SIGNER = "PDF_SIGNER"; private static final String PDF_SL_INTERACTIVE = "PDF_SL_INTERACTIVE"; private static final String PDF_SIGNED_DATA = "PDF_SIGNED_DATA"; @@ -876,6 +878,18 @@ public class PdfAsHelper { HttpSession session = request.getSession(); session.setAttribute(PDF_SIGNED_DATA, signedData); } + + public static void setStatisticEvent(HttpServletRequest request, + HttpServletResponse response, StatisticEvent event) { + HttpSession session = request.getSession(); + session.setAttribute(PDF_STATISTICS, event); + } + + public static StatisticEvent getStatisticEvent(HttpServletRequest request, + HttpServletResponse response) { + HttpSession session = request.getSession(); + return (StatisticEvent)session.getAttribute(PDF_STATISTICS); + } public static void setLocale(HttpServletRequest request, HttpServletResponse response, String locale) { diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java index 86bef9f3..5b3fe82a 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java @@ -26,6 +26,7 @@ package at.gv.egiz.pdfas.web.servlets; import java.io.IOException; import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -44,6 +45,7 @@ import at.gv.egiz.sl.util.SLMarschaller; /** * Servlet implementation class DataURL */ +@MultipartConfig public class DataURLServlet extends HttpServlet { private static final long serialVersionUID = 1L; diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java index 8e59ff1c..4be3d7dd 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java @@ -35,10 +35,14 @@ import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.helper.HTMLFormater; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.UrlParameterExtractor; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; /** * Servlet implementation class ErrorPage @@ -88,6 +92,20 @@ public class ErrorPage extends HttpServlet { String errorURL = PdfAsHelper.getErrorURL(request, response); Throwable e = PdfAsHelper .getSessionException(request, response); + + StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request, response); + if(!statisticEvent.isLogged()) { + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + String message = PdfAsHelper.getSessionErrMessage(request, response); if (errorURL != null && WebConfiguration.isProvidePdfURLinWhitelist(errorURL)) { diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java index 120b9811..bd0bd935 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java @@ -38,14 +38,21 @@ import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; +import at.gv.egiz.pdfas.web.filter.UserAgentFilter; import at.gv.egiz.pdfas.web.helper.DigestHelper; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; import at.gv.egiz.pdfas.web.helper.RemotePDFFetcher; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; /** * Servlet implementation class Sign @@ -90,6 +97,12 @@ public class ExternSignServlet extends HttpServlet { String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); PdfAsHelper.setErrorURL(request, response, errorUrl); + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setStartNow(); + statisticEvent.setSource(Source.WEB); + statisticEvent.setOperation(Operation.SIGN); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + try { // Mandatory Parameters on Get Request: String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request); @@ -106,8 +119,19 @@ public class ExternSignServlet extends HttpServlet { } byte[] pdfData = RemotePDFFetcher.fetchPdfFile(pdfUrl); - doSignature(request, response, pdfData); + doSignature(request, response, pdfData, statisticEvent); } catch (Exception e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + PdfAsHelper.setSessionException(request, response, e.getMessage(), e); PdfAsHelper.gotoError(getServletContext(), request, response); @@ -128,6 +152,12 @@ public class ExternSignServlet extends HttpServlet { String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); PdfAsHelper.setErrorURL(request, response, errorUrl); + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setStartNow(); + statisticEvent.setSource(Source.WEB); + statisticEvent.setOperation(Operation.SIGN); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + try { byte[] filecontent = null; @@ -225,14 +255,33 @@ public class ExternSignServlet extends HttpServlet { if(source.equals("internal")) { request.setAttribute("FILEERR", true); request.getRequestDispatcher("index.jsp").forward(request, response); + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(new Exception("No file uploaded")); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + return; } } throw new PdfAsException("No Signature data available"); } - doSignature(request, response, filecontent); + doSignature(request, response, filecontent, statisticEvent); } catch (Exception e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + PdfAsHelper.setSessionException(request, response, e.getMessage(), e); PdfAsHelper.gotoError(getServletContext(), request, response); @@ -240,11 +289,15 @@ public class ExternSignServlet extends HttpServlet { } protected void doSignature(HttpServletRequest request, - HttpServletResponse response, byte[] pdfData) throws Exception { + HttpServletResponse response, byte[] pdfData, StatisticEvent statisticEvent) throws Exception { // Get Connector String connector = PdfAsParameterExtractor.getConnector(request); String transactionId = PdfAsParameterExtractor.getTransactionId(request); + + statisticEvent.setFilesize(pdfData.length); + statisticEvent.setProfileId(null); + statisticEvent.setDevice(connector); String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request); PdfAsHelper.setInvokeURL(request, response, invokeUrl); @@ -300,6 +353,8 @@ public class ExternSignServlet extends HttpServlet { } } + PdfAsHelper.setStatisticEvent(request, response, statisticEvent); + PdfAsHelper.startSignature(request, response, getServletContext(), pdfData, connector, PdfAsHelper.buildPosString(request, response), transactionId, PdfAsParameterExtractor .getSigType(request), PdfAsParameterExtractor.getPreProcessorMap(request)); @@ -334,9 +389,18 @@ public class ExternSignServlet extends HttpServlet { } } + + byte[] pdfSignedData = PdfAsHelper.synchornousSignature(request, response, pdfData); PdfAsHelper.setSignedPdf(request, response, pdfSignedData); + + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + PdfAsHelper.gotoProvidePdf(getServletContext(), request, response); return; } else { diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java index 483b9707..64bae47e 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java @@ -37,6 +37,9 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.api.ws.PDFASVerificationResponse; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; /** * Servlet implementation class PDFData @@ -79,6 +82,8 @@ public class PDFData extends HttpServlet { HttpServletResponse response) throws ServletException, IOException { byte[] signedData = PdfAsHelper.getSignedPdf(request, response); + StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request, response); + String plainPDFDigest = PdfAsParameterExtractor.getOrigDigest(request); if (signedData != null) { @@ -101,6 +106,15 @@ public class PDFData extends HttpServlet { response.setHeader("Signer-Certificate", pdfCert); } + if(!statisticEvent.isLogged()) { + statisticEvent.setStatus(Status.OK); + + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + PDFASVerificationResponse resp = PdfAsHelper.getPDFASVerificationResponse(request); if(resp != null) { response.setHeader("CertificateCheckCode", String.valueOf(resp.getCertificateCode())); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java index 53be36da..7100af3b 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java @@ -43,6 +43,7 @@ import at.gv.egiz.pdfas.web.exception.PdfAsStoreException; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; import at.gv.egiz.pdfas.web.helper.DigestHelper; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; import at.gv.egiz.pdfas.web.store.RequestStore; public class UIEntryPointServlet extends HttpServlet { @@ -85,6 +86,11 @@ public class UIEntryPointServlet extends HttpServlet { + " value"); } + StatisticEvent statisticEvent = RequestStore.getInstance() + .fetchStatisticEntry(storeId); + + PdfAsHelper.setStatisticEvent(req, resp, statisticEvent); + Connector connector = pdfAsRequest.getParameters().getConnector(); String invokeUrl = pdfAsRequest.getParameters().getInvokeURL(); @@ -149,16 +155,16 @@ public class UIEntryPointServlet extends HttpServlet { } } Map<String, String> map = null; - if(pdfAsRequest.getParameters().getPreprocessor() != null) { - map = pdfAsRequest.getParameters().getPreprocessor().getMap(); + if (pdfAsRequest.getParameters().getPreprocessor() != null) { + map = pdfAsRequest.getParameters().getPreprocessor() + .getMap(); } - + PdfAsHelper.startSignature(req, resp, getServletContext(), pdfAsRequest.getInputData(), connector.toString(), pdfAsRequest.getParameters().getPosition(), pdfAsRequest.getParameters().getTransactionId(), - pdfAsRequest.getParameters().getProfile(), - map); + pdfAsRequest.getParameters().getProfile(), map); } else { throw new PdfAsWebException("Invalid connector (" + Connector.BKU + " | " + Connector.ONLINEBKU + " | " diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java index 32bb41ac..a8beffeb 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java @@ -38,15 +38,22 @@ import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; +import at.gv.egiz.pdfas.web.filter.UserAgentFilter; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; import at.gv.egiz.pdfas.web.helper.RemotePDFFetcher; import at.gv.egiz.pdfas.web.helper.VerifyEncoder; import at.gv.egiz.pdfas.web.helper.VerifyResultEncoder; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; /** * Servlet implementation class VerifyServlet @@ -81,6 +88,13 @@ public class VerifyServlet extends HttpServlet { String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); PdfAsHelper.setErrorURL(request, response, errorUrl); + + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setStartNow(); + statisticEvent.setSource(Source.WEB); + statisticEvent.setOperation(Operation.VERIFY); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + try { // Mandatory Parameters on Get Request: String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request); @@ -97,8 +111,19 @@ public class VerifyServlet extends HttpServlet { } byte[] pdfData = RemotePDFFetcher.fetchPdfFile(pdfUrl); - doVerify(request, response, pdfData); + doVerify(request, response, pdfData, statisticEvent); } catch (Throwable e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + logger.warn("Generic Error: ", e); PdfAsHelper.setSessionException(request, response, e.getMessage(), e); @@ -118,6 +143,12 @@ public class VerifyServlet extends HttpServlet { String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); PdfAsHelper.setErrorURL(request, response, errorUrl); + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setStartNow(); + statisticEvent.setSource(Source.WEB); + statisticEvent.setOperation(Operation.VERIFY); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + try { byte[] filecontent = null; @@ -225,14 +256,33 @@ public class VerifyServlet extends HttpServlet { request.setAttribute("FILEERR", true); request.getRequestDispatcher("index.jsp").forward( request, response); + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(new Exception("No file uploaded")); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + return; } } throw new PdfAsException("No Signature data available"); } - doVerify(request, response, filecontent); + doVerify(request, response, filecontent, statisticEvent); } catch (Throwable e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + logger.warn("Generic Error: ", e); PdfAsHelper.setSessionException(request, response, e.getMessage(), e); @@ -241,7 +291,7 @@ public class VerifyServlet extends HttpServlet { } protected void doVerify(HttpServletRequest request, - HttpServletResponse response, byte[] pdfData) throws Exception { + HttpServletResponse response, byte[] pdfData, StatisticEvent statisticEvent) throws Exception { SignatureVerificationLevel lvl = PdfAsParameterExtractor .getVerificationLevel(request); @@ -270,6 +320,12 @@ public class VerifyServlet extends HttpServlet { encoder = VerifyEncoder.getEncoder(PdfAsParameterExtractor.PARAM_HTML); } + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + encoder.produce(request, response, results); } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java new file mode 100644 index 00000000..3c59a7cc --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java @@ -0,0 +1,111 @@ +package at.gv.egiz.pdfas.web.stats; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ServiceLoader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.web.config.WebConfiguration; + +public class StatisticFrontend implements StatisticBackend { + + private static StatisticFrontend _instance; + + private static ServiceLoader<StatisticBackend> backendLoader = ServiceLoader + .load(StatisticBackend.class); + + private static final Logger logger = LoggerFactory + .getLogger(StatisticFrontend.class); + + private List<StatisticBackend> statisticBackends = new ArrayList<StatisticBackend>(); + + private StatisticFrontend() { + Iterator<StatisticBackend> statisticIterator = backendLoader.iterator(); + List<String> enabledBackends = WebConfiguration.getStatisticBackends(); + + if (enabledBackends == null) { + logger.info("No statitistic backends configured using all available."); + } else { + Iterator<String> enabledBackendsIterator = enabledBackends + .iterator(); + logger.info("Allowing the following statistic backends:"); + while (enabledBackendsIterator.hasNext()) { + logger.info(" - {}", enabledBackendsIterator.next()); + } + } + + while (statisticIterator.hasNext()) { + StatisticBackend statisticBackend = statisticIterator.next(); + + if(enabledBackends == null || enabledBackends.contains(statisticBackend + .getName())) { + logger.info("adding Statistic Logger {} [{}]", statisticBackend + .getName(), statisticBackend.getClass().getName()); + + statisticBackends.add(statisticBackend); + } else { + logger.info("skipping Statistic Logger {} [{}]", statisticBackend + .getName(), statisticBackend.getClass().getName()); + } + } + + + Iterator<String> enabledBackendsIterator = enabledBackends + .iterator(); + while (enabledBackendsIterator.hasNext()) { + String enabledBackend = enabledBackendsIterator.next(); + statisticIterator = statisticBackends.iterator(); + boolean found = false; + while (statisticIterator.hasNext()) { + StatisticBackend statisticBackend = statisticIterator.next(); + if(statisticBackend.getName().equals(enabledBackend)) { + found = true; + break; + } + } + + if(!found) { + logger.warn("Failed to load statistic backend {}. Not in classpath?", enabledBackend); + } + } + } + + public static StatisticFrontend getInstance() { + if (_instance == null) { + _instance = new StatisticFrontend(); + } + return _instance; + } + + + @Override + public String getName() { + return StatisticFrontend.class.getSimpleName(); + } + + + @Override + public void storeEvent(StatisticEvent statisticEvent) { + + if(statisticEvent == null) { + logger.warn("Tried to log null as statisticEvent!"); + return; + } + + if(statisticEvent.isLogged()) { + logger.warn("Tried to relog statisticEvent!"); + return; + } + + Iterator<StatisticBackend> statisticBackendIterator = statisticBackends.iterator(); + + while(statisticBackendIterator.hasNext()) { + StatisticBackend statisticBackend = statisticBackendIterator.next(); + statisticBackend.storeEvent(statisticEvent); + } + } + +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticFileBackend.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticFileBackend.java new file mode 100644 index 00000000..531c47bf --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticFileBackend.java @@ -0,0 +1,56 @@ +package at.gv.egiz.pdfas.web.stats.impl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.web.stats.StatisticBackend; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; + +public class StatisticFileBackend implements StatisticBackend { + + public static final String NAME = "StatisticFileBackend"; + + public static final String STATISTIC_LOGGER = "at.gv.egiz.pdfas.web.statistics"; + + private static final Logger technical_logger = LoggerFactory + .getLogger(StatisticFileBackend.class); + private static final Logger statistic_logger = LoggerFactory + .getLogger(STATISTIC_LOGGER); + + private void addCSVValue(String value, StringBuilder sb) { + if (value != null) { + value = value.replace(';', ','); + sb.append(value); + } + sb.append(";"); + } + + private String getLogEntry(StatisticEvent statisticEvent) { + StringBuilder sb = new StringBuilder(); + addCSVValue(String.valueOf(statisticEvent.getTimestamp()), sb); + addCSVValue(statisticEvent.getOperation().getName(), sb); + addCSVValue(statisticEvent.getDevice(), sb); + addCSVValue(statisticEvent.getProfileId(), sb); + addCSVValue(String.valueOf(statisticEvent.getFilesize()), sb); + addCSVValue(statisticEvent.getUserAgent(), sb); + addCSVValue(statisticEvent.getStatus().getName(), sb); + addCSVValue((statisticEvent.getException() != null) ? statisticEvent + .getException().getMessage() : null, sb); + addCSVValue(String.valueOf(statisticEvent.getErrorCode()), sb); + addCSVValue(String.valueOf(statisticEvent.getDuration()), sb); + return sb.toString(); + } + + @Override + public void storeEvent(StatisticEvent statisticEvent) { + String entry = getLogEntry(statisticEvent); + technical_logger.trace("Stat log entry: {}", entry); + statistic_logger.info("{}", entry); + } + + @Override + public String getName() { + return NAME; + } + +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java index 82534aa3..f07a36ce 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java @@ -24,8 +24,10 @@ package at.gv.egiz.pdfas.web.store; import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; public interface IRequestStore { - public String createNewStoreEntry(PDFASSignRequest request); + public StatisticEvent fetchStatisticEntry(String id); + public String createNewStoreEntry(PDFASSignRequest request, StatisticEvent event); public PDFASSignRequest fetchStoreEntry(String id); } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java index 6ec61292..f712a894 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.UUID; import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; public class InMemoryRequestStore implements IRequestStore { @@ -34,14 +35,25 @@ public class InMemoryRequestStore implements IRequestStore { } private HashMap<String, PDFASSignRequest> store = new HashMap<String, PDFASSignRequest>(); + private HashMap<String, StatisticEvent> statEvents = new HashMap<String, StatisticEvent>(); - public String createNewStoreEntry(PDFASSignRequest request) { + public String createNewStoreEntry(PDFASSignRequest request, StatisticEvent event) { UUID id = UUID.randomUUID(); String sid = id.toString(); this.store.put(sid, request); + this.statEvents.put(sid, event); return sid; } + public StatisticEvent fetchStatisticEntry(String id) { + if(statEvents.containsKey(id)) { + StatisticEvent event = statEvents.get(id); + statEvents.remove(id); + return event; + } + return null; + } + public PDFASSignRequest fetchStoreEntry(String id) { if(store.containsKey(id)) { PDFASSignRequest request = store.get(id); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java index 91aec279..e3b57b28 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java @@ -41,10 +41,17 @@ import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; import at.gv.egiz.pdfas.api.ws.PDFASSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSigning; import at.gv.egiz.pdfas.api.ws.VerificationLevel; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; import at.gv.egiz.pdfas.web.config.WebConfiguration; +import at.gv.egiz.pdfas.web.filter.UserAgentFilter; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; import at.gv.egiz.pdfas.web.store.RequestStore; @MTOM @@ -72,6 +79,11 @@ public class PDFASSigningImpl implements PDFASSigning { return null; } + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setSource(Source.SOAP); + statisticEvent.setOperation(Operation.SIGN); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + statisticEvent.setStartNow(); PDFASSignResponse response = new PDFASSignResponse(); try { if(request.getParameters().getConnector() == null) { @@ -79,6 +91,10 @@ public class PDFASSigningImpl implements PDFASSigning { "Invalid connector value!"); } + statisticEvent.setFilesize(request.getInputData().length); + statisticEvent.setProfileId(request.getParameters().getProfile()); + statisticEvent.setDevice(request.getParameters().getConnector().toString()); + Map<String, String> preProcessor = null; if(request.getParameters().getPreprocessor() != null) { preProcessor = request.getParameters().getPreprocessor().getMap(); @@ -122,6 +138,21 @@ public class PDFASSigningImpl implements PDFASSigning { verifyResult = verResults.get(0); } + if(verifyResult.getValueCheckCode().getCode() == 0) { + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } else { + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setErrorCode(verifyResult.getValueCheckCode().getCode()); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + response.getVerificationResponse().setCertificateCode( verifyResult.getCertificateCheck().getCode()); response.getVerificationResponse().setValueCode( @@ -130,7 +161,7 @@ public class PDFASSigningImpl implements PDFASSigning { } else { // Signatures with user interaction!! String id = RequestStore.getInstance().createNewStoreEntry( - request); + request, statisticEvent); if (id == null) { throw new WebServiceException("Failed to store request"); @@ -149,6 +180,17 @@ public class PDFASSigningImpl implements PDFASSigning { response.setRedirectUrl(userEntryURL); } } catch (Throwable e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + logger.warn("Error in Soap Service", e); if (e.getCause() != null) { response.setError(e.getCause().getMessage()); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java index e46da89e..fcfe2a42 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java @@ -18,10 +18,17 @@ import at.gv.egiz.pdfas.api.ws.PDFASVerifyRequest; import at.gv.egiz.pdfas.api.ws.PDFASVerifyResponse; import at.gv.egiz.pdfas.api.ws.PDFASVerifyResult; import at.gv.egiz.pdfas.api.ws.VerificationLevel; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; import at.gv.egiz.pdfas.web.config.WebConfiguration; +import at.gv.egiz.pdfas.web.filter.UserAgentFilter; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; +import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; +import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; @MTOM @WebService(endpointInterface = "at.gv.egiz.pdfas.api.ws.PDFASVerification") @@ -37,6 +44,12 @@ public class PDFASVerificationImpl implements PDFASVerification { return null; } + StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setSource(Source.SOAP); + statisticEvent.setOperation(Operation.VERIFY); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + statisticEvent.setStartNow(); + PDFASVerifyResponse response = new PDFASVerifyResponse(); response.setVerifyResults(new ArrayList<PDFASVerifyResult>()); try { @@ -60,6 +73,10 @@ public class PDFASVerificationImpl implements PDFASVerification { lvl = SignatureVerificationLevel.FULL_VERIFICATION; } + statisticEvent.setFilesize(request.getInputData().length); + statisticEvent.setProfileId(null); + statisticEvent.setDevice(request.getVerificationLevel().toString()); + List<VerifyResult> results = PdfAsHelper.synchornousVerify( request.getInputData(), sigIdx, lvl, preProcessor); @@ -111,7 +128,24 @@ public class PDFASVerificationImpl implements PDFASVerification { response.getVerifyResults().add(webResult); } - } catch (Exception e) { + + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } catch (Throwable e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if(e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError)e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + logger.warn("Failed to verify PDF", e); if (WebConfiguration.isShowErrorDetails()) { throw new WebServiceException("Generic Error", e); diff --git a/pdf-as-web/src/main/resources/META-INF/services/at.gv.egiz.pdfas.web.stats.StatisticBackend b/pdf-as-web/src/main/resources/META-INF/services/at.gv.egiz.pdfas.web.stats.StatisticBackend new file mode 100644 index 00000000..d77e0d54 --- /dev/null +++ b/pdf-as-web/src/main/resources/META-INF/services/at.gv.egiz.pdfas.web.stats.StatisticBackend @@ -0,0 +1 @@ +at.gv.egiz.pdfas.web.stats.impl.StatisticFileBackend
\ No newline at end of file diff --git a/pdf-as-web/src/main/webapp/WEB-INF/web.xml b/pdf-as-web/src/main/webapp/WEB-INF/web.xml index f8b886ca..b6cfb46d 100644 --- a/pdf-as-web/src/main/webapp/WEB-INF/web.xml +++ b/pdf-as-web/src/main/webapp/WEB-INF/web.xml @@ -16,9 +16,16 @@ <filter-class>at.gv.egiz.pdfas.web.filter.ExceptionCatchFilter</filter-class> </filter> <filter> + <filter-name>UserAgentFilter</filter-name> + <display-name>UserAgentFilter</display-name> + <description></description> + <filter-class>at.gv.egiz.pdfas.web.filter.UserAgentFilter</filter-class> + </filter> + <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> </filter> + <!-- filter-mapping> <filter-name>sitemesh</filter-name> @@ -28,6 +35,10 @@ <filter-name>ExceptionCatchFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> + <filter-mapping> + <filter-name>UserAgentFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> <!-- listener> <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class> |