summaryrefslogtreecommitdiff
path: root/BKUOnline/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'BKUOnline/src/main/java')
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java63
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java127
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java113
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java317
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java154
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java49
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java48
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java37
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java45
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java41
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java324
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java386
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java61
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java47
14 files changed, 1812 insertions, 0 deletions
diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/accesscontroller/SpringSecurityManager.java
new file mode 100644
index 00000000..5795478b
--- /dev/null
+++ b/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/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java
new file mode 100644
index 00000000..6030c1c0
--- /dev/null
+++ b/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/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/AppletDispatcher.java
new file mode 100644
index 00000000..24938cd5
--- /dev/null
+++ b/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 <clemens.orthacker@iaik.tugraz.at>
+ */
+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 <code>GET</code> and <code>POST</code> 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);
+ }
+
+ // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
+ /**
+ * Handles the HTTP <code>GET</code> 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 <code>POST</code> 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";
+ }// </editor-fold>
+
+}
diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java
new file mode 100644
index 00000000..7dfec211
--- /dev/null
+++ b/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<String, String> headerMap = new HashMap<String, String>();
+ for (Enumeration<String> 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/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java
new file mode 100644
index 00000000..5ffe2399
--- /dev/null
+++ b/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<String> 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/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SessionTimeout.java
new file mode 100644
index 00000000..2b56166c
--- /dev/null
+++ b/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/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ShutdownHandler.java
new file mode 100644
index 00000000..741b5e32
--- /dev/null
+++ b/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/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java
new file mode 100644
index 00000000..2c6f522e
--- /dev/null
+++ b/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/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java
new file mode 100644
index 00000000..305d8c1c
--- /dev/null
+++ b/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/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java
new file mode 100644
index 00000000..b77f7660
--- /dev/null
+++ b/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<JAXBElement<? extends RequestType>> connect();
+
+ public List<JAXBElement<? extends RequestType>> nextRequest(List<JAXBElement<? extends ResponseType>> responses);
+
+ public List<HashDataInput> getHashDataInput();
+}
diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java
new file mode 100644
index 00000000..a2447ab7
--- /dev/null
+++ b/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<JAXBElement<? extends RequestType>> requests;
+ protected final ArrayList<JAXBElement<? extends ResponseType>> responses;
+
+ protected ArrayList<HashDataInput> hashDataInputs;
+
+ private long timeout;
+
+ public STALRequestBrokerImpl(long timeoutMillisec) {
+ if (timeoutMillisec <= 0)
+ timeoutMillisec = DEFAULT_TIMEOUT_MS;
+ timeout = timeoutMillisec;
+ requests = new ArrayList<JAXBElement<? extends RequestType>>();
+ responses = new ArrayList<JAXBElement<? extends ResponseType>>();
+ hashDataInputs = new ArrayList<HashDataInput>();
+
+ // 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<STALResponse> handleRequest(List<? extends STALRequest> stalRequests) {
+ if (interrupted) {
+ return null;
+ }
+ try {
+ synchronized (requests) {
+ log.trace("produce request");
+
+ requests.clear();
+ hashDataInputs.clear();
+
+ for (STALRequest stalRequest : stalRequests) {
+ try {
+ JAXBElement<? extends RequestType> 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<STALResponse>();
+ }
+ } catch (TranslationException ex) {
+ log.error(ex.getMessage() + ", send QUIT");
+ requests.clear();
+ QuitRequestType reqT = of.createQuitRequestType();
+ JAXBElement<QuitRequestType> req = of.createGetNextRequestResponseTypeQuitRequest(reqT);
+ requests.add(req);
+ log.trace("notifying request consumers");
+ requests.notify();
+ return new ArrayList<STALResponse>();
+ }
+ }
+
+
+// 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<SignRequestType> 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<InfoboxReadRequestType> 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<QuitRequestType> req = of.createGetNextRequestResponseTypeQuitRequest(reqT);
+// requests.add(req);
+// log.trace("notifying request consumers");
+// requests.notify();
+// return new ArrayList<STALResponse>();
+// } else {
+// log.error("Received unsupported STAL request: " + stalRequest.getClass().getName() + ", send QUIT");
+// requests.clear();
+// QuitRequestType reqT = of.createQuitRequestType();
+// JAXBElement<QuitRequestType> req = of.createGetNextRequestResponseTypeQuitRequest(reqT);
+// requests.add(req);
+// log.trace("notifying request consumers");
+// requests.notify();
+// return new ArrayList<STALResponse>();
+// }
+// }
+ 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<STALResponse> stalResponses = new ArrayList<STALResponse>();
+ try {
+ for (JAXBElement<? extends ResponseType> 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<JAXBElement<? extends RequestType>> 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<JAXBElement<? extends RequestType>> nextRequest(List<JAXBElement<? extends ResponseType>> 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<? extends ResponseType> 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<HashDataInput> getHashDataInput() {
+ synchronized (requests) {
+ log.trace("return " + hashDataInputs.size() + " current HashDataInput(s) ");
+ return hashDataInputs;
+ }
+ }
+
+ private List<JAXBElement<? extends RequestType>> createSingleQuitRequest() {
+ QuitRequestType quitT = of.createQuitRequestType();
+ JAXBElement<QuitRequestType> quit = of.createGetNextRequestResponseTypeQuitRequest(quitT);
+ ArrayList<JAXBElement<? extends RequestType>> l = new ArrayList<JAXBElement<? extends RequestType>>();
+ l.add(quit);
+ return l;
+ }
+}
diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java
new file mode 100644
index 00000000..c8ab280f
--- /dev/null
+++ b/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<JAXBElement<? extends RequestType>> 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<? extends RequestType> 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<QuitRequestType> 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<JAXBElement<? extends ResponseType>> responsesIn = request.getInfoboxReadResponseOrSignResponseOrErrorResponse();
+// List<ResponseType> 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<? extends ResponseType> 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<JAXBElement<? extends RequestType>> 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<? extends RequestType> 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<QuitRequestType> 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<HashDataInput> hashDataInputs = stal.getHashDataInput();
+
+ if (hashDataInputs != null) {
+
+ Map<String, HashDataInput> hashDataIdMap = new HashMap<String, HashDataInput>();
+ for (HashDataInput hdi : hashDataInputs) {
+ if (log.isTraceEnabled()) {
+ log.trace("Provided HashDataInput for reference " + hdi.getReferenceId());
+ }
+ hashDataIdMap.put(hdi.getReferenceId(), hdi);
+ }
+
+ List<GetHashDataInputType.Reference> 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<JAXBElement<? extends ResponseType>> responsesIn) {
+ GetNextRequestResponseType response = new GetNextRequestResponseType();
+ response.setSessionId(TEST_SESSION_ID.toString());
+
+ List<JAXBElement<? extends RequestType>> 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<Reference> 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<JAXBElement<? extends RequestType>> 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<JAXBElement<? extends RequestType>> 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<JAXBElement<? extends RequestType>> 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/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java
new file mode 100644
index 00000000..9caf950f
--- /dev/null
+++ b/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 <clemens.orthacker@iaik.tugraz.at>
+ */
+public class STALXJAXBContextFactory implements JAXBContextFactory {
+
+ private static final Log log = LogFactory.getLog(STALXJAXBContextFactory.class);
+
+ @Override
+ public JAXBRIContext createJAXBContext(SEIModel sei, List<Class> classesToBind, List<TypeReference> 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<Class> classes = new ArrayList<Class>();
+ 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/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/TestSignatureData.java
new file mode 100644
index 00000000..2f58bb3d
--- /dev/null
+++ b/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<String, byte[]> HASHDATA_INPUT = new HashMap<String, byte[]>();
+ 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<String, String> HASHDATA_MIMETYPES = new HashMap<String, String>();
+ static {
+ HASHDATA_MIMETYPES.put(ID[0], "text/plain");
+ HASHDATA_MIMETYPES.put(ID[1], "any/mime-type");
+ }
+
+// private static final byte[] signedInfo = "<dsig:SignedInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\"><dsig:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" /> <dsig:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1\" /> <dsig:Reference Id=\"signed-data-reference-0-1214921968-27971781-24309\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-0-1214921968-27971781-13578')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference><dsig:Reference Id=\"etsi-data-reference-0-1214921968-27971781-25439\" Type=\"http://uri.etsi.org/01903/v1.1.1#SignedProperties\" URI=\"#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1214921968-27971781-3095')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)\"><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><dsig:DigestValue>yV6Q+I60buqR4mMaxA7fi+CV35A=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>".getBytes();
+// private static final byte[] signedInfo2Ref = "<dsig:SignedInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\"><dsig:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" /> <dsig:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1\" /> <dsig:Reference Id=\"signed-data-reference-0-1214921968-27971781-24309\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-0-1214921968-27971781-13578')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference><dsig:Reference Id=\"signed-data-reference-1\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-1')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference><dsig:Reference Id=\"etsi-data-reference-0-1214921968-27971781-25439\" Type=\"http://uri.etsi.org/01903/v1.1.1#SignedProperties\" URI=\"#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1214921968-27971781-3095')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)\"><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><dsig:DigestValue>yV6Q+I60buqR4mMaxA7fi+CV35A=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>".getBytes();
+// private static final String signedInfo2Ref = "<dsig:Reference Id=\"signed-data-reference-1\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-1')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference>";
+ /**
+ * SIGNED_INFO[0] contains reference ID[0]
+ * SIGNED_INFO[1] contains reference ID[0] and ID[1]
+ */
+ public static final List<byte[]> SIGNED_INFO = new ArrayList<byte[]>();
+ static {
+ SIGNED_INFO.add("<dsig:SignedInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\"><dsig:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" /> <dsig:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1\" /> <dsig:Reference Id=\"signed-data-reference-0-1214921968-27971781-24309\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-0-1214921968-27971781-13578')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference><dsig:Reference Id=\"etsi-data-reference-0-1214921968-27971781-25439\" Type=\"http://uri.etsi.org/01903/v1.1.1#SignedProperties\" URI=\"#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1214921968-27971781-3095')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)\"><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><dsig:DigestValue>yV6Q+I60buqR4mMaxA7fi+CV35A=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>".getBytes());
+ SIGNED_INFO.add("<dsig:SignedInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\"><dsig:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" /> <dsig:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1\" /> <dsig:Reference Id=\"signed-data-reference-0-1214921968-27971781-24309\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-0-1214921968-27971781-13578')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference><dsig:Reference Id=\"signed-data-reference-1\" URI=\"#signed-data-object-0-1214921968-27971781-13578\"><dsig:Transforms> <dsig:Transform Algorithm=\"http://www.w3.org/2002/06/xmldsig-filter2\"> <xpf:XPath xmlns:xpf=\"http://www.w3.org/2002/06/xmldsig-filter2\" Filter=\"intersect\">id('signed-data-object-1')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /> <dsig:DigestValue>H1IePEEfGQ2SG03H6LTzw1TpCuM=</dsig:DigestValue></dsig:Reference><dsig:Reference Id=\"etsi-data-reference-0-1214921968-27971781-25439\" Type=\"http://uri.etsi.org/01903/v1.1.1#SignedProperties\" URI=\"#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1214921968-27971781-3095')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)\"><dsig:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><dsig:DigestValue>yV6Q+I60buqR4mMaxA7fi+CV35A=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>".getBytes());
+ }
+
+}