From d89f36b67ea1d838a78523538a24e044518f3587 Mon Sep 17 00:00:00 2001 From: mcentner Date: Tue, 26 Jan 2010 16:22:56 +0000 Subject: MOCCA 1.2.11 with SHA-2 enabled. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/branches/mocca-1.2.11-sha2@599 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../accesscontroller/SpringSecurityManager.java | 63 ++++ .../egiz/bku/online/conf/SpringConfigurator.java | 127 +++++++ .../egiz/bku/online/webapp/AppletDispatcher.java | 113 ++++++ .../egiz/bku/online/webapp/BKURequestHandler.java | 317 +++++++++++++++++ .../gv/egiz/bku/online/webapp/ResultServlet.java | 154 ++++++++ .../gv/egiz/bku/online/webapp/SessionTimeout.java | 49 +++ .../gv/egiz/bku/online/webapp/ShutdownHandler.java | 48 +++ .../egiz/bku/online/webapp/SpringBKUServlet.java | 37 ++ .../service/impl/RequestBrokerSTALFactory.java | 45 +++ .../egiz/stal/service/impl/STALRequestBroker.java | 41 +++ .../stal/service/impl/STALRequestBrokerImpl.java | 324 +++++++++++++++++ .../gv/egiz/stal/service/impl/STALServiceImpl.java | 386 +++++++++++++++++++++ .../stal/service/impl/STALXJAXBContextFactory.java | 61 ++++ .../egiz/stal/service/impl/TestSignatureData.java | 47 +++ 14 files changed, 1812 insertions(+) create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java create mode 100644 mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java (limited to 'mocca-1.2.11/BKUOnline/src/main/java') diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java new file mode 100644 index 00000000..5795478b --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java @@ -0,0 +1,63 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.online.accesscontroller; + +import java.io.IOException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +import at.gv.egiz.bku.accesscontroller.SecurityManagerFacade; +import at.gv.egiz.bku.conf.Configurator; + +public class SpringSecurityManager extends SecurityManagerFacade implements + ResourceLoaderAware { + + private ResourceLoader resourceLoader; + + private static Log log = LogFactory.getLog(SpringSecurityManager.class); + + protected Configurator config; + + public void setConfig(Configurator config) { + this.config = config; + } + + public void init() { + String noMatch = config.getProperty("AccessController.acceptNoMatch"); + if (noMatch != null) { + log.debug("Setting allow now match to: " + noMatch); + setAllowUnmatched(Boolean.getBoolean(noMatch)); + } + String policy = config.getProperty("AccessController.policyResource"); + log.info("Loading resource: " + policy); + try { + Resource res = resourceLoader.getResource(policy); + init(res.getInputStream()); + } catch (IOException e) { + log.error(e); + } + } + + @Override + public void setResourceLoader(ResourceLoader loader) { + this.resourceLoader = loader; + } +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java new file mode 100644 index 00000000..6030c1c0 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java @@ -0,0 +1,127 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.online.conf; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +import at.gv.egiz.bku.conf.Configurator; +import at.gv.egiz.bku.online.webapp.SpringBKUServlet; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.stal.service.impl.RequestBrokerSTALFactory; + +public class SpringConfigurator extends Configurator implements + ResourceLoaderAware { + + private final static Log log = LogFactory.getLog(SpringConfigurator.class); + + private ResourceLoader resourceLoader; + + public void setResource(Resource resource) { + log.debug("Loading config from: " + resource); + if (resource != null) { + Properties props = new Properties(); + try { + props.load(resource.getInputStream()); + super.setConfiguration(props); + } catch (IOException e) { + log.error("Cannot load config", e); + } + } else { + log.warn("Cannot load properties, resource: " + resource); + } + } + + public void configureNetwork() { + super.configureNetwork(); + String appletTimeout = getProperty("AppletTimeout"); + if ((appletTimeout != null)) { + try { + long ato = Long.parseLong(appletTimeout); + log.debug("Setting applet timeout to:"+ato); + RequestBrokerSTALFactory.setTimeout(ato); + } catch (NumberFormatException nfe) { + log.error("Cannot set Applettimeout", nfe); + } + + } + } + + public void configure() { + super.configure(); + SpringBKUServlet.setConfigurator(this); + } + + @Override + public void setResourceLoader(ResourceLoader loader) { + this.resourceLoader = loader; + } + + private File getDirectory(String property) { + if (property != null) { + Resource certDirRes = resourceLoader.getResource(property); + File certDir; + try { + certDir = certDirRes.getFile(); + } catch (IOException e) { + log.error("Cannot get cert directory", e); + throw new SLRuntimeException(e); + } + if (!certDir.isDirectory()) { + log.error("Expecting directory as SSL.certDirectory parameter"); + throw new SLRuntimeException( + "Expecting directory as SSL.certDirectory parameter"); + } + return certDir; + } + return null; + + } + + @Override + protected File getCADir() { + String caDirectory = getProperty("SSL.caDirectory"); + return getDirectory(caDirectory); + } + + @Override + protected File getCertDir() { + String certDirectory = getProperty("SSL.certDirectory"); + return getDirectory(certDirectory); + } + + @Override + protected InputStream getManifest() { + Resource r = resourceLoader.getResource("META-INF/MANIFEST.MF"); + if (r != null) { + try { + return r.getInputStream(); + } catch (IOException e) { + log.error("Cannot read manifest data:", e); + } + } + return null; + } +} \ No newline at end of file diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java new file mode 100644 index 00000000..24938cd5 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java @@ -0,0 +1,113 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package at.gv.egiz.bku.online.webapp; + +import java.io.IOException; +import java.util.regex.Pattern; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * prevent applet caching, + * could be removed once applet is loaded via jnlp + * + * @author Clemens Orthacker + */ +public class AppletDispatcher extends HttpServlet { + + protected final static Log log = LogFactory.getLog(AppletDispatcher.class); + + public static final String DISPATCH_CTX = "dispatch/"; + public static final String RAND_PREFIX = "__"; + public static final String RAND_ATTRIBUTE = "rand"; + public static final Pattern ctxPattern = Pattern.compile(DISPATCH_CTX); + public static final Pattern archivePattern = Pattern.compile(RAND_PREFIX + "[a-zA-Z0-9]*\\.jar$"); + + /** + * Processes requests for both HTTP GET and POST methods. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + String uri = request.getRequestURI(); +// log.trace("request URI " + uri); + + uri = uri.substring(request.getContextPath().length()); +// log.trace("removing contextPath " + uri); + + uri = ctxPattern.matcher(uri).replaceAll(""); +// log.trace("removing dispatch context " + uri); + + uri = archivePattern.matcher(uri).replaceAll(".jar"); +// log.trace("removing random suffix " + uri); + + if (log.isTraceEnabled()) { + log.trace("dispatching request URI " + request.getRequestURI() + + " to " + uri); + } + + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(uri); + dispatcher.forward(request, response); + } + + // + /** + * Handles the HTTP GET method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Handles the HTTP POST method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Returns a short description of the servlet. + * @return a String containing servlet description + */ + @Override + public String getServletInfo() { + return "Short description"; + }// + +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java new file mode 100644 index 00000000..7dfec211 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java @@ -0,0 +1,317 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.online.webapp; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.binding.BindingProcessor; +import at.gv.egiz.bku.binding.HTTPBindingProcessor; +import at.gv.egiz.bku.binding.HttpUtil; +import at.gv.egiz.bku.binding.IdFactory; +import at.gv.egiz.bku.utils.StreamUtil; +import at.gv.egiz.org.apache.tomcat.util.http.AcceptLanguage; + +/** + * Handles SL requests and instantiates BindingProcessors + * + */ +public class BKURequestHandler extends SpringBKUServlet { + + private static final long serialVersionUID = 1L; + + public static final String APPLET_PAGE_P = "appletPage"; + public static final String APPLET_PAGE_DEFAULT = "BKUApplet"; + + public static final String PARAM_APPLET_WIDTH = "appletWidth"; + public static final String ATTR_APPLET_WIDTH = "appletWidth"; + + public static final String PARAM_APPLET_HEIGHT = "appletHeight"; + public static final String ATTR_APPLET_HEIGHT = "appletHeight"; + + public static final String PARAM_APPLET_BACKGROUND = "appletBackground"; + public static final String ATTR_APPLET_BACKGROUND = "appletBackground"; + + public static final String PARAM_APPLET_BACKGROUND_COLOR = "appletBackgroundColor"; + public static final String ATTR_APPLET_BACKGROUND_COLOR = "appletBackgroundColor"; + public static final Pattern PATTERM_APPLET_BACKGROUND_COLOR = Pattern.compile("\\#[0-9a-fA-F]{6}"); + + public static final String PARAM_APPLET_GUI_STYLE = "appletGuiStyle"; + public static final String ATTR_APPLET_GUI_STYLE = "appletGuiStyle"; + public static final String[] VALUES_APPLET_GUI_STYLE = new String[] {"tiny", "simple", "advanced"}; + + public static final String PARAM_APPLET_EXTENSION = "appletExtension"; + public static final String ATTR_APPLET_EXTENSION = "appletExtension"; + public static final String[] VALUES_APPLET_EXTENSION = new String[] {"pin", "activation"}; + + public static final String PARAM_LOCALE = "locale"; + public static final String ATTR_LOCALE = "locale"; + public static final Pattern PATTERN_LOCALE = Pattern.compile("[a-zA-Z][a-zA-Z](_[a-zA-Z][a-zA-Z]){0,2}"); + + public final static String REDIRECT_URL_SESSION_ATTRIBUTE = "redirectUrl"; + + protected Log log = LogFactory.getLog(BKURequestHandler.class); + + private static String getStringFromStream(InputStream is, String encoding) + throws IOException { + if (is == null) { + return null; + } + if (encoding == null) { + encoding = HttpUtil.DEFAULT_CHARSET; + } + ByteArrayOutputStream os = new ByteArrayOutputStream(); + StreamUtil.copyStream(is, os); + return new String(os.toByteArray(), encoding); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, java.io.IOException { + log.debug("Received SecurityLayer request"); + + HttpSession session = req.getSession(false); + if (session != null) { + log.warn("Already a session with id: " + session.getId() + + " active, trying to get Bindingprocessor"); + BindingProcessor bp = getBindingProcessorManager().getBindingProcessor( + IdFactory.getInstance().createId(session.getId())); + if (bp != null) { + log.debug("Found binding processor, using this one"); + String appletPage = getStringFromStream( + ((HTTPBindingProcessor) bp).getFormData(APPLET_PAGE_P), + req.getCharacterEncoding()); + getDispatcher(appletPage).forward(req, resp); + return; + } + log.debug("Did not find a binding processor, creating new ..."); + } + session = req.getSession(true); + if (log.isDebugEnabled()) { + log.debug("Using session id: " + session.getId()); + } + + String acceptLanguage = req.getHeader("Accept-Language"); + Locale locale = AcceptLanguage.getLocale(acceptLanguage); + log.debug("Accept-Language locale: " + locale); + + HTTPBindingProcessor bindingProcessor; + bindingProcessor = (HTTPBindingProcessor) getBindingProcessorManager() + .createBindingProcessor(req.getRequestURL().toString(), + session.getId(), locale); + + Map headerMap = new HashMap(); + for (Enumeration headerName = req.getHeaderNames(); headerName + .hasMoreElements();) { + String header = headerName.nextElement(); + if (header != null) { + headerMap.put(header, req.getHeader(header)); + } + } + String charset = req.getCharacterEncoding(); + String contentType = req.getContentType(); + if (charset != null) { + contentType += ";" + charset; + } + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + bindingProcessor.setHTTPHeaders(headerMap); + bindingProcessor.consumeRequestStream(req.getInputStream()); + req.getInputStream().close(); + getBindingProcessorManager().process(bindingProcessor); + + log.trace("Trying to find applet parameters in request"); + + // appletWidth + String width = getStringFromStream(bindingProcessor + .getFormData(PARAM_APPLET_WIDTH), charset); + if (width != null) { + try { + // must be a valid integer + session.setAttribute(ATTR_APPLET_WIDTH, Integer.parseInt(width)); + log.trace("Found parameter " + PARAM_APPLET_WIDTH + "='" + width +"'."); + } catch (NumberFormatException nfe) { + log.warn("Applet parameter " + PARAM_APPLET_WIDTH + + " does not contain a valid value.", nfe); + } + } + + // appletHeight + String height = getStringFromStream(bindingProcessor + .getFormData(PARAM_APPLET_HEIGHT), charset); + if (height != null) { + try { + // must be a valid integer + session.setAttribute(ATTR_APPLET_HEIGHT, Integer.parseInt(height)); + log.trace("Found parameter " + PARAM_APPLET_HEIGHT + "='" + height + "'."); + } catch (NumberFormatException nfe) { + log.warn("Applet parameter " + PARAM_APPLET_HEIGHT + + " does not contain a valid value.", nfe); + } + } + + // appletBackground + String background = getStringFromStream(bindingProcessor + .getFormData(PARAM_APPLET_BACKGROUND), charset); + if (background != null) { + session.setAttribute(ATTR_APPLET_BACKGROUND, background); + try { + // must be a valid http or https URL + URI backgroundURL = new URI(background); + if ("http".equals(backgroundURL.getScheme()) + || "https".equals(backgroundURL.getScheme())) { + session.setAttribute(ATTR_APPLET_BACKGROUND, backgroundURL.toASCIIString()); + log.trace("Found parameter " + PARAM_APPLET_BACKGROUND + "='" + + backgroundURL.toASCIIString() + "'."); + } else { + log.warn("Applet parameter " + PARAM_APPLET_BACKGROUND + "='" + + background + "' is not a valid http/https URL."); + } + } catch (URISyntaxException e) { + log.warn("Applet parameter " + PARAM_APPLET_BACKGROUND + "='" + + background + "' is not a valid http/https URL.", e); + } + } + + // appletBackgroundColor + String backgroundColor = getStringFromStream(bindingProcessor + .getFormData(PARAM_APPLET_BACKGROUND_COLOR), charset); + if (backgroundColor != null) { + // must be a valid color definition + if (PATTERM_APPLET_BACKGROUND_COLOR.matcher(backgroundColor).matches()) { + session.setAttribute(ATTR_APPLET_BACKGROUND_COLOR, backgroundColor); + log.trace("Faund parameter " + PARAM_APPLET_BACKGROUND_COLOR + "='" + + backgroundColor + "'."); + } else { + log.warn("Applet parameter " + PARAM_APPLET_BACKGROUND_COLOR + "='" + + backgroundColor + "' is not a valid color definition (must be of form '#hhhhhh')."); + } + } + + // appletGuiStyle + String guiStyle = getStringFromStream(bindingProcessor + .getFormData(PARAM_APPLET_GUI_STYLE), charset); + if (guiStyle != null) { + // must be one of VALUES_APPLET_GUI_STYLE + String style = guiStyle.toLowerCase(); + if (Arrays.asList(VALUES_APPLET_GUI_STYLE).contains(style)) { + session.setAttribute(ATTR_APPLET_GUI_STYLE, style); + log.trace("Found parameter " + PARAM_APPLET_GUI_STYLE + "='" + + style + "'."); + } else { + StringBuilder sb = new StringBuilder(); + sb.append("Applet parameter ").append(PARAM_APPLET_GUI_STYLE).append( + "='").append(guiStyle).append("' is not valid (must be one of ") + .append(Arrays.toString(VALUES_APPLET_GUI_STYLE)).append(")."); + log.warn(sb); + } + } + + // appletExtension + String extension = getStringFromStream(bindingProcessor + .getFormData(PARAM_APPLET_EXTENSION), charset); + if (extension != null) { + // must be one of VALUES_APPLET_EXTENSION + String ext = extension.toLowerCase(); + if (Arrays.asList(VALUES_APPLET_EXTENSION).contains(ext)) { + session.setAttribute(ATTR_APPLET_EXTENSION, ext); + log.trace("Found parameter " + PARAM_APPLET_EXTENSION + "='" + + ext + "'."); + } else { + StringBuilder sb = new StringBuilder(); + sb.append("Applet parameter ").append(PARAM_APPLET_EXTENSION).append( + "='").append(extension).append("' is not valid (must be one of ") + .append(Arrays.toString(VALUES_APPLET_EXTENSION)).append(")."); + log.warn(sb); + } + } + + // locale + String localeFormParam = getStringFromStream(bindingProcessor + .getFormData(PARAM_LOCALE), charset); + if (localeFormParam != null) { + // must be a valid locale + if (PATTERN_LOCALE.matcher(localeFormParam).matches()) { + locale = new Locale(localeFormParam); + log.debug("Overrule accept-language header locale " + locale + + " with form param " + localeFormParam + "."); + } else { + log.warn("Parameter " + PARAM_LOCALE + "='" + localeFormParam + + "' is not a valid locale definition."); + } + } + if (locale != null) { + log.debug("Using locale " + locale); + session.setAttribute(ATTR_LOCALE, locale.toString()); + } + + // handle server side redirect url after processing + String redirectUrl = bindingProcessor.getRedirectURL(); + if ( redirectUrl != null) { + log.info("Got redirect URL "+redirectUrl+". Deferring browser redirect."); + session.setAttribute(REDIRECT_URL_SESSION_ATTRIBUTE, redirectUrl); + } + + String appletPage = getStringFromStream(bindingProcessor + .getFormData(APPLET_PAGE_P), charset); + getDispatcher(appletPage).forward(req, resp); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, java.io.IOException { + doPost(req, resp); + } + + private RequestDispatcher getDispatcher(String appletPage) { + RequestDispatcher dispatcher = null; + if (appletPage != null) { + log.trace("requested appletPage " + appletPage); + dispatcher = getServletContext().getNamedDispatcher(appletPage); + } + if (dispatcher == null) { + log.debug("no appletPage requested or appletPage not configured, using default"); + appletPage = APPLET_PAGE_DEFAULT; + dispatcher = getServletContext().getNamedDispatcher(appletPage); + } +// session.setAttribute(APPLET_PAGE_P, appletPage); + log.debug("forward to applet " + appletPage); + + return dispatcher; + } + +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java new file mode 100644 index 00000000..5ffe2399 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java @@ -0,0 +1,154 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.online.webapp; + +import java.io.IOException; +import java.util.Iterator; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.binding.HTTPBindingProcessor; +import at.gv.egiz.bku.binding.HttpUtil; +import at.gv.egiz.bku.binding.IdFactory; +import at.gv.egiz.bku.conf.Configurator; +import at.gv.egiz.bku.utils.NullOutputStream; + +/** + * Delivers the result to the browser + * + */ +public class ResultServlet extends SpringBKUServlet { + + private final static Log log = LogFactory.getLog(ResultServlet.class); + + private String encoding = "UTF-8"; + private String expiredPage = "./expiredError.jsp"; + + public ResultServlet() { + } + + private void myInit() { + String enc = getServletContext().getInitParameter("responseEncoding"); + if (enc != null) { + log.debug("Init default encoding to: " + enc); + encoding = enc; + } + String expP = getServletConfig().getInitParameter("expiredPage"); + if (expP != null) { + log.debug("Init expired page to: " + expP); + expiredPage = expP; + } + } + + @Override + public void init() throws ServletException { + super.init(); + myInit(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + myInit(); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + doGet(req, resp); + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, java.io.IOException { + String version = configurator.getProperty(Configurator.SIGNATURE_LAYOUT); + if ((version != null) && (!"".equals(version.trim()))) { + log.debug("setting SignatureLayout header to " + version); + resp.setHeader(Configurator.SIGNATURE_LAYOUT, version); + } else { + log.debug("do not set SignatureLayout header"); + } + + if (configurator.getProperty(Configurator.USERAGENT_CONFIG_P) != null) { + resp.setHeader(HttpUtil.HTTP_HEADER_SERVER, configurator + .getProperty(Configurator.USERAGENT_CONFIG_P)); + } else { + resp.setHeader(HttpUtil.HTTP_HEADER_SERVER, + Configurator.USERAGENT_DEFAULT); + } + + HttpSession session = req.getSession(false); + if (session == null) { + resp.sendRedirect(expiredPage); + return; + } + String sessionId = session.getId(); + if (sessionId == null) { + resp.sendRedirect(expiredPage); + return; + } + log.debug("Got a result request for session: " + sessionId); + HTTPBindingProcessor bp = (HTTPBindingProcessor) getBindingProcessorManager() + .getBindingProcessor(IdFactory.getInstance().createId(sessionId)); + if (bp == null) { + session.invalidate(); + resp.sendRedirect(expiredPage); + return; + } + String redirectUrl = (String) session + .getAttribute(BKURequestHandler.REDIRECT_URL_SESSION_ATTRIBUTE); + if (redirectUrl == null) { + redirectUrl = bp.getRedirectURL(); + } + if (redirectUrl != null) { + try { + bp.writeResultTo(new NullOutputStream(), encoding); + getBindingProcessorManager().removeBindingProcessor(bp.getId()); + } finally { + log.info("Executing deferred browser redirect to: " + redirectUrl); + resp.sendRedirect(redirectUrl); + session.invalidate(); + } + return; + } + + log.trace("setting response code: " + bp.getResponseCode()); + resp.setStatus(bp.getResponseCode()); + resp.setHeader("Cache-Control", "no-store"); // HTTP 1.1 + resp.setHeader("Pragma", "no-cache"); // HTTP 1.0 + resp.setDateHeader("Expires", 0); + for (Iterator it = bp.getResponseHeaders().keySet().iterator(); it + .hasNext();) { + String header = it.next(); + if (log.isTraceEnabled()) { + log.trace("setting response header " + header + ": " + bp.getResponseHeaders().get(header)); + } + resp.setHeader(header, bp.getResponseHeaders().get(header)); + } + resp.setContentType(bp.getResultContentType()); + resp.setCharacterEncoding(encoding); + bp.writeResultTo(resp.getOutputStream(), encoding); + resp.getOutputStream().flush(); + session.invalidate(); + getBindingProcessorManager().removeBindingProcessor(bp.getId()); + } +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java new file mode 100644 index 00000000..2b56166c --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java @@ -0,0 +1,49 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.online.webapp; + +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.binding.BindingProcessorManager; +import at.gv.egiz.bku.binding.IdFactory; + +/** + * Session listener to trigger the removal of the BindingProcessor + * + */ +public class SessionTimeout implements HttpSessionListener { + + private static Log log = LogFactory.getLog(SessionTimeout.class); + + @Override + public void sessionCreated(HttpSessionEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void sessionDestroyed(HttpSessionEvent event) { + BindingProcessorManager manager = (BindingProcessorManager) event.getSession().getServletContext().getAttribute(SpringBKUServlet.BEAN_NAME); + log.info("Removing session: "+event.getSession().getId()); + manager.removeBindingProcessor(IdFactory.getInstance().createId(event.getSession().getId())); + } + +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java new file mode 100644 index 00000000..741b5e32 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package at.gv.egiz.bku.online.webapp; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; + +import at.gv.egiz.bku.binding.BindingProcessorManager; + +public class ShutdownHandler implements ApplicationListener { + + private static Log log = LogFactory.getLog(ShutdownHandler.class); + + private BindingProcessorManager bindingProcessorManager; + + public void setBindingProcessorManager( + BindingProcessorManager bindingProcessorManager) { + this.bindingProcessorManager = bindingProcessorManager; + } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ContextClosedEvent) { + log.info("Shutting down BKU"); + bindingProcessorManager.shutdownNow(); + } + + } + +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java new file mode 100644 index 00000000..2c6f522e --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java @@ -0,0 +1,37 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.online.webapp; + +import javax.servlet.http.HttpServlet; + +import at.gv.egiz.bku.binding.BindingProcessorManager; +import at.gv.egiz.bku.conf.Configurator; + +public abstract class SpringBKUServlet extends HttpServlet { + + public final static String BEAN_NAME="bindingProcessorManager"; + + protected static Configurator configurator; + + protected BindingProcessorManager getBindingProcessorManager() { + return (BindingProcessorManager) getServletContext().getAttribute(BEAN_NAME); + } + + public static void setConfigurator(Configurator conf) { + configurator = conf; + } +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java new file mode 100644 index 00000000..305d8c1c --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java @@ -0,0 +1,45 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package at.gv.egiz.stal.service.impl; + +import java.util.Locale; + +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALFactory; + +/** + * + * @author clemens + */ +public class RequestBrokerSTALFactory implements STALFactory { + + private static long timeout = -1; + + @Override + public STAL createSTAL() { + return new STALRequestBrokerImpl(timeout); + } + + @Override + public void setLocale(Locale locale) { + } + + public static void setTimeout(long millisec) { + timeout = millisec; + } +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java new file mode 100644 index 00000000..b77f7660 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java @@ -0,0 +1,41 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package at.gv.egiz.stal.service.impl; + +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import java.util.List; +import javax.xml.bind.JAXBElement; + +/** + * + * @author clemens + */ +public interface STALRequestBroker extends STAL { + + public static final int ERR_4500 = 4500; + public static final long DEFAULT_TIMEOUT_MS = 1000*60*5; //5mn + + public List> connect(); + + public List> nextRequest(List> responses); + + public List getHashDataInput(); +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java new file mode 100644 index 00000000..a2447ab7 --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -0,0 +1,324 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package at.gv.egiz.stal.service.impl; + +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.service.translator.STALTranslator; +import at.gv.egiz.stal.service.translator.TranslationException; +import at.gv.egiz.stal.service.types.ObjectFactory; +import at.gv.egiz.stal.service.types.QuitRequestType; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import at.gv.egiz.stalx.service.translator.STALXTranslationHandler; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.xml.bind.JAXBElement; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * An instance of STALRequestBroker is shared between a producer thread (SLCommand) + * and multiple consumer threads (STALService). + * This implementation assures that handleRequest is executed only once the previous invocation returned. + * The BindingProcessor assures that a new SLCommand calls handleRequest() only once + * the bindingProcessor called handleRequest(QUIT) after the previous SLCommand's handleRequest() returned. + * + * Multiple STALService threads might call nextRequest()/getSignedReferences() in any order. + * + * @author clemens + */ +public class STALRequestBrokerImpl implements STALRequestBroker { + + private static final Log log = LogFactory.getLog(STALRequestBrokerImpl.class); + + private ObjectFactory of = new ObjectFactory(); + private STALTranslator translator = new STALTranslator(); + + private boolean interrupted = false; + + protected final ArrayList> requests; + protected final ArrayList> responses; + + protected ArrayList hashDataInputs; + + private long timeout; + + public STALRequestBrokerImpl(long timeoutMillisec) { + if (timeoutMillisec <= 0) + timeoutMillisec = DEFAULT_TIMEOUT_MS; + timeout = timeoutMillisec; + requests = new ArrayList>(); + responses = new ArrayList>(); + hashDataInputs = new ArrayList(); + + // register handler for STAL-X + translator.registerTranslationHandler(new STALXTranslationHandler()); + } + + /** + * Produce requests (and HashDataInputCallback) and wait for responses. + * This method is not thread safe, since every bindingprocessor thread possesses it's own instance. + * It however assures cooperation with STAL webservice threads consuming the requests and producing responses. + * + * @param requests + * @return + * + * @pre requests: either single SignRequest, QuitRequest or multiple ReadInfoboxRequests + */ + @Override + public List handleRequest(List stalRequests) { + if (interrupted) { + return null; + } + try { + synchronized (requests) { + log.trace("produce request"); + + requests.clear(); + hashDataInputs.clear(); + + for (STALRequest stalRequest : stalRequests) { + try { + JAXBElement request = translator.translate(stalRequest); + requests.add(request); + if (stalRequest instanceof SignRequest) { + //TODO refactor SignRequestType to keep HDI + // and getHashDataInput() accesses request obj + // (requests are cleared only when we receive the response) + // DataObjectHashDataInput with reference caching enabled DataObject + hashDataInputs.addAll(((SignRequest) stalRequest).getHashDataInput()); + } else if (stalRequest instanceof QuitRequest) { + log.trace("Received QuitRequest, do not wait for responses."); + log.trace("notifying request consumers"); + requests.notify(); + return new ArrayList(); + } + } catch (TranslationException ex) { + log.error(ex.getMessage() + ", send QUIT"); + requests.clear(); + QuitRequestType reqT = of.createQuitRequestType(); + JAXBElement req = of.createGetNextRequestResponseTypeQuitRequest(reqT); + requests.add(req); + log.trace("notifying request consumers"); + requests.notify(); + return new ArrayList(); + } + } + + +// if (stalRequest instanceof SignRequest) { +// log.trace("Received SignRequest, keep HashDataInput."); +// SignRequestType reqT = of.createSignRequestType(); +// reqT.setKeyIdentifier(((SignRequest) stalRequest).getKeyIdentifier()); +// reqT.setSignedInfo(((SignRequest) stalRequest).getSignedInfo()); +// JAXBElement req = of.createGetNextRequestResponseTypeSignRequest(reqT); +// requests.add(req); +// //DataObjectHashDataInput with reference caching enabled DataObject +// hashDataInputs.addAll(((SignRequest) stalRequest).getHashDataInput()); +// break; +// } else if (stalRequest instanceof InfoboxReadRequest) { +// log.trace("Received InfoboxReadRequest"); +// InfoboxReadRequestType reqT = new InfoboxReadRequestType(); +// reqT.setInfoboxIdentifier(((InfoboxReadRequest) stalRequest).getInfoboxIdentifier()); +// reqT.setDomainIdentifier(((InfoboxReadRequest) stalRequest).getDomainIdentifier()); +// JAXBElement req = of.createGetNextRequestResponseTypeInfoboxReadRequest(reqT); +// requests.add(req); +// } else if (stalRequest instanceof QuitRequest) { +// log.trace("Received QuitRequest, do not wait for responses."); +// QuitRequestType reqT = of.createQuitRequestType(); +// JAXBElement req = of.createGetNextRequestResponseTypeQuitRequest(reqT); +// requests.add(req); +// log.trace("notifying request consumers"); +// requests.notify(); +// return new ArrayList(); +// } else { +// log.error("Received unsupported STAL request: " + stalRequest.getClass().getName() + ", send QUIT"); +// requests.clear(); +// QuitRequestType reqT = of.createQuitRequestType(); +// JAXBElement req = of.createGetNextRequestResponseTypeQuitRequest(reqT); +// requests.add(req); +// log.trace("notifying request consumers"); +// requests.notify(); +// return new ArrayList(); +// } +// } + log.trace("notifying request consumers"); + requests.notify(); + } + + synchronized (responses) { + long beforeWait = System.currentTimeMillis(); + while (responses.isEmpty()) { + log.trace("waiting to consume response"); + responses.wait(timeout); + if (System.currentTimeMillis() - beforeWait >= timeout) { + log.warn("timeout while waiting to consume response, cleanup requests"); + requests.clear(); + hashDataInputs.clear(); + return Collections.singletonList((STALResponse) new ErrorResponse(ERR_4500)); + } + } + log.trace("consuming responses"); + List stalResponses = new ArrayList(); + try { + for (JAXBElement resp : responses) { + STALResponse stalResp = translator.translate(resp); + stalResponses.add(stalResp); + } + } catch (TranslationException ex) { + log.error(ex.getMessage() + ", return ErrorResponse (4000)"); + ErrorResponse stalResp = new ErrorResponse(4000); + stalResp.setErrorMessage(ex.getMessage()); + stalResponses = Collections.singletonList((STALResponse) stalResp); + } + + responses.clear(); + log.trace("notifying response producers"); + responses.notify(); + + return stalResponses; + } + } catch (InterruptedException ex) { + log.warn("interrupt in handleRequest(): " + ex.getMessage()); + interrupted = true; + return null; + } + } + + @Override + public List> connect() { + if (interrupted) { + return null; + } + try { + synchronized (requests) { + long beforeWait = System.currentTimeMillis(); + while (requests.isEmpty()) { + log.trace("waiting to consume request"); + requests.wait(timeout); + if (System.currentTimeMillis() - beforeWait >= timeout) { + log.warn("timeout while waiting to consume request"); + return createSingleQuitRequest(); + } + } + log.trace("don't consume request now, leave for further connect calls"); + return requests; + } + } catch (InterruptedException ex) { + log.warn("interrupt in nextRequest(): " + ex.getMessage()); + interrupted = true; + return null; + } + } + + /** + * This method is thread-safe, except for + * an 'initial' call to nextRequest(null) followed by a + * 'zombie' call to nextRequest(notNull). + * This case (per design) leads to a timeout of the original call. + * (synchronizing the entire method does not + * hinder the zombie to interrupt two consecutive nextRequest() calls.) + * + * @param responses + * @return QUIT if expected responses are not provided + */ + @Override + public List> nextRequest(List> resps) { + if (interrupted) { + return null; + } + try { + synchronized (requests) { + log.trace("received responses, now consume request"); + if (requests.size() != 0) { + requests.clear(); + } else { + log.warn("requests queue is empty, response might have already been produced previously "); + // return QUIT? + } + } + + synchronized (responses) { + if (resps != null && resps.size() > 0) { + long beforeWait = System.currentTimeMillis(); + while (!responses.isEmpty()) { + log.trace("waiting to produce response"); + responses.wait(timeout); + if (System.currentTimeMillis() - beforeWait >= timeout) { + log.warn("timeout while waiting to produce response"); + return createSingleQuitRequest(); + } + } + log.trace("produce response"); + responses.addAll(resps); + //reset HashDataInputCallback iff SignResponse + if (log.isTraceEnabled()) { + for (JAXBElement response : resps) { + log.trace("Received STAL response: " + response.getValue().getClass().getName()); + } + } + log.trace("notifying response consumers"); + responses.notify(); + } else { + log.error("Received NextRequest without responses, return QUIT"); + return createSingleQuitRequest(); + } + } + + synchronized (requests) { + long beforeWait = System.currentTimeMillis(); + while (requests.isEmpty()) { + log.trace("waiting to consume request"); + requests.wait(timeout); + if (System.currentTimeMillis() - beforeWait >= timeout) { + log.warn("timeout while waiting to consume request"); + return createSingleQuitRequest(); + } + } + log.trace("don't consume request now, but on next response delivery"); + return requests; + } + } catch (InterruptedException ex) { + log.warn("interrupt in nextRequest(): " + ex.getMessage()); + interrupted = true; + return null; + } + } + + @Override + public List getHashDataInput() { + synchronized (requests) { + log.trace("return " + hashDataInputs.size() + " current HashDataInput(s) "); + return hashDataInputs; + } + } + + private List> createSingleQuitRequest() { + QuitRequestType quitT = of.createQuitRequestType(); + JAXBElement quit = of.createGetNextRequestResponseTypeQuitRequest(quitT); + ArrayList> l = new ArrayList>(); + l.add(quit); + return l; + } +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java new file mode 100644 index 00000000..c8ab280f --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java @@ -0,0 +1,386 @@ + /* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.stal.service.impl; + +import at.buergerkarte.namespaces.cardchannel.service.CommandAPDUType; +import at.buergerkarte.namespaces.cardchannel.service.ScriptType; +import at.gv.egiz.bku.binding.BindingProcessor; +import at.gv.egiz.bku.binding.BindingProcessorManager; +import at.gv.egiz.bku.binding.Id; +import at.gv.egiz.bku.binding.IdFactory; + +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.service.GetHashDataInputFault; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.types.ErrorResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputFaultType; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.service.types.GetNextRequestResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestType; +import at.gv.egiz.stal.service.types.InfoboxReadRequestType; +import at.gv.egiz.stal.service.types.QuitRequestType; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import at.gv.egiz.stal.service.types.SignRequestType; +import at.gv.egiz.stal.service.types.GetHashDataInputType.Reference; +//import at.gv.egiz.stal.service.types.GetHashDataInputResponseType.Reference; + +import com.sun.xml.ws.developer.UsesJAXBContext; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.annotation.Resource; +import javax.jws.WebService; +import javax.servlet.ServletContext; +import javax.xml.bind.JAXBElement; +import javax.xml.ws.WebServiceContext; +import javax.xml.ws.handler.MessageContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author clemens + */ +@WebService(endpointInterface = "at.gv.egiz.stal.service.STALPortType", portName="STALPort", serviceName="STALService", targetNamespace="http://www.egiz.gv.at/wsdl/stal", wsdlLocation="WEB-INF/wsdl/stal.wsdl") +@UsesJAXBContext(STALXJAXBContextFactory.class) +public class STALServiceImpl implements STALPortType { + + public static final String BINDING_PROCESSOR_MANAGER = "bindingProcessorManager"; + public static final Id TEST_SESSION_ID = IdFactory.getInstance().createId("TestSession"); + protected static final Log log = LogFactory.getLog(STALServiceImpl.class); + + + static { + if (log.isTraceEnabled()) { + log.trace("enabling webservice communication dump"); + System.setProperty("com.sun.xml.ws.transport.http.HttpAdapter.dump", "true"); + } else { + System.setProperty("com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace", "false"); + } + } + @Resource + protected WebServiceContext wsContext; + protected IdFactory idF = IdFactory.getInstance(); + /** JAXB ObjectFactories */ + private at.gv.egiz.stal.service.types.ObjectFactory stalObjFactory = new at.gv.egiz.stal.service.types.ObjectFactory(); + /** don't confuse with at.buergerkarte.namespaces.cardchannel */ + private at.buergerkarte.namespaces.cardchannel.service.ObjectFactory ccObjFactory = new at.buergerkarte.namespaces.cardchannel.service.ObjectFactory(); + + @Override + public GetNextRequestResponseType connect(String sessId) { + + if (sessId == null) { + throw new NullPointerException("No session id provided"); + } + + Id sessionId = idF.createId(sessId); + + if (log.isDebugEnabled()) { + log.debug("Received Connect [" + sessionId + "]"); + } + + if (TEST_SESSION_ID.equals(sessionId)) { + return getTestSessionNextRequestResponse(null); + } + + GetNextRequestResponseType response = new GetNextRequestResponseType(); + response.setSessionId(sessionId.toString()); + + STALRequestBroker stal = getStal(sessionId); + + if (stal != null) { + + List> requestsOut = ((STALRequestBroker) stal).connect(); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().addAll(requestsOut); + + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Returning initial GetNextRequestResponse ["); + sb.append(sessionId.toString()); + sb.append("] containing "); + sb.append(requestsOut.size()); + sb.append(" requests: "); + for (JAXBElement reqOut : requestsOut) { + sb.append(reqOut.getValue().getClass()); + sb.append(' '); + } + log.debug(sb.toString()); + } + } else { + log.error("Failed to get STAL for session " + sessionId + ", returning QuitRequest"); + QuitRequestType quitT = stalObjFactory.createQuitRequestType(); + JAXBElement quit = stalObjFactory.createGetNextRequestResponseTypeQuitRequest(quitT); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(quit); + } + return response; + } + + @Override + public GetNextRequestResponseType getNextRequest(GetNextRequestType request) { + + if (request.getSessionId() == null) { + throw new NullPointerException("No session id provided"); + } + + Id sessionId = idF.createId(request.getSessionId()); + + List> responsesIn = request.getInfoboxReadResponseOrSignResponseOrErrorResponse(); +// List responsesIn = request.getInfoboxReadResponseOrSignResponseOrErrorResponse();//getResponse(); + + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Received GetNextRequest ["); + sb.append(sessionId.toString()); + sb.append("] containing "); + sb.append(responsesIn.size()); + sb.append(" responses: "); + for (JAXBElement respIn : responsesIn) { + sb.append(respIn.getValue().getClass()); + sb.append(' '); + } + log.debug(sb.toString()); + } + + if (TEST_SESSION_ID.equals(sessionId)) { + return getTestSessionNextRequestResponse(responsesIn); + } + + GetNextRequestResponseType response = new GetNextRequestResponseType(); + response.setSessionId(sessionId.toString()); + + STALRequestBroker stal = getStal(sessionId); + + if (stal != null) { + + List> requestsOut = ((STALRequestBroker) stal).nextRequest(responsesIn); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().addAll(requestsOut); + + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Returning GetNextRequestResponse ["); + sb.append(sessionId.toString()); + sb.append("] containing "); + sb.append(requestsOut.size()); + sb.append(" requests: "); + for (JAXBElement reqOut : requestsOut) { + sb.append(reqOut.getValue().getClass()); + sb.append(' '); + } + log.debug(sb.toString()); + } + } else { + log.error("Failed to get STAL for session " + sessionId + ", returning QuitRequest"); + QuitRequestType quitT = stalObjFactory.createQuitRequestType(); + JAXBElement quit = stalObjFactory.createGetNextRequestResponseTypeQuitRequest(quitT); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(quit); + } + return response; + } + + @Override + public GetHashDataInputResponseType getHashDataInput(GetHashDataInputType request) throws GetHashDataInputFault { + + if (request.getSessionId() == null) { + throw new NullPointerException("No session id provided"); + } + + Id sessionId = idF.createId(request.getSessionId()); + + if (log.isDebugEnabled()) { + log.debug("Received GetHashDataInputRequest for session " + sessionId + " containing " + request.getReference().size() + " reference(s)"); + } + + if (TEST_SESSION_ID.equals(sessionId)) { + return getTestSessionHashDataInputResponse(request.getReference()); + } + + GetHashDataInputResponseType response = new GetHashDataInputResponseType(); + response.setSessionId(sessionId.toString()); + + STALRequestBroker stal = getStal(sessionId); + + if (stal != null) { + List hashDataInputs = stal.getHashDataInput(); + + if (hashDataInputs != null) { + + Map hashDataIdMap = new HashMap(); + for (HashDataInput hdi : hashDataInputs) { + if (log.isTraceEnabled()) { + log.trace("Provided HashDataInput for reference " + hdi.getReferenceId()); + } + hashDataIdMap.put(hdi.getReferenceId(), hdi); + } + + List reqRefs = request.getReference(); + for (GetHashDataInputType.Reference reqRef : reqRefs) { + String reqRefId = reqRef.getID(); + HashDataInput reqHdi = hashDataIdMap.get(reqRefId); + if (reqHdi == null) { + String msg = "Failed to resolve HashDataInput for reference " + reqRefId; + log.error(msg); + GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); + faultInfo.setErrorCode(1); + faultInfo.setErrorMessage(msg); + throw new GetHashDataInputFault(msg, faultInfo); + } + + InputStream hashDataIS = reqHdi.getHashDataInput(); + if (hashDataIS == null) { + //HashDataInput not cached? + String msg = "Failed to obtain HashDataInput for reference " + reqRefId + ", reference not cached"; + log.error(msg); + GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); + faultInfo.setErrorCode(1); + faultInfo.setErrorMessage(msg); + throw new GetHashDataInputFault(msg, faultInfo); + } + ByteArrayOutputStream baos = null; + try { + if (log.isDebugEnabled()) { + log.debug("Resolved HashDataInput " + reqRefId + " (" + reqHdi.getMimeType() + ";charset=" + reqHdi.getEncoding() + ")"); + } + baos = new ByteArrayOutputStream(hashDataIS.available()); + int c; + while ((c = hashDataIS.read()) != -1) { + baos.write(c); + } + GetHashDataInputResponseType.Reference ref = new GetHashDataInputResponseType.Reference(); + ref.setID(reqRefId); + ref.setMimeType(reqHdi.getMimeType()); + ref.setEncoding(reqHdi.getEncoding()); + ref.setFilename(reqHdi.getFilename()); + ref.setValue(baos.toByteArray()); + response.getReference().add(ref); + } catch (IOException ex) { + String msg = "Failed to get HashDataInput for reference " + reqRefId; + log.error(msg, ex); + GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); + faultInfo.setErrorCode(1); + faultInfo.setErrorMessage(msg); + throw new GetHashDataInputFault(msg, faultInfo, ex); + } finally { + try { + baos.close(); + } catch (IOException ex) { + } + } + } + return response; + } else { + String msg = "Failed to resolve any HashDataInputs for session " + sessionId; + log.error(msg); + GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); + faultInfo.setErrorCode(1); + faultInfo.setErrorMessage(msg); + throw new GetHashDataInputFault(msg, faultInfo); + } + } else { + String msg = "Session timeout"; //Failed to get STAL for session " + sessionId; + log.error(msg + " " + sessionId); + GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); + faultInfo.setErrorCode(1); + faultInfo.setErrorMessage(msg); + throw new GetHashDataInputFault(msg, faultInfo); + } + } + + private STALRequestBroker getStal(Id sessionId) { + if (log.isTraceEnabled()) { + log.trace("resolve STAL for session " + sessionId); + } + MessageContext mCtx = wsContext.getMessageContext(); + ServletContext sCtx = (ServletContext) mCtx.get(MessageContext.SERVLET_CONTEXT); + BindingProcessorManager bpMgr = (BindingProcessorManager) sCtx.getAttribute(BINDING_PROCESSOR_MANAGER); + BindingProcessor bp = bpMgr.getBindingProcessor(sessionId); + return (bp == null) ? null : (bp.isFinished() ? null : (STALRequestBroker) bp.getSTAL()); + } + + private GetNextRequestResponseType getTestSessionNextRequestResponse(List> responsesIn) { + GetNextRequestResponseType response = new GetNextRequestResponseType(); + response.setSessionId(TEST_SESSION_ID.toString()); + + List> reqs = response.getInfoboxReadRequestOrSignRequestOrQuitRequest(); + + if (responsesIn == null) { + log.info("[TestSession] CONNECT"); +// addTestCardChannelRequest(reqs); +// addTestInfoboxReadRequest("IdentityLink", reqs); +// addTestInfoboxReadRequest("SecureSignatureKeypair", reqs); +// addTestInfoboxReadRequest("CertifiedKeypair", reqs); + addTestSignatureRequests("SecureSignatureKeypair", reqs); + } else if (responsesIn != null && responsesIn.size() > 0 && responsesIn.get(0).getValue() instanceof ErrorResponseType) { + log.info("[TestSession] received ErrorResponse, return QUIT request"); + QuitRequestType quitT = stalObjFactory.createQuitRequestType(); + reqs.add(stalObjFactory.createGetNextRequestResponseTypeQuitRequest(quitT)); + } else { + log.info("[TestSession] received " + responsesIn.size() + " response(s), return QUIT" ); + QuitRequestType quitT = stalObjFactory.createQuitRequestType(); + reqs.add(stalObjFactory.createGetNextRequestResponseTypeQuitRequest(quitT)); + } + return response; + } + + + private GetHashDataInputResponseType getTestSessionHashDataInputResponse(List references) { + log.debug("[TestSession] received GET_HASHDATAINPUT"); + + GetHashDataInputResponseType response = new GetHashDataInputResponseType(); + response.setSessionId(TEST_SESSION_ID.toString()); + + for (Reference reference : references) { + String refId = reference.getID(); + log.debug("[TestSession] adding hashdata input for " + refId); + GetHashDataInputResponseType.Reference ref = new GetHashDataInputResponseType.Reference(); + ref.setID(refId); + ref.setMimeType(TestSignatureData.HASHDATA_MIMETYPES.get(refId)); //todo resolve from TestSignatureData + ref.setValue(TestSignatureData.HASHDATA_INPUT.get(refId)); + ref.setEncoding(TestSignatureData.ENCODING); + response.getReference().add(ref); + } + return response; + } + + private void addTestCardChannelRequest(List> requestList) { + log.info("[TestSession] add CARDCHANNEL request"); + ScriptType scriptT = ccObjFactory.createScriptType(); + CommandAPDUType cmd = ccObjFactory.createCommandAPDUType(); + cmd.setValue("TestSession CardChannelCMD 1234".getBytes()); + scriptT.getResetOrCommandAPDUOrVerifyAPDU().add(cmd); + requestList.add(ccObjFactory.createScript(scriptT)); + } + + private void addTestInfoboxReadRequest(String infoboxIdentifier, List> requestList) { + log.info("[TestSession] add READ "+ infoboxIdentifier + " request"); + InfoboxReadRequestType ibrT = stalObjFactory.createInfoboxReadRequestType(); + ibrT.setInfoboxIdentifier(infoboxIdentifier); + requestList.add(stalObjFactory.createGetNextRequestResponseTypeInfoboxReadRequest(ibrT)); + } + + private void addTestSignatureRequests(String keyIdentifier, List> reqs) { + log.info("[TestSession] add SIGN " + keyIdentifier + " request"); + SignRequestType sigT = stalObjFactory.createSignRequestType(); + sigT.setKeyIdentifier(keyIdentifier); + sigT.setSignedInfo(TestSignatureData.SIGNED_INFO.get(1)); //select! + reqs.add(stalObjFactory.createGetNextRequestResponseTypeSignRequest(sigT)); + } + +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java new file mode 100644 index 00000000..9caf950f --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java @@ -0,0 +1,61 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.stal.service.impl; + +import com.sun.xml.bind.api.JAXBRIContext; +import com.sun.xml.bind.api.TypeReference; +import com.sun.xml.ws.api.model.SEIModel; +import com.sun.xml.ws.developer.JAXBContextFactory; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class STALXJAXBContextFactory implements JAXBContextFactory { + + private static final Log log = LogFactory.getLog(STALXJAXBContextFactory.class); + + @Override + public JAXBRIContext createJAXBContext(SEIModel sei, List classesToBind, List typeReferences) throws JAXBException { + if (log.isTraceEnabled()) { + log.trace("JAXBContext seed for SEI " + sei.getTargetNamespace() + ":"); + for (Class class1 : classesToBind) { + log.trace(" " + class1); + } + for (TypeReference typeReference : typeReferences) { + log.trace(" typeRef " + typeReference.tagName + " -> " + typeReference.type); + } + } + List classes = new ArrayList(); + classes.addAll(classesToBind); + Class ccOF = at.buergerkarte.namespaces.cardchannel.service.ObjectFactory.class; + if (!classes.contains(ccOF)) { + log.debug("adding " + ccOF + " to JAXBContext seed"); + classes.add(ccOF); + } + + //TODO add typeReference? + + return JAXBRIContext.newInstance(classes.toArray(new Class[classes.size()]), + typeReferences, null, sei.getTargetNamespace(), false, null); + } +} diff --git a/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java new file mode 100644 index 00000000..2f58bb3d --- /dev/null +++ b/mocca-1.2.11/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java @@ -0,0 +1,47 @@ +package at.gv.egiz.stal.service.impl; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public final class TestSignatureData { + + protected final static Log log = LogFactory.getLog(TestSignatureData.class); + + public static final String[] ID = new String[] {"signed-data-reference-0-1214921968-27971781-24309", "signed-data-reference-1"}; + public static final String ENCODING = "UTF-8"; + + public static final Map HASHDATA_INPUT = new HashMap(); + static { + try { + HASHDATA_INPUT.put(ID[0], "Ich bin ein einfacher Text. lläöü߀".getBytes(ENCODING)); + HASHDATA_INPUT.put(ID[1], "2te referenz".getBytes(ENCODING)); + } catch (UnsupportedEncodingException ex) { + log.error("failed to init signature test data", ex); + } + } + public static final Map HASHDATA_MIMETYPES = new HashMap(); + static { + HASHDATA_MIMETYPES.put(ID[0], "text/plain"); + HASHDATA_MIMETYPES.put(ID[1], "any/mime-type"); + } + +// private static final byte[] signedInfo = " id('signed-data-object-0-1214921968-27971781-13578')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM=yV6Q+I60buqR4mMaxA7fi+CV35A=".getBytes(); +// private static final byte[] signedInfo2Ref = " id('signed-data-object-0-1214921968-27971781-13578')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM= id('signed-data-object-1')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM=yV6Q+I60buqR4mMaxA7fi+CV35A=".getBytes(); +// private static final String signedInfo2Ref = " id('signed-data-object-1')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM="; + /** + * SIGNED_INFO[0] contains reference ID[0] + * SIGNED_INFO[1] contains reference ID[0] and ID[1] + */ + public static final List SIGNED_INFO = new ArrayList(); + static { + SIGNED_INFO.add(" id('signed-data-object-0-1214921968-27971781-13578')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM=yV6Q+I60buqR4mMaxA7fi+CV35A=".getBytes()); + SIGNED_INFO.add(" id('signed-data-object-0-1214921968-27971781-13578')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM= id('signed-data-object-1')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM=yV6Q+I60buqR4mMaxA7fi+CV35A=".getBytes()); + } + +} -- cgit v1.2.3