diff options
Diffstat (limited to 'pdf-as-web/src')
17 files changed, 532 insertions, 16 deletions
| 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> | 
