summaryrefslogtreecommitdiff
path: root/utils/src/main/java/at/gv/egiz
diff options
context:
space:
mode:
Diffstat (limited to 'utils/src/main/java/at/gv/egiz')
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/local/ui/BKUControllerInterface.java23
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialog.java202
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialogInterface.java33
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/HexDump.java75
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/StreamUtil.java101
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/binding/Protocol.java41
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FormDataURLSupplier.java26
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/HTTPURLProtocolHandlerImpl.java76
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/SimpleFormDataContextImpl.java41
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/StreamData.java61
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URIResolverAdapter.java96
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencer.java90
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencerContext.java27
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLProtocolHandler.java32
-rw-r--r--utils/src/main/java/at/gv/egiz/dom/DOMUtils.java115
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java416
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/IdentityLinkTransformer.java285
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/ans1/CitizenPublicKey.java92
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/ans1/IdentityLink.java315
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/ans1/PersonData.java91
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/ans1/PhysicalPersonData.java143
-rw-r--r--utils/src/main/java/at/gv/egiz/org/apache/tomcat/util/http/AcceptLanguage.java151
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/NamespaceContextCallback.java41
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/RedirectCallback.java42
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java259
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/RedirectUnmarshallerListener.java68
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/impl/SignatureLocationType.java50
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java70
-rw-r--r--utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java60
-rw-r--r--utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesException.java40
-rw-r--r--utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java225
-rw-r--r--utils/src/main/java/at/gv/egiz/xmldsig/KeyTypeNotSupportedException.java65
-rw-r--r--utils/src/main/java/at/gv/egiz/xmldsig/KeyValueFactory.java279
33 files changed, 3731 insertions, 0 deletions
diff --git a/utils/src/main/java/at/gv/egiz/bku/local/ui/BKUControllerInterface.java b/utils/src/main/java/at/gv/egiz/bku/local/ui/BKUControllerInterface.java
new file mode 100644
index 00000000..5e191c79
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/local/ui/BKUControllerInterface.java
@@ -0,0 +1,23 @@
+/*
+* 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.local.ui;
+
+public interface BKUControllerInterface {
+
+ public void shutDown();
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialog.java b/utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialog.java
new file mode 100644
index 00000000..5aa74d99
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialog.java
@@ -0,0 +1,202 @@
+/*
+* 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.local.ui;
+
+import java.awt.AWTException;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ResourceBundle;
+
+import javax.imageio.ImageIO;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class TrayIconDialog implements TrayIconDialogInterface {
+
+ private static Log log = LogFactory.getLog(TrayIconDialog.class);
+ private static TrayIconDialogInterface instance;
+ private boolean isSupported;
+ private BKUControllerInterface shutDown;
+ private TrayIcon trayIcon = null;
+ private ResourceBundle resourceBundle = null;
+
+ private TrayIconDialog() {
+ }
+
+ private void displayTrayMsg(String captionID, String messageID,
+ TrayIcon.MessageType type) {
+ if ((isSupported) && (resourceBundle != null)) {
+ try {
+ trayIcon.displayMessage(resourceBundle.getString(captionID),
+ resourceBundle.getString(messageID), type);
+ } catch (Exception ex) {
+ log.error(ex);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egiz.bku.local.ui.TrayIconDialogInterface#displayInfo(java.lang.String
+ * , java.lang.String)
+ */
+ public void displayInfo(String captionID, String messageID) {
+ displayTrayMsg(captionID, messageID, TrayIcon.MessageType.INFO);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egiz.bku.local.ui.TrayIconDialogInterface#displayWarning(java.lang
+ * .String, java.lang.String)
+ */
+ public void displayWarning(String captionID, String messageID) {
+ displayTrayMsg(captionID, messageID, TrayIcon.MessageType.WARNING);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egiz.bku.local.ui.TrayIconDialogInterface#displayError(java.lang.
+ * String, java.lang.String)
+ */
+ public void displayError(String captionID, String messageID) {
+ displayTrayMsg(captionID, messageID, TrayIcon.MessageType.ERROR);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egiz.bku.local.ui.TrayIconDialogInterface#init(java.util.ResourceBundle
+ * )
+ */
+ public void init(ResourceBundle resourceBundel) {
+ this.resourceBundle = resourceBundel;
+ isSupported = SystemTray.isSupported();
+ log.info("Trayicon supported: " + isSupported);
+ try {
+ if (isSupported) {
+ SystemTray tray = SystemTray.getSystemTray();
+ Image image = ImageIO.read(getClass().getClassLoader()
+ .getResourceAsStream("at/gv/egiz/bku/local/ui/chipperling.png"));
+ PopupMenu popup = new PopupMenu();
+ MenuItem exitItem = new MenuItem(resourceBundel
+ .getString("TrayMenu.Shutdown"));
+ popup.add(exitItem);
+ exitItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ log.info("Calling Shutdown");
+ if (shutDown != null) {
+ shutDown.shutDown();
+ }
+ }
+ });
+
+ trayIcon = new TrayIcon(image, "BKULogo", popup);
+ trayIcon.setImageAutoSize(true);
+ trayIcon.setToolTip(resourceBundel.getString("TrayMenu.Tooltip"));
+ try {
+ tray.add(trayIcon);
+ } catch (AWTException e) {
+ log.error("TrayIcon could not be added.", e);
+ isSupported = false;
+ }
+ }
+ } catch (IOException e) {
+ log.error(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egiz.bku.local.ui.TrayIconDialogInterface#setShutdownHook(at.gv.egiz
+ * .bku.local.ui.BKUControllerInterface)
+ */
+ public void setShutdownHook(BKUControllerInterface shutDown) {
+ this.shutDown = shutDown;
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized static TrayIconDialogInterface getInstance() {
+ ClassLoader cl = TrayIconDialog.class.getClassLoader();
+ if (instance == null) {
+ if (cl.toString().startsWith("sun.")) {
+ instance = new TrayIconDialog();
+ return instance;
+ }
+ ClassLoader parent = cl;
+ while (!parent.toString().startsWith("sun.")) {
+ parent = parent.getParent();
+ }
+ try {
+ Class<TrayIconDialog> otherClassInstance = (Class<TrayIconDialog>) parent
+ .loadClass(TrayIconDialog.class.getName());
+ Method getInstanceMethod = otherClassInstance.getDeclaredMethod(
+ "getInstance", new Class[] {});
+ Object otherSingleton = getInstanceMethod.invoke(null, new Object[] {});
+ instance = (TrayIconDialogInterface) Proxy.newProxyInstance(cl,
+ new Class[] { TrayIconDialogInterface.class },
+ new PassThroughProxyHandler(otherSingleton));
+ } catch (ClassNotFoundException ce) {
+ instance = new TrayIconDialog();
+ } catch (Exception e) {
+ log.error(e);
+ instance = new TrayIconDialog();
+ }
+ return instance;
+ }
+ return instance;
+ }
+
+ /**
+ *
+ * Only works for public methods
+ *
+ */
+ static class PassThroughProxyHandler implements InvocationHandler {
+ private final Object delegate;
+
+ public PassThroughProxyHandler(Object delegate) {
+ this.delegate = delegate;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ Method delegateMethod = delegate.getClass().getMethod(method.getName(),
+ method.getParameterTypes());
+ return delegateMethod.invoke(delegate, args);
+ }
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialogInterface.java b/utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialogInterface.java
new file mode 100644
index 00000000..87c64102
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/local/ui/TrayIconDialogInterface.java
@@ -0,0 +1,33 @@
+/*
+* 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.local.ui;
+
+import java.util.ResourceBundle;
+
+public interface TrayIconDialogInterface {
+
+ public abstract void displayInfo(String captionID, String messageID);
+
+ public abstract void displayWarning(String captionID, String messageID);
+
+ public abstract void displayError(String captionID, String messageID);
+
+ public abstract void init(ResourceBundle resourceBundel);
+
+ public abstract void setShutdownHook(BKUControllerInterface shutDown);
+
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/HexDump.java b/utils/src/main/java/at/gv/egiz/bku/utils/HexDump.java
new file mode 100644
index 00000000..88d49bad
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/HexDump.java
@@ -0,0 +1,75 @@
+/*
+* 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.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+
+public class HexDump {
+
+ public static String hexDump(InputStream is) throws IOException {
+ StringWriter writer = new StringWriter();
+ hexDump(is, writer);
+ return writer.toString();
+ }
+
+ public static void hexDump(InputStream is, Writer writer) throws IOException {
+ hexDump(is, writer, 16);
+ }
+
+ public static void hexDump(InputStream is, Writer writer, int chunkSize) throws IOException {
+
+ byte[] chunk = new byte[chunkSize];
+ long adr = 0;
+ for (int l; (l = is.read(chunk)) != -1;) {
+
+ writer.append(String.format("[%06x]", adr));
+ for (int i = 0; i < l; i++) {
+ if (i % 8 == 0) {
+ writer.append(" ");
+ } else {
+ writer.append(":");
+ }
+ writer.append(Integer.toHexString((chunk[i] & 240) >> 4));
+ writer.append(Integer.toHexString(chunk[i] & 15));
+ }
+
+ for (int i = 0; i < (chunkSize - l); i++) {
+ writer.append(" ");
+ }
+
+ for (int i = 0; i < l; i++) {
+ if (i % 8 == 0) {
+ writer.append(" ");
+ }
+ if (chunk[i] > 31 && chunk[i] < 127) {
+ writer.append((char) chunk[i]);
+ } else {
+ writer.append(".");
+ }
+ }
+
+ writer.append("\n");
+ adr += l;
+
+ }
+
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/StreamUtil.java b/utils/src/main/java/at/gv/egiz/bku/utils/StreamUtil.java
new file mode 100644
index 00000000..a774df2b
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/StreamUtil.java
@@ -0,0 +1,101 @@
+/*
+* 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.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+
+public class StreamUtil {
+
+ /**
+ * Copies data. None of the streams will be closed.
+ *
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ public static void copyStream(InputStream is, OutputStream os)
+ throws IOException {
+ copyStream(is, os, 1024);
+ }
+
+ /**
+ * Copies data. None of the streams will be closed.
+ *
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ public static void copyStream(InputStream is, OutputStream os, int bufferSize)
+ throws IOException {
+ byte[] buffer = new byte[bufferSize];
+ copyStream(is, os, buffer);
+ }
+
+ /**
+ * Copies data. None of the streams will be closed.
+ *
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ public static void copyStream(InputStream is, OutputStream os, byte[] buffer)
+ throws IOException {
+ for (int i = is.read(buffer); i > -1; i = is.read(buffer)) {
+ os.write(buffer, 0, i);
+ }
+ }
+
+ /**
+ * Copies data. None of the streams will be closed.
+ *
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ public static void copyStream(Reader is, Writer os)
+ throws IOException {
+ copyStream(is, os, 1024);
+ }
+
+ /**
+ * Copies data. None of the streams will be closed.
+ *
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ public static void copyStream(Reader is, Writer os, int bufferSize)
+ throws IOException {
+ char[] chars = new char[bufferSize];
+ for (int i = is.read(chars); i > -1; i = is.read(chars)) {
+ os.write(chars, 0, i);
+ }
+ }
+
+
+ public static String asString(InputStream is, String charset)
+ throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ copyStream(is, os);
+ return new String(os.toByteArray(), charset);
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/binding/Protocol.java b/utils/src/main/java/at/gv/egiz/bku/utils/binding/Protocol.java
new file mode 100644
index 00000000..f0504697
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/binding/Protocol.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.bku.utils.binding;
+
+public enum Protocol {
+ HTTP("http"), HTTPS("https");
+
+ private String name;
+
+ Protocol(String s) {
+ name = s;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public static Protocol fromString(String protocol) {
+ if (HTTP.toString().equalsIgnoreCase(protocol)) {
+ return HTTP;
+ }
+ if (HTTPS.toString().equalsIgnoreCase(protocol)) {
+ return HTTPS;
+ }
+ return null;
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FormDataURLSupplier.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FormDataURLSupplier.java
new file mode 100644
index 00000000..7272f1bb
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FormDataURLSupplier.java
@@ -0,0 +1,26 @@
+/*
+* 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.utils.urldereferencer;
+
+import java.io.InputStream;
+
+public interface FormDataURLSupplier {
+ public static final String PROPERTY_KEY_NAME = "at.gv.egiz.bku.util.urldereferencer.FormDataURLSupplier";
+
+ public InputStream getFormData(String aParameterName);
+ public String getFormDataContentType(String aParameterName);
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/HTTPURLProtocolHandlerImpl.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/HTTPURLProtocolHandlerImpl.java
new file mode 100644
index 00000000..5cba2e1d
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/HTTPURLProtocolHandlerImpl.java
@@ -0,0 +1,76 @@
+/*
+* 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.utils.urldereferencer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.InvalidParameterException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class HTTPURLProtocolHandlerImpl implements URLProtocolHandler {
+
+ private static Log log = LogFactory.getLog(HTTPURLProtocolHandlerImpl.class);
+
+ public final static String HTTP = "http";
+ public final static String HTTPS = "https";
+ public final static String FORMDATA = "formdata";
+ public final static String[] PROTOCOLS = { HTTP, HTTPS, FORMDATA };
+
+ public StreamData dereference(String aUrl, URLDereferencerContext aContext)
+ throws IOException {
+ String urlString = aUrl.toLowerCase().trim();
+ if (urlString.startsWith(FORMDATA)) {
+ log.debug("Requested to dereference a formdata url");
+ return dereferenceFormData(aUrl, aContext);
+ }
+
+ URL url = new URL(aUrl);
+ if ((!HTTP.equalsIgnoreCase(url.getProtocol()) && (!HTTPS
+ .equalsIgnoreCase(url.getProtocol())))) {
+ throw new InvalidParameterException("Url " + aUrl + " not supported");
+ }
+ return dereferenceHTTP(url);
+ }
+
+ protected StreamData dereferenceHTTP(URL url) throws IOException {
+ HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
+ return new StreamData(url.toString(), httpConn.getContentType(), httpConn
+ .getInputStream());
+ }
+
+ protected StreamData dereferenceFormData(String aUrl,
+ URLDereferencerContext aContext) throws IOException {
+ log.debug("Dereferencing formdata url: " + aUrl);
+ String[] parts = aUrl.split(":", 2);
+ FormDataURLSupplier supplier = (FormDataURLSupplier) aContext
+ .getProperty(FormDataURLSupplier.PROPERTY_KEY_NAME);
+ if (supplier == null) {
+ throw new NullPointerException(
+ "No FormdataUrlSupplier found in provided context");
+ }
+ String contentType = supplier.getFormDataContentType(parts[1]);
+ InputStream is = supplier.getFormData(parts[1]);
+ if (is != null) {
+ return new StreamData(aUrl, contentType, is);
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/SimpleFormDataContextImpl.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/SimpleFormDataContextImpl.java
new file mode 100644
index 00000000..e9da9c81
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/SimpleFormDataContextImpl.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.bku.utils.urldereferencer;
+
+public class SimpleFormDataContextImpl implements URLDereferencerContext {
+ protected FormDataURLSupplier formdata;
+
+ /**
+ *
+ * @param formdata must not be null
+ */
+ public SimpleFormDataContextImpl(FormDataURLSupplier formdata) {
+ if (formdata == null) {
+ throw new NullPointerException("FormdataURLSupplier must not be null");
+ }
+ this.formdata = formdata;
+ }
+
+ @Override
+ public Object getProperty(Object key) {
+ if (key.equals(FormDataURLSupplier.PROPERTY_KEY_NAME)) {
+ return formdata;
+ }
+ return null;
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/StreamData.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/StreamData.java
new file mode 100644
index 00000000..541c6878
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/StreamData.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.bku.utils.urldereferencer;
+
+import java.io.InputStream;
+
+/**
+ * This class models the result when dereferencing an URL.
+ *
+ */
+public class StreamData {
+
+ protected InputStream inputStream;
+ protected String url;
+ protected String contentType;
+
+ /**
+ *
+ * @param url
+ * @param contentType
+ * @param stream must not be null
+ */
+ public StreamData(String url, String contentType, InputStream stream) {
+ if (stream == null) {
+ throw new NullPointerException("Parameter inputstream must not be null");
+ }
+ inputStream = stream;
+ this.contentType = contentType;
+ this.url = url;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ /**
+ *
+ * @return the returned stream must be closed
+ */
+ public InputStream getStream() {
+ return inputStream;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URIResolverAdapter.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URIResolverAdapter.java
new file mode 100644
index 00000000..2d11010e
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URIResolverAdapter.java
@@ -0,0 +1,96 @@
+/*
+* 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.utils.urldereferencer;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Adapter to make the Urldereferencer work as URIResolver for
+ * Stylesheettransforms.
+ *
+ * @author wbauer
+ *
+ */
+public class URIResolverAdapter implements URIResolver {
+
+ private static Log log = LogFactory.getLog(URIResolverAdapter.class);
+
+ private URLDereferencer urlDereferencer;
+ private URLDereferencerContext ctx;
+
+ /**
+ *
+ * @param deferecencer
+ * must not be null
+ * @param ctx may be null
+ */
+ public URIResolverAdapter(URLDereferencer deferecencer,
+ URLDereferencerContext ctx) {
+ if (deferecencer == null) {
+ throw new NullPointerException("Urlderefencer must not be set to null");
+ }
+ this.urlDereferencer = deferecencer;
+ this.ctx = ctx;
+ }
+
+ @Override
+ public Source resolve(String href, String base) throws TransformerException {
+ log.debug("Resolving href: "+href+" base: "+base);
+ try {
+ URI baseUri = null;
+ URI hrefUri = new URI(href);
+ if (base != null) {
+ baseUri = new URI(base);
+ }
+ URI abs;
+ if (baseUri != null) {
+ abs = baseUri.resolve(hrefUri);
+ } else {
+ abs = hrefUri;
+ }
+ if (!abs.isAbsolute()) {
+ throw new TransformerException("Only absolute URLs are supported");
+ }
+ return new StreamSource(urlDereferencer.dereference(abs.toString(), ctx)
+ .getStream());
+ } catch (URISyntaxException e) {
+ throw new TransformerException("Cannot resolve URI: base:" + base
+ + " href:" + href, e);
+ } catch (IOException iox) {
+ throw new TransformerException("Cannot resolve URI: base:" + base
+ + " href:" + href, iox);
+ }
+ }
+
+ public URLDereferencerContext getCtx() {
+ return ctx;
+ }
+
+ public void setCtx(URLDereferencerContext ctx) {
+ this.ctx = ctx;
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencer.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencer.java
new file mode 100644
index 00000000..d747753f
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencer.java
@@ -0,0 +1,90 @@
+/*
+* 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.utils.urldereferencer;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Class used to dereference (external URLs).
+ *
+ * @author wbauer
+ *
+ */
+public class URLDereferencer {
+
+ private static Log log = LogFactory.getLog(URLDereferencer.class);
+
+ private static URLDereferencer instance = new URLDereferencer();
+
+ private Map<String, URLProtocolHandler> handlerMap = new HashMap<String, URLProtocolHandler>();
+
+ private URLDereferencer() {
+ registerHandlers();
+ }
+
+ /**
+ *
+ * @param aUrl
+ * must not be null
+ * @param aContext
+ * @throws MalformedURLException
+ * if the protocol is not supported
+ */
+ public StreamData dereference(String aUrl, URLDereferencerContext aContext)
+ throws IOException {
+ log.debug("Looking for handler for URL: " + aUrl);
+ int i = aUrl.indexOf(":");
+ if (i == -1) {
+ throw new MalformedURLException("Invalid url: " + aUrl);
+ }
+ String protocol = aUrl.substring(0, i).toLowerCase().trim();
+ URLProtocolHandler handler = handlerMap.get(protocol);
+ if (handler == null) {
+ throw new MalformedURLException("No handler for protocol: " + protocol
+ + " found");
+ }
+ return handler.dereference(aUrl, aContext);
+ }
+
+ /**
+ * Registers a handler for a protocol.
+ *
+ * @param aProtocol
+ * @param aHandler
+ * may be set to null to disable this protocol
+ */
+ public void registerHandler(String aProtocol, URLProtocolHandler aHandler) {
+ handlerMap.put(aProtocol.toLowerCase(), aHandler);
+ }
+
+ public static URLDereferencer getInstance() {
+ return instance;
+ }
+
+ protected void registerHandlers() {
+ URLProtocolHandler handler = new HTTPURLProtocolHandlerImpl();
+ for (String proto : HTTPURLProtocolHandlerImpl.PROTOCOLS) {
+ handlerMap.put(proto, handler);
+ }
+ }
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencerContext.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencerContext.java
new file mode 100644
index 00000000..6befd5b3
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLDereferencerContext.java
@@ -0,0 +1,27 @@
+/*
+* 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.utils.urldereferencer;
+
+public interface URLDereferencerContext {
+
+ /**
+ *
+ * @param key
+ * @return may return null
+ */
+ public Object getProperty(Object key);
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLProtocolHandler.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLProtocolHandler.java
new file mode 100644
index 00000000..f584f450
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/URLProtocolHandler.java
@@ -0,0 +1,32 @@
+/*
+* 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.utils.urldereferencer;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+
+public interface URLProtocolHandler {
+ /**
+ *
+ * @param aUrl
+ * @param aContext
+ * @return the streamdata of this url or null if the url cannot be resolved.
+ * @throws IOException
+ */
+ public StreamData dereference(String aUrl, URLDereferencerContext aContext) throws IOException;
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java b/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java
new file mode 100644
index 00000000..32c7c5e6
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/dom/DOMUtils.java
@@ -0,0 +1,115 @@
+/*
+* 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.dom;
+
+import iaik.utils.Base64OutputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Text;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+
+public final class DOMUtils {
+
+ /**
+ * DOM Implementation.
+ */
+ private static String DOM_LS_3_0 = "LS 3.0";
+
+ private static DOMImplementationLS domImplLS;
+
+ private DOMUtils() {
+ }
+
+ private static synchronized void ensureDOMImplementation() {
+
+ if (domImplLS == null) {
+
+ DOMImplementationRegistry registry;
+ try {
+ registry = DOMImplementationRegistry.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to get DOMImplementationRegistry.");
+ }
+
+ domImplLS = (DOMImplementationLS) registry.getDOMImplementation(DOM_LS_3_0);
+ if (domImplLS == null) {
+ throw new RuntimeException("Failed to get DOMImplementation " + DOM_LS_3_0);
+ }
+
+ }
+
+ }
+
+ public static DOMImplementationLS getDOMImplementationLS() {
+
+ if (domImplLS == null) {
+ ensureDOMImplementation();
+ }
+
+ return domImplLS;
+ }
+
+ public static Document createDocument() {
+
+ // This does not work with the Xerces-J version (2.6.2) included in Java 6
+ //document = ((DOMImplementation) domImplLS).createDocument(null, null, null);
+ // Therefore we have to employ the good old DocumentBuilderFactory
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db;
+ try {
+ db = dbf.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ return db.newDocument();
+
+ }
+
+ public static Text createBase64Text(byte[] bytes, Document doc) throws IOException {
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ Base64OutputStream base64OutputStream = new Base64OutputStream(outputStream);
+ base64OutputStream.write(bytes);
+ base64OutputStream.flush();
+ return doc.createTextNode(outputStream.toString("ASCII"));
+
+ }
+
+ public static Text createBase64Text(InputStream bytes, Document doc) throws IOException {
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ Base64OutputStream base64OutputStream = new Base64OutputStream(outputStream, new byte[] {0xa});
+
+ byte[] b = new byte[2^8];
+ for(int l; (l = bytes.read(b)) != -1;) {
+ base64OutputStream.write(b, 0, l);
+ }
+
+ base64OutputStream.flush();
+ return doc.createTextNode(outputStream.toString("ASCII"));
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java b/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java
new file mode 100644
index 00000000..5f4e5d92
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java
@@ -0,0 +1,416 @@
+/*
+* 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.idlink;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+
+import org.w3._2000._09.xmldsig_.KeyValueType;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.AbstractPersonType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType.Value;
+import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType.FamilyName;
+import at.gv.egiz.idlink.ans1.CitizenPublicKey;
+import at.gv.egiz.idlink.ans1.IdentityLink;
+import at.gv.egiz.idlink.ans1.PersonData;
+import at.gv.egiz.idlink.ans1.PhysicalPersonData;
+import at.gv.egiz.xmldsig.KeyTypeNotSupportedException;
+import at.gv.egiz.xmldsig.KeyValueFactory;
+
+public class CompressedIdentityLinkFactory {
+
+ /**
+ * The instance returned by {@link #getInstance()}.
+ */
+ private static CompressedIdentityLinkFactory instance;
+
+ /**
+ * The <code>JAXBContext</code>.
+ */
+ private static JAXBContext jaxbContext;
+
+ /**
+ * The <code>KeyValueFactory</code>.
+ */
+ private static KeyValueFactory keyValueFactory;
+
+ /**
+ * Get an instance of this <code>CompressedIdentityLinkFactory</code>.
+ *
+ * @return an instance of this <code>CompressedIdentityLinkFactory</code>
+ */
+ public synchronized static CompressedIdentityLinkFactory getInstance() {
+ if (instance == null) {
+ instance = new CompressedIdentityLinkFactory();
+ }
+ return instance;
+ }
+
+ /**
+ * Private constructor.
+ */
+ private CompressedIdentityLinkFactory() {
+
+ keyValueFactory = new KeyValueFactory();
+
+ StringBuffer packageNames = new StringBuffer();
+ packageNames.append(at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(org.w3._2001._04.xmldsig_more_.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory.class.getPackage().getName());
+
+ try {
+ jaxbContext = JAXBContext.newInstance(packageNames.toString());
+ } catch (JAXBException e) {
+ // we should not get an JAXBException initializing the JAXBContext
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public IdentityLink createIdLink(CompressedIdentityLinkType compressedIdentityLinkType) {
+
+ // IssuerTemplate
+ String issuerTemplate = compressedIdentityLinkType.getIssuerTemplate();
+
+ // AssertionId
+ String assertionID = compressedIdentityLinkType.getAssertionID();
+
+ // IssueInstant
+ String issueInstant = compressedIdentityLinkType.getIssueInstant();
+
+ AbstractPersonType personDataType = compressedIdentityLinkType.getPersonData();
+
+ String baseId = null;
+
+ List<IdentificationType> identifications = personDataType.getIdentification();
+ for (IdentificationType identificationType : identifications) {
+ String type = identificationType.getType();
+ if ("urn:publicid:gv.at:baseid".equals(type)) {
+ baseId = identificationType.getValue().getValue();
+ }
+ }
+
+ String givenName = null;
+ String familyName = null;
+ String dateOfBirth = null;
+
+ if (personDataType instanceof PhysicalPersonType) {
+ PhysicalPersonType physicalPersonType = (PhysicalPersonType) personDataType;
+ PersonNameType name = physicalPersonType.getName();
+ List<String> givenNames = name.getGivenName();
+ if (!givenNames.isEmpty()) {
+ givenName = givenNames.get(0);
+ }
+ List<FamilyName> familyNames = name.getFamilyName();
+ if (!familyNames.isEmpty()) {
+ familyName = familyNames.get(0).getValue();
+ }
+ dateOfBirth = physicalPersonType.getDateOfBirth();
+ }
+
+ PhysicalPersonData physicalPersonData = new PhysicalPersonData(baseId, givenName, familyName, dateOfBirth);
+ PersonData personData = new PersonData(physicalPersonData);
+
+ int numKeys = compressedIdentityLinkType.getCitizenPublicKey().size();
+ CitizenPublicKey[] citizenPublicKeys = new CitizenPublicKey[numKeys];
+ for (int i = 0; i < numKeys;) {
+ citizenPublicKeys[i] = new CitizenPublicKey(++i);
+ }
+
+ byte[] signatureValue = compressedIdentityLinkType.getSignatureValue();
+ byte[] referenceDigest = compressedIdentityLinkType.getReferenceDigest();
+ byte[] referenceManifestDigest = compressedIdentityLinkType.getReferenceManifestDigest();
+ byte[] manifestReferenceDigest = compressedIdentityLinkType.getManifestReferenceDigest();
+
+ IdentityLink idLink = new IdentityLink(issuerTemplate, assertionID, issueInstant, personData, citizenPublicKeys, signatureValue);
+ idLink.setReferenceDigest(referenceDigest);
+ idLink.setReferenceManifestDigest(referenceManifestDigest);
+ idLink.setManifestReferenceDigest(manifestReferenceDigest);
+
+ return idLink;
+
+ }
+
+ /**
+ * Creates a new <code>CompressedIdentityLink</code> element from the given
+ * ASN.1 representation of an <code>idLink</code>.
+ *
+ * @param idLink
+ * the ASN.1 representation of an <code>IdentityLink</code>
+ * @param certificates
+ * a list of {@link X509Certificate}s containing the corresponding
+ * public keys
+ * @param domainId TODO
+ * @return a new <code>CompressedIdentityLink</code> element
+ *
+ * @throws NullPointerException
+ * if <code>idLink</code> or <code>certificates</code> is
+ * <code>null</code>
+ * @throws IllegalArgumentException
+ * if <code>idLink</code> references certificates not in the range
+ * of the <code>certificates</code> list
+ */
+ public JAXBElement<CompressedIdentityLinkType> createCompressedIdentityLink(
+ at.gv.egiz.idlink.ans1.IdentityLink idLink,
+ List<X509Certificate> certificates, String domainId) {
+
+ at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory prFactory =
+ new at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory();
+
+ at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory pbFactory =
+ new at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory();
+
+ org.w3._2000._09.xmldsig_.ObjectFactory dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
+
+ // PersonData
+ PhysicalPersonData __physicalPersonData = idLink.getPersonData()
+ .getPhysicalPerson();
+
+ Value identificationTypeValue = prFactory.createIdentificationTypeValue();
+ identificationTypeValue.setValue(__physicalPersonData.getBaseId());
+ IdentificationType identificationType = prFactory
+ .createIdentificationType();
+ identificationType.setValue(identificationTypeValue);
+ if (domainId != null) {
+ identificationType.setType(domainId);
+ } else {
+ identificationType.setType("urn:publicid:gv.at:baseid");
+ }
+
+ PersonNameType personNameType = prFactory.createPersonNameType();
+ FamilyName personNameTypeFamilyName = prFactory
+ .createPersonNameTypeFamilyName();
+ personNameTypeFamilyName.setValue(__physicalPersonData.getFamilyName());
+ personNameType.getFamilyName().add(personNameTypeFamilyName);
+ personNameType.getGivenName().add(__physicalPersonData.getGivenName());
+
+ PhysicalPersonType physicalPersonType = prFactory
+ .createPhysicalPersonType();
+ physicalPersonType.getIdentification().add(identificationType);
+ physicalPersonType.setName(personNameType);
+ physicalPersonType.setDateOfBirth(__physicalPersonData.getDateOfBirth());
+
+ // CompressedIdentityLink
+ CompressedIdentityLinkType compressedIdentityLinkType = pbFactory
+ .createCompressedIdentityLinkType();
+ compressedIdentityLinkType.setIssuerTemplate(idLink.getIssuerTemplate());
+ compressedIdentityLinkType.setAssertionID(idLink.getAssertionID());
+ compressedIdentityLinkType.setIssueInstant(idLink.getIssueInstant());
+ compressedIdentityLinkType.setPersonData(physicalPersonType);
+
+ // CitizenPublicKey
+ CitizenPublicKey[] __citizenPublicKeys = idLink.getCitizenPublicKeys();
+ for (CitizenPublicKey __citizenPublicKey : __citizenPublicKeys) {
+
+ X509Certificate certificate = certificates.get(__citizenPublicKey.getOnToken());
+ PublicKey publicKey = certificate.getPublicKey();
+
+ JAXBElement<?> keyValue;
+ try {
+ keyValue = keyValueFactory.createKeyValue(publicKey);
+ } catch (KeyTypeNotSupportedException e) {
+ // TODO: handle exception properly
+ throw new RuntimeException(e);
+ }
+
+ KeyValueType keyValueType = dsFactory.createKeyValueType();
+ keyValueType.getContent().add(keyValue);
+
+ compressedIdentityLinkType.getCitizenPublicKey().add(keyValueType);
+ }
+
+ compressedIdentityLinkType.setSignatureValue(idLink.getSignatureValue());
+ compressedIdentityLinkType.setReferenceDigest(idLink.getReferenceDigest());
+ compressedIdentityLinkType.setReferenceManifestDigest(idLink
+ .getReferenceManifestDigest());
+ compressedIdentityLinkType.setManifestReferenceDigest(idLink
+ .getManifestReferenceDigest());
+ JAXBElement<CompressedIdentityLinkType> compressedIdentityLink = pbFactory
+ .createCompressedIdentityLink(compressedIdentityLinkType);
+
+ return compressedIdentityLink;
+
+ }
+
+ /**
+ * Marshall the given <code>compressedIdentityLink</code> into a DOM document
+ * with the given Nodes as <code>parent</code> and <code>nextSibling</code>
+ * nodes.
+ *
+ * @param compressedIdentityLink
+ * the <code>CompressedIdentityLink</code> element
+ * @param parent
+ * the parent node
+ * @param nextSibling
+ * the next sibling node (may be <code>null</code>)
+ * @param applyWorkarounds
+ * apply workarounds as spefiyed by
+ * {@link #applyWorkarounds(Element, int)}
+ *
+ * @throws JAXBException
+ * if an unexpected error occurs while marshalling
+ * @throws NullPointerException
+ * if <code>compressdIdentityLink</code> or <code>parent</code> is
+ * <code>null</code>
+ */
+ public void marshallCompressedIdentityLink(
+ JAXBElement<CompressedIdentityLinkType> compressedIdentityLink,
+ Node parent, Node nextSibling, boolean applyWorkarounds) throws JAXBException {
+
+ DOMResult result = new DOMResult(parent, nextSibling);
+
+
+ try {
+ Marshaller marshaller = jaxbContext.createMarshaller();
+
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+ marshaller.marshal(compressedIdentityLink, result);
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+
+ if (applyWorkarounds) {
+ Element element = (Element) ((nextSibling != null)
+ ? nextSibling.getPreviousSibling()
+ : parent.getFirstChild());
+ applyWorkarounds(element, 76);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public CompressedIdentityLinkType unmarshallCompressedIdentityLink(Source source) throws JAXBException {
+
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ return ((JAXBElement<CompressedIdentityLinkType>) unmarshaller.unmarshal(source)).getValue();
+
+ }
+
+ /**
+ * Apply some workarounds to the given CompressedIdentityLink
+ * <code>element</code> to achieve compatibility with IdentityLink
+ * transformation stylesheets that have been designed for a (buggy) form of
+ * the CompressedIdentityLink as produced by a well-known citizen card
+ * environment implementation.
+ *
+ * <ol>
+ * <li>Replace the attribute node <code>URN</code> of the
+ * <code>NamedCurve</code> element of an <code>ECDSAKeyValue</code> element by
+ * a child text-node with the same content.</li>
+ * <li>Replace the attribute nodes <code>Value</code> of the <code>X</code>
+ * and <code>Y</code> elements of an <code>ECDSAKeyValue</code> element by a
+ * child text-node with the same content.</li>
+ * <li>Insert &quot;\n&quot; at <code>base64LineLength</code> into the Base64
+ * content of the <code>Modulus</code> element of an <code>RSAKeyValue</code>
+ * element.
+ * </ol>
+ *
+ * @param element
+ * the <code>CompressedIdentityLink</code> element
+ * @param base64LineLength
+ * the line length of Base64 content
+ */
+ public void applyWorkarounds(Element element, int base64LineLength) {
+
+ Document document = element.getOwnerDocument();
+
+ NodeList nodeList = element.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmldsig-more#", "NamedCurve");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node ecdsaNameCurve = nodeList.item(i);
+ Attr attrNode = ((Element) ecdsaNameCurve).getAttributeNodeNS(null,
+ "URN");
+ ecdsaNameCurve
+ .appendChild(document.createTextNode(attrNode.getValue()));
+ ((Element) ecdsaNameCurve).removeAttributeNode(attrNode);
+ }
+ nodeList = document.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmldsig-more#", "X");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node x = nodeList.item(i);
+ Attr attrNode = ((Element) x).getAttributeNodeNS(null, "Value");
+ x.appendChild(document.createTextNode(attrNode.getValue()));
+ ((Element) x).removeAttributeNode(attrNode);
+ }
+ nodeList = document.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmldsig-more#", "Y");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node y = nodeList.item(i);
+ Attr attrNode = ((Element) y).getAttributeNodeNS(null, "Value");
+ y.appendChild(document.createTextNode(attrNode.getValue()));
+ ((Element) y).removeAttributeNode(attrNode);
+ }
+
+ if (base64LineLength > 0) {
+ nodeList = document.getElementsByTagNameNS(
+ "http://www.w3.org/2000/09/xmldsig#", "Modulus");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node modulus = nodeList.item(i);
+ String value = ((Element) modulus).getTextContent();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(value.getBytes())));
+ char[] buff = new char[base64LineLength];
+ StringBuffer newValue = new StringBuffer();
+ int found = 0;
+ try {
+ while ((found = reader.read(buff)) > 0) {
+ newValue.append(buff, 0, found);
+ if (found == base64LineLength)
+ newValue.append('\n');
+ }
+ } catch (IOException e) {
+ // this should never happen, as we are reading from a ByteArrayInputStream
+ throw new RuntimeException(e);
+ }
+ ((Element) modulus).setTextContent(newValue.toString());
+ }
+
+ }
+
+
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkTransformer.java b/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkTransformer.java
new file mode 100644
index 00000000..7886b07d
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkTransformer.java
@@ -0,0 +1,285 @@
+/*
+* 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.idlink;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+public class IdentityLinkTransformer {
+
+ private class IdLTransformer {
+
+ /**
+ * Is transformer in use?
+ */
+ private boolean inUse = false;
+
+ /**
+ * How often has this transformer been used?
+ */
+ private int timesUsed = 0;
+
+ /**
+ * The time this transformer has been created.
+ */
+ private long created;
+
+ /**
+ * When has this transformer been used the last time?
+ */
+ private long lastTimeUsed;
+
+ /**
+ * Average performance in milliseconds.
+ */
+ private long time;
+
+ /**
+ * Time used for initialization.
+ */
+ private long initTime;
+
+ /**
+ * The stylesheet transformer.
+ */
+ private Transformer transformer;
+
+ /**
+ * Stylesheet URL.
+ */
+ private String stylesheetURL;
+
+ /**
+ *
+ * @param stylesheetURL
+ * @throws IOException
+ * @throws TransformerConfigurationException
+ */
+ public IdLTransformer(String stylesheetURL) throws IOException, TransformerConfigurationException {
+
+ created = System.currentTimeMillis();
+
+ // TODO: implement stylesheet cache
+ this.stylesheetURL = stylesheetURL;
+ URL url = new URL(stylesheetURL);
+
+ if (!"http".equalsIgnoreCase(url.getProtocol()) && !"https".equalsIgnoreCase(url.getProtocol())) {
+ throw new MalformedURLException("Protocol " + url.getProtocol() + " not supported for IssuerTemplate URL.");
+ }
+ StreamSource source = new StreamSource(url.openStream());
+
+ transformer = factory.newTransformer(source);
+
+ initTime = System.currentTimeMillis() - created;
+
+ }
+
+ public void transform(Source xmlSource, Result outputTarget) throws TransformerException {
+ long t0 = System.currentTimeMillis();
+ try {
+ transformer.transform(xmlSource, outputTarget);
+ } catch (TransformerException e) {
+ throw e;
+ } finally {
+ inUse = false;
+ long t1 = System.currentTimeMillis();
+ time += (t1 - t0);
+ timesUsed++;
+ lastTimeUsed = System.currentTimeMillis();
+ }
+ }
+
+ /**
+ * @return <code>true</code> if this transformer is in use, or <code>false</code> otherwise
+ */
+ public boolean isInUse() {
+ return inUse;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer str = new StringBuffer();
+ str.append("Transformer ").append(stylesheetURL)
+ .append("\n created ").append(new Date(created)).append(" used ").append(
+ timesUsed).append(" times, (init ").append(initTime).append("ms / ")
+ .append(((float) time) / timesUsed).append("ms avg) last time ").append(new Date(lastTimeUsed));
+ return str.toString();
+ }
+
+ }
+
+ /**
+ * The transfomer factory.
+ */
+ private static TransformerFactory factory;
+
+ /**
+ * The instance to be returned by {@link #getInstance()}.
+ */
+ private static IdentityLinkTransformer instance;
+
+ /**
+ * Returns an instance of this <code>IdentityLinkTransfomer</code>.
+ *
+ * @return an instance of this <code>IdentityLinkTransformer</code>
+ */
+ public static IdentityLinkTransformer getInstance() {
+ if (instance == null) {
+ instance = new IdentityLinkTransformer();
+ factory = TransformerFactory.newInstance();
+ }
+ return instance;
+ }
+
+ /**
+ * Sets the given <code>domainIdentifier</code> on the corresponding
+ * node of the given <code>idLink</code>.
+ * <p>This method may be used to cope with a flaw in the IssuerTemplate-Stylesheets
+ * used to transform a <code>CompressedIdentitiyLink</code> into an
+ * <code>IdentityLink</code>. Some IssuerTemplate-Stylesheets do not
+ * consider the <code>pr:Type</code> element value of the
+ * <code>CompressedIdentityLink</code> and render a <code>pr:Type</code>
+ * element value of <code>urn:publicid:gv.at:baseid</code>
+ * into the <code>IdentityLink</code> structure. This method allows to
+ * set the <code>pr:Type</code> element value on the given <code>idLink</code>
+ * after the transformation.
+ * </p>
+ *
+ * @param idLink the <code>IdentityLink</code> element or one of it's ancestors.
+ * Must not be <code>null</code>.
+ *
+ * @param domainIdentifier the value to be set for the <code>pr:Type</code> element
+ *
+ * @throws NullPointerException if <code>idLink</code> is <code>null</code>.
+ */
+ public static void setDomainIdentifier(Node idLink, String domainIdentifier) {
+
+ Element element;
+ if (idLink instanceof Element) {
+ element = (Element) idLink;
+ } else if (idLink instanceof Document) {
+ element = ((Document) idLink).getDocumentElement();
+ } else if (idLink != null) {
+ Document document = idLink.getOwnerDocument();
+ element = document.getDocumentElement();
+ } else {
+ throw new NullPointerException("Parameter 'idLink' must no be null.");
+ }
+
+ NodeList nodeList = element.getElementsByTagNameNS(
+ "http://reference.e-government.gv.at/namespace/persondata/20020228#",
+ "Type");
+
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ if (nodeList.item(i) instanceof Element) {
+ Element typeElement = (Element) nodeList.item(i);
+ NodeList children = typeElement.getChildNodes();
+ for (int j = 0; j < children.getLength(); j++) {
+ if (children.item(j) instanceof Text) {
+ ((Text) children.item(j)).setNodeValue(domainIdentifier);
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * The pool of <code>Transformer</code>.
+ */
+ private Map<String, List<IdLTransformer>> pool;
+
+ /**
+ * Private constructor.
+ */
+ private IdentityLinkTransformer() {
+ pool = new HashMap<String, List<IdLTransformer>>();
+ }
+
+ private synchronized IdLTransformer getFreeTransfomer(String stylesheetURL) throws TransformerConfigurationException, IOException {
+
+ IdLTransformer transformer = null;
+
+ List<IdLTransformer> transfomerList = pool.get(stylesheetURL);
+ if (transfomerList == null) {
+ transfomerList = new ArrayList<IdLTransformer>();
+ pool.put(stylesheetURL, transfomerList);
+ }
+
+ for (IdLTransformer candTransformer : transfomerList) {
+ if (!candTransformer.inUse) {
+ transformer = candTransformer;
+ break;
+ }
+ }
+
+ if (transformer == null) {
+ transformer = new IdLTransformer(stylesheetURL);
+ transfomerList.add(transformer);
+ }
+
+ transformer.inUse = true;
+ return transformer;
+
+ }
+
+ public void transformIdLink(String stylesheetURL, Source source, Result result) throws IOException, TransformerException {
+ IdLTransformer transformer = getFreeTransfomer(stylesheetURL);
+ transformer.transform(source, result);
+ }
+
+ public String getStatistics() {
+
+ StringBuffer str = new StringBuffer();
+ Iterator<String> keys = pool.keySet().iterator();
+ int count = 0;
+ while (keys.hasNext()) {
+ String stylesheetURL = (String) keys.next();
+ str.append("Stylesheet URL: ").append(stylesheetURL);
+ Iterator<IdLTransformer> transformer = pool.get(stylesheetURL).iterator();
+ while (transformer.hasNext()) {
+ IdLTransformer idLTransformer = (IdLTransformer) transformer.next();
+ str.append("\n ").append(idLTransformer);
+ count++;
+ }
+ }
+ str.append("\n(").append(count).append(" transformer)");
+ return str.toString();
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/idlink/ans1/CitizenPublicKey.java b/utils/src/main/java/at/gv/egiz/idlink/ans1/CitizenPublicKey.java
new file mode 100644
index 00000000..c32cf2b9
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/idlink/ans1/CitizenPublicKey.java
@@ -0,0 +1,92 @@
+/*
+* 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.idlink.ans1;
+
+import java.math.BigInteger;
+
+import iaik.asn1.*;
+
+/**
+ * This class implements the ASN.1 representation of the
+ * <code>CitizenPublicKey</code> of a compressed identity link.
+ *
+ * <pre>CitizenPublicKey ::= CHOICE {
+ onToken [0] INTEGER,
+ referenceURL [1] UTF8String,
+ x509Data [2] SubjectPublicKeyInfo
+}
+</pre>
+ *
+ * @author mivkovic@egiz.gv.at, mcentner@egiz.gv.at
+ */
+public class CitizenPublicKey implements ASN1Type {
+
+ /**
+ * <code>onToken</code>
+ */
+ private int onToken; // INTEGER
+
+ /**
+ * Creates a new <code>CitizenPublicKey</code> with the given
+ * <code>onToken</code> value.
+ *
+ * @param onToken
+ */
+ public CitizenPublicKey(int onToken) {
+ this.onToken = onToken;
+ }
+
+ /**
+ * Creates a new <code>CitizenPublicKey</code> from the given ASN.1 representation.
+ *
+ * @param obj
+ * @throws CodingException
+ */
+ public CitizenPublicKey(ASN1Object obj) throws CodingException {
+ decode(obj);
+ }
+
+ @Override
+ public void decode(ASN1Object obj) throws CodingException {
+ try {
+ BigInteger Value = (BigInteger)(obj.getValue());
+ onToken = Value.intValue();
+ } catch (Exception ex) {
+ throw new CodingException(ex.toString());
+ }
+ }
+
+ @Override
+ public ASN1Object toASN1Object() {
+ INTEGER ot = new INTEGER(onToken);
+ return ot;
+ }
+
+ /**
+ * Returns the DER encoding of this <code>CitizenPublicKey</code>.
+ *
+ * @return the DER encoding of this <code>CitizenPublicKey</code>
+ */
+ public byte[] getEncoded() {
+ return DerCoder.encode(toASN1Object());
+ }
+
+ public int getOnToken() {
+ return onToken;
+ }
+
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/idlink/ans1/IdentityLink.java b/utils/src/main/java/at/gv/egiz/idlink/ans1/IdentityLink.java
new file mode 100644
index 00000000..37e4b240
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/idlink/ans1/IdentityLink.java
@@ -0,0 +1,315 @@
+/*
+* 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.idlink.ans1;
+
+import iaik.asn1.ASN1Object;
+import iaik.asn1.ASN1Type;
+import iaik.asn1.BIT_STRING;
+import iaik.asn1.CON_SPEC;
+import iaik.asn1.CodingException;
+import iaik.asn1.DerCoder;
+import iaik.asn1.INTEGER;
+import iaik.asn1.SEQUENCE;
+import iaik.asn1.UTF8String;
+
+/**
+ * This class impelments an ASN.1 representation of the compressed <code>IdentiyLink</code>.
+ * <pre>
+PersonenBindung ::= SEQUENCE {
+ version INTEGER,
+ issuerTemplate UTF8String,
+ assertionID UTF8String,
+ issueInstant UTF8String,
+ personData PersonData,
+ citizenPublicKey SEQUENCE SIZE (1..MAX) OF CitizenPublicKey,
+ signatureValue BIT STRING,
+ referenceDigest [0] BIT STRING OPTIONAL,
+ referenceManifestDigest [1] BIT STRING OPTIONAL,
+ manifestReferenceDigest [2] BIT STRING OPTIONAL
+}
+</pre>
+ *
+ * @author mivkovic@egiz.gv.at, mcentner@egiz.gv.at
+ */
+public class IdentityLink implements ASN1Type {
+
+ private int version = 1; // INTEGER
+ private String issuerTemplate; // UTF8String
+ private String assertionID; // UTF8String
+ private String issueInstant; // UTF8String
+ private PersonData personData; // PersonData
+ private CitizenPublicKey[] citizenPublicKeys; // SEQUENCE SIZE (1..MAX) OF
+ private byte[] signatureValue; // BIT STRING
+ private byte[] referenceDigest; // BIT STRING OPTIONAL
+ private byte[] referenceManifestDigest; // BIT STRING OPTIONAL
+ private byte[] manifestReferenceDigest; // BIT STRING OPTIONAL
+
+ /**
+ * Creates a new <code>IdentityLink</code> with the given
+ * <code>issuerTemplate</code>, <code>assertionID</code>,
+ * <code>issueInstant</code>, <code>personData</code>,
+ * <code>citizenPublicKeys</code> and <code>signatureValue</code>.
+ *
+ * @param issuerTemplate
+ * @param assertionID
+ * @param issueInstant
+ * @param personData
+ * @param citizenPublicKeys
+ * @param signatureValue
+ */
+ public IdentityLink(String issuerTemplate, String assertionID,
+ String issueInstant, PersonData personData,
+ CitizenPublicKey[] citizenPublicKeys, byte[] signatureValue) {
+ this.issuerTemplate = issuerTemplate;
+ this.assertionID = assertionID;
+ this.issueInstant = issueInstant;
+ this.personData = personData;
+ this.citizenPublicKeys = citizenPublicKeys;
+ this.signatureValue = signatureValue;
+ }
+
+ /**
+ * Create a new IdentityLink from an ASN1Object.
+ *
+ * @param identiyLink
+ * @throws CodingException
+ */
+ public IdentityLink(ASN1Object identiyLink) throws CodingException {
+ decode(identiyLink);
+ }
+
+ @Override
+ public void decode(ASN1Object obj) throws CodingException {
+ issuerTemplate = (String) ((ASN1Object) obj.getComponentAt(1)).getValue();
+ assertionID = (String) ((ASN1Object) obj.getComponentAt(2)).getValue();
+ issueInstant = (String) ((ASN1Object) obj.getComponentAt(3)).getValue();
+
+ if (((CON_SPEC) obj.getComponentAt(4)).getAsnType().getTag() == 0)
+ personData = new PersonData((ASN1Object) obj.getComponentAt(4).getValue());
+ else {
+ throw new CodingException("CorporateBodyData currently not supported.");
+ }
+
+ SEQUENCE publicKeySequence = (SEQUENCE) obj.getComponentAt(5);
+ int anz = publicKeySequence.countComponents();
+ citizenPublicKeys = new CitizenPublicKey[anz];
+ for (int i = 0; i < citizenPublicKeys.length; i++) {
+ CON_SPEC tmp = (CON_SPEC) publicKeySequence.getComponentAt(i);
+ if (tmp.getAsnType().getTag() == 0) {
+ citizenPublicKeys[i] = new CitizenPublicKey((ASN1Object) tmp.getValue());
+ } else {
+ throw new CodingException(
+ "Currently only PublicKeys on token are supported.");
+ }
+ }
+
+ signatureValue = (byte[]) ((ASN1Object) obj.getComponentAt(6)).getValue();
+
+ for (int i = 7; i < obj.countComponents(); i++) {
+ CON_SPEC tmp = (CON_SPEC) obj.getComponentAt(i);
+ switch (tmp.getAsnType().getTag()) {
+ case 0:
+ referenceDigest = (byte[]) ((BIT_STRING) tmp.getValue()).getValue();
+ break;
+ case 1:
+ referenceManifestDigest = (byte[]) ((BIT_STRING) tmp.getValue())
+ .getValue();
+ break;
+ case 2:
+ manifestReferenceDigest = (byte[]) ((BIT_STRING) tmp.getValue())
+ .getValue();
+ break;
+ }
+
+ }
+
+ }
+
+ @Override
+ public ASN1Object toASN1Object() {
+ SEQUENCE pb = new SEQUENCE();
+ pb.addComponent(new INTEGER(version));
+ pb.addComponent(new UTF8String(issuerTemplate));
+ pb.addComponent(new UTF8String(assertionID));
+ pb.addComponent(new UTF8String(issueInstant));
+
+ pb.addComponent(new CON_SPEC(0, personData.toASN1Object()));
+ SEQUENCE seq = new SEQUENCE();
+ for (int i = 0; i < citizenPublicKeys.length; i++) {
+ seq.addComponent(new CON_SPEC(0, citizenPublicKeys[i].toASN1Object()));
+ }
+ pb.addComponent(seq);
+ pb.addComponent(new BIT_STRING(signatureValue));
+ if (referenceDigest != null)
+ pb.addComponent(new CON_SPEC(0, new BIT_STRING(referenceDigest)));
+ if (referenceManifestDigest != null)
+ pb.addComponent(new CON_SPEC(1, new BIT_STRING(referenceManifestDigest)));
+ if (manifestReferenceDigest != null)
+ pb.addComponent(new CON_SPEC(2, new BIT_STRING(manifestReferenceDigest)));
+ return pb;
+ }
+
+ /**
+ * Returns the DER encoding of this <code>IdentityLink</code>.
+ *
+ * @return the DER encoding of this <code>IdentityLink</code>
+ */
+ public byte[] toByteArray() {
+ return DerCoder.encode(toASN1Object());
+ }
+
+ /**
+ * @return the version
+ */
+ public int getVersion() {
+ return version;
+ }
+
+ /**
+ * @param version the version to set
+ */
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ /**
+ * @return the issuerTemplate
+ */
+ public String getIssuerTemplate() {
+ return issuerTemplate;
+ }
+
+ /**
+ * @param issuerTemplate the issuerTemplate to set
+ */
+ public void setIssuerTemplate(String issuerTemplate) {
+ this.issuerTemplate = issuerTemplate;
+ }
+
+ /**
+ * @return the assertionID
+ */
+ public String getAssertionID() {
+ return assertionID;
+ }
+
+ /**
+ * @param assertionID the assertionID to set
+ */
+ public void setAssertionID(String assertionID) {
+ this.assertionID = assertionID;
+ }
+
+ /**
+ * @return the issueInstant
+ */
+ public String getIssueInstant() {
+ return issueInstant;
+ }
+
+ /**
+ * @param issueInstant the issueInstant to set
+ */
+ public void setIssueInstant(String issueInstant) {
+ this.issueInstant = issueInstant;
+ }
+
+ /**
+ * @return the personData
+ */
+ public PersonData getPersonData() {
+ return personData;
+ }
+
+ /**
+ * @param personData the personData to set
+ */
+ public void setPersonData(PersonData personData) {
+ this.personData = personData;
+ }
+
+ /**
+ * @return the citizenPublicKeys
+ */
+ public CitizenPublicKey[] getCitizenPublicKeys() {
+ return citizenPublicKeys;
+ }
+
+ /**
+ * @param citizenPublicKeys the citizenPublicKeys to set
+ */
+ public void setCitizenPublicKeys(CitizenPublicKey[] citizenPublicKeys) {
+ this.citizenPublicKeys = citizenPublicKeys;
+ }
+
+ /**
+ * @return the signatureValue
+ */
+ public byte[] getSignatureValue() {
+ return signatureValue;
+ }
+
+ /**
+ * @param signatureValue the signatureValue to set
+ */
+ public void setSignatureValue(byte[] signatureValue) {
+ this.signatureValue = signatureValue;
+ }
+
+ /**
+ * @return the referenceDigest
+ */
+ public byte[] getReferenceDigest() {
+ return referenceDigest;
+ }
+
+ /**
+ * @param referenceDigest the referenceDigest to set
+ */
+ public void setReferenceDigest(byte[] referenceDigest) {
+ this.referenceDigest = referenceDigest;
+ }
+
+ /**
+ * @return the referenceManifestDigest
+ */
+ public byte[] getReferenceManifestDigest() {
+ return referenceManifestDigest;
+ }
+
+ /**
+ * @param referenceManifestDigest the referenceManifestDigest to set
+ */
+ public void setReferenceManifestDigest(byte[] referenceManifestDigest) {
+ this.referenceManifestDigest = referenceManifestDigest;
+ }
+
+ /**
+ * @return the manifestReferenceDigest
+ */
+ public byte[] getManifestReferenceDigest() {
+ return manifestReferenceDigest;
+ }
+
+ /**
+ * @param manifestReferenceDigest the manifestReferenceDigest to set
+ */
+ public void setManifestReferenceDigest(byte[] manifestReferenceDigest) {
+ this.manifestReferenceDigest = manifestReferenceDigest;
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/idlink/ans1/PersonData.java b/utils/src/main/java/at/gv/egiz/idlink/ans1/PersonData.java
new file mode 100644
index 00000000..2a537eb3
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/idlink/ans1/PersonData.java
@@ -0,0 +1,91 @@
+/*
+* 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.idlink.ans1;
+
+import iaik.asn1.*;
+
+/**
+ * This class represents the ASN.1 version of the <code>PersonData</code>
+ * of a compressed identity link.
+ *
+ * <pre>
+PersonData ::= CHOICE {
+ physcialPerson [0] PhysicalPersonData,
+ corporateBody [1] CorporateBodyData
+} </pre>
+ *
+ * @author mivkovic@egiz.gv.at, mcentner@egiz.gv.at
+ *
+ */
+public class PersonData implements ASN1Type {
+
+ /**
+ * <code>physicalPerson</code>
+ */
+ private PhysicalPersonData physicalPerson; // PhysicalPersonData
+
+ /**
+ * Creates a new <code>PersonData</code> with the given
+ * <code>physicalPersonData</code>.
+ *
+ * @param physicalPersonData
+ */
+ public PersonData(PhysicalPersonData physicalPersonData) {
+ physicalPerson = physicalPersonData;
+ }
+
+ /**
+ * Creates a new <code>PersonData</code> from its ASN.1 representation.
+ *
+ * @param obj
+ * @throws CodingException
+ */
+ public PersonData(ASN1Object obj) throws CodingException {
+ decode(obj);
+ }
+
+ @Override
+ public void decode(ASN1Object obj) throws CodingException {
+ try {
+ physicalPerson = new PhysicalPersonData(obj);
+ } catch (Exception ex) {
+ throw new CodingException(ex.toString());
+ }
+ }
+
+ @Override
+ public ASN1Object toASN1Object() {
+ return physicalPerson.toASN1Object();
+ }
+
+ /**
+ * Returns the DER encoded representation of this <code>PersonData</code>.
+ *
+ * @return the DER encoded representation of this <code>PersonData</code>
+ */
+ public byte[] getEncoded() {
+ return DerCoder.encode(toASN1Object());
+ }
+
+ /**
+ * @return the physicalPerson
+ */
+ public PhysicalPersonData getPhysicalPerson() {
+ return physicalPerson;
+ }
+
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/idlink/ans1/PhysicalPersonData.java b/utils/src/main/java/at/gv/egiz/idlink/ans1/PhysicalPersonData.java
new file mode 100644
index 00000000..a6aea97e
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/idlink/ans1/PhysicalPersonData.java
@@ -0,0 +1,143 @@
+/*
+* 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.idlink.ans1;
+
+import iaik.asn1.*;
+
+/**
+ * This class represents the ASN.1 version of the <code>PhysicalPersonData</code>
+ * of an compressed identity link.
+ *
+ * <pre>PhysicalPersonData ::= SEQUENCE {
+ baseId UTF8String,
+ givenName UTF8String,
+ familyName UTF8String,
+ dateOfBirth UTF8String
+}</pre>
+ *
+ * @author mivkovic@egiz.gv.at, mcentner@eigz.gv.at
+ */
+public class PhysicalPersonData implements ASN1Type {
+
+ /**
+ * <code>baseId</code>
+ */
+ private String baseId; // UTF8String
+
+ /**
+ * <code>givenName</code>
+ */
+ private String givenName; // UTF8String
+
+ /**
+ * <code>familyName</code>
+ */
+ private String familyName; // UTF8String
+
+ /**
+ * <code>dataOfBirth</code>
+ */
+ private String dateOfBirth; // UTF8String
+
+ /**
+ * Creates a new <code>PhysicalPersonData</code> with the
+ * given <code>baseId</code>, <code>givenName</code>, <code>familyName</code>
+ * and <code>dataOfBirth</code>.
+ *
+ * @param baseId
+ * @param givenName
+ * @param familyName
+ * @param dateOfBirth
+ */
+ public PhysicalPersonData(String baseId, String givenName, String familyName, String dateOfBirth) {
+ this.baseId = baseId;
+ this.givenName = givenName;
+ this.familyName = familyName;
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ /**
+ * Creates a new <code>PhysicalPersonData</code> from its ASN.1 representation.
+ *
+ * @param obj
+ *
+ * @throws CodingException
+ */
+ public PhysicalPersonData(ASN1Object obj) throws CodingException {
+ decode(obj);
+ }
+
+ @Override
+ public void decode(ASN1Object obj) throws CodingException {
+ try {
+ baseId = (String) ((ASN1Object) obj.getComponentAt(0)).getValue();
+ givenName = (String) ((ASN1Object) obj.getComponentAt(1)).getValue();
+ familyName = (String) ((ASN1Object) obj.getComponentAt(2)).getValue();
+ dateOfBirth = (String) ((ASN1Object) obj.getComponentAt(3)).getValue();
+ } catch (Exception ex) {
+ throw new CodingException(ex.toString());
+ }
+ }
+
+ @Override
+ public ASN1Object toASN1Object() {
+ SEQUENCE ppd = new SEQUENCE();
+ ppd.addComponent(new UTF8String(baseId));
+ ppd.addComponent(new UTF8String(givenName));
+ ppd.addComponent(new UTF8String(familyName));
+ ppd.addComponent(new UTF8String(dateOfBirth));
+ return ppd;
+ }
+
+ /**
+ * Returns the DER encoding of this <code>PhysicalPersonData</code>.
+ *
+ * @return the DER encoding of this <code>PhysicalPersonData</code>
+ */
+ public byte[] toByteArray() {
+ return DerCoder.encode(toASN1Object());
+ }
+
+ /**
+ * @return the baseId
+ */
+ public String getBaseId() {
+ return baseId;
+ }
+
+ /**
+ * @return the givenName
+ */
+ public String getGivenName() {
+ return givenName;
+ }
+
+ /**
+ * @return the familyName
+ */
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ /**
+ * @return the dateOfBirth
+ */
+ public String getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+} \ No newline at end of file
diff --git a/utils/src/main/java/at/gv/egiz/org/apache/tomcat/util/http/AcceptLanguage.java b/utils/src/main/java/at/gv/egiz/org/apache/tomcat/util/http/AcceptLanguage.java
new file mode 100644
index 00000000..231966ac
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/org/apache/tomcat/util/http/AcceptLanguage.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.org.apache.tomcat.util.http;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * Util to process the "Accept-Language" header. Used by facade to implement
+ * getLocale() and by StaticInterceptor.
+ *
+ * Not optimized - it's very slow.
+ *
+ * @author James Duncan Davidson [duncan@eng.sun.com]
+ * @author James Todd [gonzo@eng.sun.com]
+ * @author Jason Hunter [jch@eng.sun.com]
+ * @author Harish Prabandham
+ * @author costin@eng.sun.com
+ */
+public class AcceptLanguage {
+
+ public static Locale getLocale(String acceptLanguage) {
+ if( acceptLanguage == null ) return Locale.getDefault();
+
+ Hashtable<String,Vector<String>> languages =
+ new Hashtable<String,Vector<String>>();
+ Vector<Double> quality = new Vector<Double>();
+ processAcceptLanguage(acceptLanguage, languages, quality);
+
+ if (languages.size() == 0) return Locale.getDefault();
+
+ Vector<Locale> l = new Vector<Locale>();
+ extractLocales( languages,quality, l);
+
+ return (Locale)l.elementAt(0);
+ }
+
+ public static Enumeration getLocales(String acceptLanguage) {
+ // Short circuit with an empty enumeration if null header
+ if (acceptLanguage == null) {
+ Vector<Locale> v = new Vector<Locale>();
+ v.addElement(Locale.getDefault());
+ return v.elements();
+ }
+
+ Hashtable<String,Vector<String>> languages =
+ new Hashtable<String,Vector<String>>();
+ Vector<Double> quality=new Vector<Double>();
+ processAcceptLanguage(acceptLanguage, languages , quality);
+
+ if (languages.size() == 0) {
+ Vector<Locale> v = new Vector<Locale>();
+ v.addElement(Locale.getDefault());
+ return v.elements();
+ }
+ Vector<Locale> l = new Vector<Locale>();
+ extractLocales( languages, quality , l);
+ return l.elements();
+ }
+
+ private static void processAcceptLanguage( String acceptLanguage,
+ Hashtable<String,Vector<String>> languages, Vector<Double> q)
+ {
+ StringTokenizer languageTokenizer =
+ new StringTokenizer(acceptLanguage, ",");
+
+ while (languageTokenizer.hasMoreTokens()) {
+ String language = languageTokenizer.nextToken().trim();
+ int qValueIndex = language.indexOf(';');
+ int qIndex = language.indexOf('q');
+ int equalIndex = language.indexOf('=');
+ Double qValue = new Double(1);
+
+ if (qValueIndex > -1 &&
+ qValueIndex < qIndex &&
+ qIndex < equalIndex) {
+ String qValueStr = language.substring(qValueIndex + 1);
+ language = language.substring(0, qValueIndex);
+ qValueStr = qValueStr.trim().toLowerCase();
+ qValueIndex = qValueStr.indexOf('=');
+ qValue = new Double(0);
+ if (qValueStr.startsWith("q") &&
+ qValueIndex > -1) {
+ qValueStr = qValueStr.substring(qValueIndex + 1);
+ try {
+ qValue = new Double(qValueStr.trim());
+ } catch (NumberFormatException nfe) {
+ }
+ }
+ }
+
+ // XXX
+ // may need to handle "*" at some point in time
+
+ if (! language.equals("*")) {
+ String key = qValue.toString();
+ Vector<String> v;
+ if (languages.containsKey(key)) {
+ v = languages.get(key) ;
+ } else {
+ v= new Vector<String>();
+ q.addElement(qValue);
+ }
+ v.addElement(language);
+ languages.put(key, v);
+ }
+ }
+ }
+
+ private static void extractLocales(Hashtable languages, Vector q,
+ Vector<Locale> l)
+ {
+ // XXX We will need to order by q value Vector in the Future ?
+ Enumeration e = q.elements();
+ while (e.hasMoreElements()) {
+ Vector v =
+ (Vector)languages.get(((Double)e.nextElement()).toString());
+ Enumeration le = v.elements();
+ while (le.hasMoreElements()) {
+ String language = (String)le.nextElement();
+ String country = "";
+ int countryIndex = language.indexOf("-");
+ if (countryIndex > -1) {
+ country = language.substring(countryIndex + 1).trim();
+ language = language.substring(0, countryIndex).trim();
+ }
+ l.addElement(new Locale(language, country));
+ }
+ }
+ }
+
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/NamespaceContextCallback.java b/utils/src/main/java/at/gv/egiz/slbinding/NamespaceContextCallback.java
new file mode 100644
index 00000000..08c075ac
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/NamespaceContextCallback.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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding;
+
+import javax.xml.namespace.NamespaceContext;
+
+/**
+ *
+ * @author clemens
+ */
+public interface NamespaceContextCallback {
+
+ /**
+ * preserves the current namespace context from the XMLEventFilter
+ * @param filter
+ */
+ void preserveNamespaceContext(RedirectEventFilter filter);
+
+ /**
+ * @return the namespace context if preserveNamespaceContext() was called on this object before, null otherwise
+ */
+ NamespaceContext getNamespaceContext();
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/RedirectCallback.java b/utils/src/main/java/at/gv/egiz/slbinding/RedirectCallback.java
new file mode 100644
index 00000000..80fb56dc
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/RedirectCallback.java
@@ -0,0 +1,42 @@
+/*
+* 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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding;
+
+import java.io.ByteArrayOutputStream;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ *
+ * The beforeUnmarshal(Unmarshaller um, Object parent) methods don't allow to pass the RedirectEventFilter,
+ * so we implement a callback interface common to all generated classes
+ * @author clemens
+ */
+public interface RedirectCallback {
+
+ void enableRedirect(RedirectEventFilter filter) throws XMLStreamException;
+
+ void disableRedirect(RedirectEventFilter filter) throws XMLStreamException;
+
+ /**
+ * @return the redirected stream or null if enableRedirect() was not called before
+ */
+ ByteArrayOutputStream getRedirectedStream();
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java b/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java
new file mode 100644
index 00000000..d2a7fb30
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java
@@ -0,0 +1,259 @@
+/*
+* 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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding;
+
+import java.io.OutputStream;
+import java.util.Set;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class RedirectEventFilter implements EventFilter {
+
+ public static final String DEFAULT_ENCODING = "UTF-8";
+ private static Log log = LogFactory.getLog(RedirectEventFilter.class);
+ protected XMLEventWriter redirectWriter = null;
+ protected Set<QName> redirectTriggers = null;
+ private int depth = -1;
+ protected NamespaceContext currentNamespaceContext = null;
+
+ /**
+ * Event redirection is disabled, set a redirect stream to enable.
+ */
+ public RedirectEventFilter() {
+ redirectWriter = null;
+ // redirectTriggers = null;
+ }
+
+ /**
+ *
+ * @param redirectStream
+ * if null, no events are redirected
+ * @param redirectTriggers
+ * if null, all events are redirected
+ */
+ public RedirectEventFilter(OutputStream redirectStream, String encoding)
+ throws XMLStreamException { // , List<QName> redirectTriggers
+ if (redirectStream != null) {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ if (encoding == null) {
+ encoding = DEFAULT_ENCODING;
+ }
+ this.redirectWriter = outputFactory.createXMLEventWriter(redirectStream,
+ encoding);
+ }
+ // this.redirectTriggers = redirectTriggers;
+ }
+
+ /**
+ * All startElement events occuring in the redirectTriggers list will trigger
+ * redirection of the entire (sub-)fragment.
+ *
+ * @param event
+ * @return false if an event is redirected
+ */
+ @Override
+ public boolean accept(XMLEvent event) {
+ int eventType = event.getEventType();
+
+ if (eventType == XMLStreamConstants.START_ELEMENT) {
+ currentNamespaceContext = event.asStartElement().getNamespaceContext();
+ }
+ if (redirectWriter == null) {
+ return true;
+ }
+ if (eventType == XMLStreamConstants.START_ELEMENT) {
+ if (depth >= 0 || triggersRedirect(event.asStartElement().getName())) {
+ depth++;
+ }
+ } else if (eventType == XMLStreamConstants.END_ELEMENT) {
+ if (depth >= 0 && --depth < 0) {
+ // redirect the end element of the trigger,
+ // but do not redirect the end element of the calling type
+ if (redirectTriggers != null) {
+ redirectEvent(event);
+ return false;
+ }
+ }
+ }
+ if (depth >= 0) { //|| (depth == 0 && redirectTriggers == null)) {
+ redirectEvent(event);
+ return false;
+ }
+ return true; // depth < 0;
+
+// switch (event.getEventType()) {
+// case XMLStreamConstants.START_ELEMENT:
+// StartElement startElt = event.asStartElement();
+// if (depth >= 0 || triggersRedirect(startElt.getName())) {
+// depth++;
+// }
+// // namespace context changes only on start elements
+// // (first event might not be startElement, but we don't need CDATA's
+// // namespace context)
+// currentNamespaceContext = startElt.getNamespaceContext();
+// break;
+// case XMLStreamConstants.END_ELEMENT:
+// // if depth switches from positive to negative, this is the closing tag of
+// // the trigger (redirect as well!)
+// if (depth >= 0 && --depth < 0) {
+// redirectEvent(event);
+// return false;
+// }
+// break;
+// }
+// if (depth >= 0) {
+// redirectEvent(event);
+// return false;
+// }
+// return true; // depth < 0;
+ }
+
+ /**
+ * @param startElt
+ * @return true if the set of triggers contains startElement
+ * (or no triggers are registered, i.e. everything is redirected)
+ */
+ private boolean triggersRedirect(QName startElement) {
+ if (redirectTriggers != null) {
+ return redirectTriggers.contains(startElement);
+ }
+ return true;
+ }
+
+ private void redirectEvent(XMLEvent event) {
+ try {
+ if (log.isTraceEnabled()) {
+ log.trace("redirecting StAX event " + event);
+ }
+ redirectWriter.add(event);
+ } catch (XMLStreamException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Enable/disable redirection of <em>all</em> events from now on.
+ * The redirected events will be UTF-8 encoded and written to the stream.
+ *
+ * @param redirectstream
+ * if null, redirection is disabled
+ */
+ public void setRedirectStream(OutputStream redirectStream) throws XMLStreamException {
+ setRedirectStream(redirectStream, DEFAULT_ENCODING, null);
+ }
+
+ /**
+ * Enable/disable redirection of <em>all</em> events from now on.
+ *
+ * @param redirectStream if null, redirection is disabled
+ * @param encoding The encoding for the redirect stream
+ * @throws javax.xml.stream.XMLStreamException
+ */
+ public void setRedirectStream(OutputStream redirectStream, String encoding) throws XMLStreamException {
+ setRedirectStream(redirectStream, encoding, null);
+ }
+
+ /**
+ * Enable/disable redirection of all (child) elements contained in redirect triggers.
+ * The redirected events will be UTF-8 encoded and written to the stream.
+ *
+ * @param redirectstream
+ * if null, redirection is disabled
+ * @param redirectTriggers elements that trigger the redirection
+ */
+ public void setRedirectStream(OutputStream redirectStream, Set<QName> redirectTriggers) throws XMLStreamException {
+ setRedirectStream(redirectStream, DEFAULT_ENCODING, redirectTriggers);
+ }
+
+ /**
+ * Enable/disable redirection of all (child) elements contained in redirect triggers.
+ *
+ * @param redirectstream
+ * if null, redirection is disabled
+ * @param encoding The encoding for the redirect stream
+ * @param redirectTriggers elements that trigger the redirection
+ */
+ public void setRedirectStream(OutputStream redirectStream, String encoding, Set<QName> redirectTriggers) throws XMLStreamException {
+ if (redirectStream != null) {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ if (encoding == null) {
+ encoding = DEFAULT_ENCODING;
+ }
+ redirectWriter = outputFactory.createXMLEventWriter(redirectStream,
+ encoding);
+ if (redirectTriggers == null) {
+ // start redirecting
+ depth = 0;
+ }
+ this.redirectTriggers = redirectTriggers;
+ } else {
+ redirectWriter = null;
+ this.redirectTriggers = null;
+ }
+ }
+
+ /**
+ * Enable/disable redirection of fragments (defined by elements in
+ * redirectTriggers)
+ *
+ * @param redirectStream
+ * if null, redirection is disabled
+ * @param redirectTriggers
+ * All startElement events occuring in this list will trigger
+ * redirection of the entire fragment. If null, all events are
+ * redirected
+ */
+ // public void setRedirectStream(OutputStream redirectStream, List<QName>
+ // redirectTriggers) throws XMLStreamException {
+ // if (redirectStream != null) {
+ // XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ // redirectWriter = outputFactory.createXMLEventWriter(redirectStream);
+ // } else {
+ // redirectWriter = null;
+ // }
+ // this.redirectTriggers = (redirectStream == null) ? null : redirectTriggers;
+ // }
+ /**
+ * flushes the internal EventWriter
+ *
+ * @throws javax.xml.stream.XMLStreamException
+ */
+ public void flushRedirectStream() throws XMLStreamException {
+ redirectWriter.flush();
+ }
+
+ /**
+ * the namespaceContext of the last startelement event read
+ *
+ * @return
+ */
+ public NamespaceContext getCurrentNamespaceContext() {
+ return currentNamespaceContext;
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/RedirectUnmarshallerListener.java b/utils/src/main/java/at/gv/egiz/slbinding/RedirectUnmarshallerListener.java
new file mode 100644
index 00000000..08c12146
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/RedirectUnmarshallerListener.java
@@ -0,0 +1,68 @@
+/*
+* 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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding;
+
+import javax.xml.bind.Unmarshaller;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Enables event redirection before marshalling a target of type RedirectCallback.
+ * It is up to the target class to implement the redirection (default implementation in RedirectCallback).
+ * Disables event redirection after marshalling (when the closing tag occurs).
+ * @author clemens
+ */
+public class RedirectUnmarshallerListener extends Unmarshaller.Listener {
+
+ private static Log log = LogFactory.getLog(RedirectUnmarshallerListener.class);
+ protected RedirectEventFilter eventFilter;
+
+ public RedirectUnmarshallerListener(RedirectEventFilter eventFilter) {
+ this.eventFilter = eventFilter;
+ }
+
+ @Override
+ public void beforeUnmarshal(Object target, Object parent) {
+ if (target instanceof RedirectCallback) {
+ try {
+ ((RedirectCallback) target).enableRedirect(eventFilter);
+ } catch (XMLStreamException ex) {
+ log.error("failed to enable event redirection for " + target.getClass().getName() + ": " + ex.getMessage(), ex);
+ }
+ }
+ if (target instanceof NamespaceContextCallback) {
+ ((NamespaceContextCallback) target).preserveNamespaceContext(eventFilter);
+ }
+ }
+
+ @Override
+ public void afterUnmarshal(Object target, Object parent) {
+ if (target instanceof RedirectCallback) {
+ try {
+ ((RedirectCallback) target).disableRedirect(eventFilter);
+ } catch (XMLStreamException ex) {
+ log.error("failed to disable event redirection for " + target.getClass().getName() + ": " + ex.getMessage(), ex);
+ }
+ }
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/SignatureLocationType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/SignatureLocationType.java
new file mode 100644
index 00000000..494e6972
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/SignatureLocationType.java
@@ -0,0 +1,50 @@
+/*
+* 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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding.impl;
+
+import at.gv.egiz.slbinding.*;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.namespace.NamespaceContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author clemens
+ */
+public class SignatureLocationType extends at.buergerkarte.namespaces.securitylayer._1.SignatureLocationType implements NamespaceContextCallback {
+
+ @XmlTransient
+ private static Log log = LogFactory.getLog(SignatureLocationType.class);
+ @XmlTransient
+ protected NamespaceContext namespaceContext;
+
+ @Override
+ public NamespaceContext getNamespaceContext() {
+ return namespaceContext;
+ }
+
+ @Override
+ public void preserveNamespaceContext(RedirectEventFilter filter) {
+ log.debug("preserving namespace context for SignatureLocationType");
+ namespaceContext = filter.getCurrentNamespaceContext();
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java
new file mode 100644
index 00000000..b4e988f0
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java
@@ -0,0 +1,70 @@
+/*
+* 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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding.impl;
+
+import at.gv.egiz.slbinding.*;
+import java.io.ByteArrayOutputStream;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author clemens
+ */
+public class TransformsInfoType extends at.buergerkarte.namespaces.securitylayer._1.TransformsInfoType implements RedirectCallback {
+
+ @XmlTransient
+ private static Log log = LogFactory.getLog(TransformsInfoType.class);
+ @XmlTransient
+ private static final Set<QName> redirectTriggers = initRedirectTriggers();
+ @XmlTransient
+ protected ByteArrayOutputStream redirectOS = null;
+
+ private static Set<QName> initRedirectTriggers() {
+ HashSet<QName> dsigTransforms = new HashSet<QName>();
+ dsigTransforms.add(new QName("http://www.w3.org/2000/09/xmldsig#", "Transforms"));
+ return dsigTransforms;
+ }
+
+ @Override
+ public void enableRedirect(RedirectEventFilter filter) throws XMLStreamException {
+ log.debug("enabling event redirection for TransformsInfoType");
+ redirectOS = new ByteArrayOutputStream();
+ filter.setRedirectStream(redirectOS, redirectTriggers);
+ }
+
+ @Override
+ public void disableRedirect(RedirectEventFilter filter) throws XMLStreamException {
+ log.debug("disabling event redirection for TransformsInfoType");
+ filter.flushRedirectStream();
+ filter.setRedirectStream(null);
+ }
+
+ @Override
+ public ByteArrayOutputStream getRedirectedStream() {
+ return redirectOS;
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java
new file mode 100644
index 00000000..c32542aa
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java
@@ -0,0 +1,60 @@
+/*
+* 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.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.slbinding.impl;
+
+import at.gv.egiz.slbinding.RedirectCallback;
+import at.gv.egiz.slbinding.RedirectEventFilter;
+import java.io.ByteArrayOutputStream;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.stream.XMLStreamException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author clemens
+ */
+public class XMLContentType extends at.buergerkarte.namespaces.securitylayer._1.XMLContentType implements RedirectCallback {
+
+ @XmlTransient
+ private static Log log = LogFactory.getLog(TransformsInfoType.class);
+ @XmlTransient
+ protected ByteArrayOutputStream redirectOS = null;
+
+ @Override
+ public void enableRedirect(RedirectEventFilter filter) throws XMLStreamException {
+ log.debug("enabling event redirection for XMLContentType");
+ redirectOS = new ByteArrayOutputStream();
+ filter.setRedirectStream(redirectOS);
+ }
+
+ @Override
+ public void disableRedirect(RedirectEventFilter filter) throws XMLStreamException {
+ log.debug("disabling event redirection for XMLContentType");
+ filter.flushRedirectStream();
+ filter.setRedirectStream(null);
+ }
+
+ @Override
+ public ByteArrayOutputStream getRedirectedStream() {
+ return redirectOS;
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesException.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesException.java
new file mode 100644
index 00000000..e892a13b
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesException.java
@@ -0,0 +1,40 @@
+/*
+* 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.xades;
+
+public class QualifyingPropertiesException extends Exception {
+
+ public QualifyingPropertiesException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public QualifyingPropertiesException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public QualifyingPropertiesException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public QualifyingPropertiesException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
new file mode 100644
index 00000000..ae159215
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
@@ -0,0 +1,225 @@
+/*
+* 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.xades;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.etsi.uri._01903.v1_1.CertIDListType;
+import org.etsi.uri._01903.v1_1.CertIDType;
+import org.etsi.uri._01903.v1_1.DataObjectFormatType;
+import org.etsi.uri._01903.v1_1.DigestAlgAndValueType;
+import org.etsi.uri._01903.v1_1.QualifyingPropertiesType;
+import org.etsi.uri._01903.v1_1.SignaturePolicyIdentifierType;
+import org.etsi.uri._01903.v1_1.SignedDataObjectPropertiesType;
+import org.etsi.uri._01903.v1_1.SignedPropertiesType;
+import org.etsi.uri._01903.v1_1.SignedSignaturePropertiesType;
+import org.w3._2000._09.xmldsig_.DigestMethodType;
+import org.w3._2000._09.xmldsig_.X509IssuerSerialType;
+import org.w3c.dom.Node;
+
+public class QualifyingPropertiesFactory {
+
+ public static String NS_URI_V1_1_1 = "http://uri.etsi.org/01903/v1.1.1#";
+
+ public static String SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1 = NS_URI_V1_1_1 + "SignedProperties";
+
+ private static QualifyingPropertiesFactory instance;
+
+ /**
+ * The <code>JAXBContext</code>.
+ */
+ private static JAXBContext jaxbContext;
+
+ public static synchronized QualifyingPropertiesFactory getInstance() {
+ if (instance == null) {
+ instance = new QualifyingPropertiesFactory();
+ }
+ return instance;
+ }
+
+ private DatatypeFactory datatypeFactory;
+
+ private org.etsi.uri._01903.v1_1.ObjectFactory qpFactory;
+
+ private org.w3._2000._09.xmldsig_.ObjectFactory dsFactory;
+
+ public QualifyingPropertiesFactory() {
+
+ try {
+ datatypeFactory = DatatypeFactory.newInstance();
+ } catch (DatatypeConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+
+ qpFactory = new org.etsi.uri._01903.v1_1.ObjectFactory();
+
+ dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
+
+ StringBuffer packageNames = new StringBuffer();
+
+ packageNames.append(org.etsi.uri._01903.v1_1.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
+
+ try {
+ jaxbContext = JAXBContext.newInstance(packageNames.toString());
+ } catch (JAXBException e) {
+ // we should not get an JAXBException initializing the JAXBContext
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate) throws QualifyingPropertiesException {
+
+ DigestMethodType digestMethodType = dsFactory.createDigestMethodType();
+ digestMethodType.setAlgorithm(DigestMethod.SHA1);
+
+ byte[] digest;
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+ digest = messageDigest.digest(certificate.getEncoded());
+ } catch (CertificateEncodingException e) {
+ throw new QualifyingPropertiesException(e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new QualifyingPropertiesException(e);
+ }
+
+ DigestAlgAndValueType digestAlgAndValueType = qpFactory.createDigestAlgAndValueType();
+ digestAlgAndValueType.setDigestMethod(digestMethodType);
+ digestAlgAndValueType.setDigestValue(digest);
+
+ return digestAlgAndValueType;
+
+ }
+
+ public X509IssuerSerialType createX509IssuerSerialType(X509Certificate certificate) {
+
+ String name = certificate.getIssuerX500Principal().getName("RFC2253");
+ BigInteger serialNumber = certificate.getSerialNumber();
+
+ X509IssuerSerialType issuerSerialType = dsFactory.createX509IssuerSerialType();
+ issuerSerialType.setX509IssuerName(name);
+ issuerSerialType.setX509SerialNumber(serialNumber);
+
+ return issuerSerialType;
+
+ }
+
+ public DataObjectFormatType createDataObjectFormatType(String objectReference, String mimeType, String description) {
+
+ DataObjectFormatType dataObjectFormatType = qpFactory.createDataObjectFormatType();
+ dataObjectFormatType.setObjectReference(objectReference);
+
+ if (mimeType != null) {
+ dataObjectFormatType.setMimeType(mimeType);
+ }
+ if (description != null) {
+ dataObjectFormatType.setDescription(description);
+ }
+
+ return dataObjectFormatType;
+ }
+
+ public JAXBElement<QualifyingPropertiesType> createQualifyingProperties111(Date signingTime, List<X509Certificate> certificates, String idValue, List<DataObjectFormatType> dataObjectFormats) throws QualifyingPropertiesException {
+
+ GregorianCalendar gregorianCalendar = new GregorianCalendar();
+ gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
+ gregorianCalendar.setTime(signingTime);
+
+ SignedSignaturePropertiesType signedSignaturePropertiesType = qpFactory.createSignedSignaturePropertiesType();
+
+ // SigningTime
+ XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(gregorianCalendar);
+ xmlGregorianCalendar.setFractionalSecond(null);
+ signedSignaturePropertiesType.setSigningTime(xmlGregorianCalendar);
+
+ // SigningCertificate
+ CertIDListType certIDListType = qpFactory.createCertIDListType();
+ List<CertIDType> certIDs = certIDListType.getCert();
+
+ for (X509Certificate certificate : certificates) {
+
+ CertIDType certIDType = qpFactory.createCertIDType();
+ certIDType.setCertDigest(createDigestAlgAndValueType(certificate));
+ certIDType.setIssuerSerial(createX509IssuerSerialType(certificate));
+
+ certIDs.add(certIDType);
+
+ }
+ signedSignaturePropertiesType.setSigningCertificate(certIDListType);
+
+ // SignaturePolicy
+ SignaturePolicyIdentifierType signaturePolicyIdentifierType = qpFactory.createSignaturePolicyIdentifierType();
+ signaturePolicyIdentifierType.setSignaturePolicyImplied(new SignaturePolicyIdentifierType.SignaturePolicyImplied());
+ signedSignaturePropertiesType.setSignaturePolicyIdentifier(signaturePolicyIdentifierType);
+
+ // SignedProperties
+ SignedPropertiesType signedPropertiesType = qpFactory.createSignedPropertiesType();
+ signedPropertiesType.setSignedSignatureProperties(signedSignaturePropertiesType);
+
+ // DataObjectFormat
+ if (dataObjectFormats != null && !dataObjectFormats.isEmpty()) {
+ SignedDataObjectPropertiesType signedDataObjectPropertiesType = qpFactory.createSignedDataObjectPropertiesType();
+ List<DataObjectFormatType> dataObjectFormatTypes = signedDataObjectPropertiesType.getDataObjectFormat();
+ dataObjectFormatTypes.addAll(dataObjectFormats);
+ signedPropertiesType.setSignedDataObjectProperties(signedDataObjectPropertiesType);
+ }
+
+ signedPropertiesType.setId(idValue);
+
+ // QualifyingProperties
+ QualifyingPropertiesType qualifyingPropertiesType = qpFactory.createQualifyingPropertiesType();
+ qualifyingPropertiesType.setSignedProperties(signedPropertiesType);
+
+ return qpFactory.createQualifyingProperties(qualifyingPropertiesType);
+
+ }
+
+ public void marshallQualifyingProperties(JAXBElement<QualifyingPropertiesType> qualifyingProperties, Node parent) throws JAXBException {
+
+ try {
+ Marshaller marshaller = jaxbContext.createMarshaller();
+
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+ marshaller.marshal(qualifyingProperties, parent);
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/xmldsig/KeyTypeNotSupportedException.java b/utils/src/main/java/at/gv/egiz/xmldsig/KeyTypeNotSupportedException.java
new file mode 100644
index 00000000..3afa6d51
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/xmldsig/KeyTypeNotSupportedException.java
@@ -0,0 +1,65 @@
+/*
+* 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.xmldsig;
+
+/**
+ * @author mcentner
+ *
+ */
+public class KeyTypeNotSupportedException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ *
+ */
+ public KeyTypeNotSupportedException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * @param message
+ */
+ public KeyTypeNotSupportedException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * @param cause
+ */
+ public KeyTypeNotSupportedException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public KeyTypeNotSupportedException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/xmldsig/KeyValueFactory.java b/utils/src/main/java/at/gv/egiz/xmldsig/KeyValueFactory.java
new file mode 100644
index 00000000..c1772312
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/xmldsig/KeyValueFactory.java
@@ -0,0 +1,279 @@
+/*
+* 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.xmldsig;
+
+import iaik.security.ecc.interfaces.ECDSAParams;
+import iaik.security.ecc.interfaces.ECDSAPublicKey;
+import iaik.security.ecc.math.ecgroup.Coordinate;
+import iaik.security.ecc.math.ecgroup.ECPoint;
+import iaik.security.ecc.math.ecgroup.EllipticCurve;
+import iaik.security.ecc.math.field.BinaryField;
+import iaik.security.ecc.math.field.Field;
+import iaik.security.ecc.math.field.FieldElement;
+import iaik.security.ecc.math.field.PrimeField;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.PublicKey;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+import javax.xml.bind.JAXBElement;
+
+import org.w3._2000._09.xmldsig_.DSAKeyValueType;
+import org.w3._2000._09.xmldsig_.RSAKeyValueType;
+import org.w3._2001._04.xmldsig_more_.BasePointParamsType;
+import org.w3._2001._04.xmldsig_more_.CharTwoFieldElemType;
+import org.w3._2001._04.xmldsig_more_.CurveParamsType;
+import org.w3._2001._04.xmldsig_more_.DomainParamsType;
+import org.w3._2001._04.xmldsig_more_.ECDSAKeyValueType;
+import org.w3._2001._04.xmldsig_more_.ECPointType;
+import org.w3._2001._04.xmldsig_more_.ExplicitParamsType;
+import org.w3._2001._04.xmldsig_more_.FieldElemType;
+import org.w3._2001._04.xmldsig_more_.FieldParamsType;
+import org.w3._2001._04.xmldsig_more_.PnBFieldParamsType;
+import org.w3._2001._04.xmldsig_more_.PrimeFieldElemType;
+import org.w3._2001._04.xmldsig_more_.PrimeFieldParamsType;
+import org.w3._2001._04.xmldsig_more_.TnBFieldParamsType;
+import org.w3._2001._04.xmldsig_more_.DomainParamsType.NamedCurve;
+
+public class KeyValueFactory {
+
+ private static byte[] bigInteger2byteArray(BigInteger bigPositiveInt) {
+ if (bigPositiveInt == null)
+ throw new NullPointerException("Argument 'bigPositiveInt' must not be null");
+ if (bigPositiveInt.signum() != 1)
+ throw new IllegalArgumentException("Argument 'bigPositiveInt' must not be negative");
+
+ byte[] byteRepresentation = bigPositiveInt.toByteArray();
+ if (byteRepresentation[0] == 0) {
+ byte[] oldByteRepresentation = byteRepresentation;
+ byteRepresentation = new byte[oldByteRepresentation.length - 1];
+ System.arraycopy(oldByteRepresentation, 1, byteRepresentation, 0, oldByteRepresentation.length - 1);
+ }
+ return byteRepresentation;
+ }
+
+ org.w3._2001._04.xmldsig_more_.ObjectFactory ecFactory = new org.w3._2001._04.xmldsig_more_.ObjectFactory();
+
+ org.w3._2000._09.xmldsig_.ObjectFactory dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
+
+ public JAXBElement<?> createKeyValue(PublicKey publicKey) throws KeyTypeNotSupportedException {
+
+ if (publicKey instanceof RSAPublicKey) {
+ RSAKeyValueType keyValueType = createRSAKeyValueType((RSAPublicKey) publicKey);
+ return dsFactory.createRSAKeyValue(keyValueType);
+ } else if (publicKey instanceof DSAPublicKey) {
+ DSAKeyValueType keyValueType = createKeyValueType((DSAPublicKey) publicKey);
+ return dsFactory.createDSAKeyValue(keyValueType);
+ } else if (publicKey instanceof ECDSAPublicKey) {
+ ECDSAKeyValueType keyValueType = createKeyValueType((ECDSAPublicKey) publicKey);
+ return ecFactory.createECDSAKeyValue(keyValueType);
+ } else if ("EC".equals(publicKey.getAlgorithm())) {
+ byte[] encoded = publicKey.getEncoded();
+ try {
+ iaik.security.ecc.ecdsa.ECPublicKey key = new iaik.security.ecc.ecdsa.ECPublicKey(encoded);
+ ECDSAKeyValueType keyValueType = createKeyValueType(key);
+ return ecFactory.createECDSAKeyValue(keyValueType);
+ } catch (InvalidKeyException e) {
+ throw new KeyTypeNotSupportedException("Public key of type "
+ + publicKey.getAlgorithm() + " (" + publicKey.getClass()
+ + ") not supported.");
+ }
+ } else {
+ throw new KeyTypeNotSupportedException("Public key of type "
+ + publicKey.getAlgorithm() + " (" + publicKey.getClass()
+ + ") not supported.");
+ }
+
+ }
+
+ public RSAKeyValueType createRSAKeyValueType(RSAPublicKey publicKey) {
+
+ RSAKeyValueType keyValueType = dsFactory.createRSAKeyValueType();
+ keyValueType.setExponent(bigInteger2byteArray(publicKey.getPublicExponent()));
+ keyValueType.setModulus(bigInteger2byteArray(publicKey.getModulus()));
+
+ return keyValueType;
+ }
+
+ public DSAKeyValueType createKeyValueType(DSAPublicKey publicKey) {
+
+ DSAKeyValueType keyValueType = dsFactory.createDSAKeyValueType();
+
+ if (publicKey.getParams() != null) {
+ // P, Q, G
+ DSAParams params = publicKey.getParams();
+ if (params.getP() != null && params.getQ() != null) {
+ keyValueType.setP(bigInteger2byteArray(params.getP()));
+ keyValueType.setQ(bigInteger2byteArray(params.getQ()));
+ }
+ if (params.getG() != null) {
+ keyValueType.setG(bigInteger2byteArray(params.getG()));
+ }
+ }
+ //
+ keyValueType.setY(bigInteger2byteArray(publicKey.getY()));
+
+ return keyValueType;
+ }
+
+ public ECDSAKeyValueType createKeyValueType(ECDSAPublicKey publicKey) throws KeyTypeNotSupportedException {
+
+ ECDSAKeyValueType keyValueType = ecFactory.createECDSAKeyValueType();
+
+ ECDSAParams params = publicKey.getParameter();
+ if (params != null) {
+ keyValueType.setDomainParameters(createDomainParamsType(params));
+ }
+
+ if (!publicKey.getW().isInfinity()) {
+ keyValueType.setPublicKey(createPointType(publicKey.getW()));
+ }
+
+ return keyValueType;
+ }
+
+ public ECPointType createPointType(ECPoint point) throws KeyTypeNotSupportedException {
+ ECPointType pointType = ecFactory.createECPointType();
+ Coordinate affine = point.getCoordinates().toAffine();
+ pointType.setX(createFieldElemType(affine.getX()));
+ pointType.setY(createFieldElemType(affine.getY()));
+ return pointType;
+ }
+
+ public FieldElemType createFieldElemType(FieldElement fieldElement) throws KeyTypeNotSupportedException {
+ int fieldId = fieldElement.getField().getFieldId();
+ if (fieldId == PrimeField.PRIME_FIELD_ID) {
+ PrimeFieldElemType fieldElemType = ecFactory.createPrimeFieldElemType();
+ fieldElemType.setValue(fieldElement.toBigInt());
+ return fieldElemType;
+ } else if (fieldId == BinaryField.BINARY_FIELD_ID) {
+ CharTwoFieldElemType fieldElemType = ecFactory.createCharTwoFieldElemType();
+ fieldElemType.setValue(fieldElement.toByteArray());
+ return fieldElemType;
+ } else {
+ throw new KeyTypeNotSupportedException("Field element of type " + fieldId + " not supported.");
+ }
+ }
+
+ public FieldParamsType createFieldParamsType(Field field) throws KeyTypeNotSupportedException {
+
+ if (field.getFieldId() == PrimeField.PRIME_FIELD_ID) {
+ // PrimeFieldParamsType
+ PrimeFieldParamsType primeFieldParamsType = ecFactory.createPrimeFieldParamsType();
+ primeFieldParamsType.setP(field.getSize());
+ return primeFieldParamsType;
+ } else if (field.getFieldId() == BinaryField.BINARY_FIELD_ID && field instanceof BinaryField) {
+ // CharTwoFieldParamsType
+
+ BinaryField binaryField = (BinaryField) field;
+ int[] irreduciblePolynomial = binaryField.getIrreduciblePolynomial();
+
+ // The irreducible polynomial as a BinaryFieldValue
+ FieldElement irreducible = binaryField.newElement(irreduciblePolynomial);
+
+ int order = binaryField.getOrder();
+ int[] coeffPositions = new int[3];
+
+ // Get coefficients of irreducible polynomial
+ int coeffCount = 2;
+ for (int i = 1; i < order -1; i++) {
+ if (irreducible.testBit(i)) {
+ coeffPositions[coeffCount - 2] = i;
+ coeffCount++;
+ if (coeffCount == 5)
+ break;
+ }
+ }
+ // detect if trinomial or pentanomial base is present...
+ switch (coeffCount) {
+ case 3:
+ // trinomial base
+ TnBFieldParamsType tnBFieldParamsType = ecFactory.createTnBFieldParamsType();
+ tnBFieldParamsType.setM(BigInteger.valueOf(binaryField.getOrder()));
+ tnBFieldParamsType.setK(BigInteger.valueOf(coeffPositions[0]));
+ return tnBFieldParamsType;
+
+ case 5:
+ // pentanomial base
+ PnBFieldParamsType pnBFieldParamsType = ecFactory.createPnBFieldParamsType();
+ pnBFieldParamsType.setM(BigInteger.valueOf(binaryField.getOrder()));
+ pnBFieldParamsType.setK1(BigInteger.valueOf(coeffPositions[0]));
+ pnBFieldParamsType.setK2(BigInteger.valueOf(coeffPositions[1]));
+ pnBFieldParamsType.setK3(BigInteger.valueOf(coeffPositions[2]));
+ return pnBFieldParamsType;
+
+ default:
+ throw new KeyTypeNotSupportedException("Only trinomial and pentanomial base is supported.");
+ }
+
+ } else {
+ throw new KeyTypeNotSupportedException("Field element of type " + field.getFieldId() + " not supported.");
+ }
+
+ }
+
+ public DomainParamsType createDomainParamsType(ECDSAParams params) throws KeyTypeNotSupportedException {
+
+ DomainParamsType domainParamsType = ecFactory.createDomainParamsType();
+ EllipticCurve curve = params.getG().getCurve();
+
+ String oid = params.getOID();
+ if (oid != null) {
+ // NamedCurve
+ NamedCurve namedCurve = ecFactory.createDomainParamsTypeNamedCurve();
+ namedCurve.setURN("urn:oid:" + oid);
+ domainParamsType.setNamedCurve(namedCurve);
+ } else {
+ // Explicit parameters
+ ExplicitParamsType explicitParamsType = ecFactory.createExplicitParamsType();
+ explicitParamsType.setFieldParams(createFieldParamsType(curve.getField()));
+
+ CurveParamsType curveParamsType = ecFactory.createCurveParamsType();
+
+ // curve coefficients
+ curveParamsType.setA(createFieldElemType(curve.getA()));
+ curveParamsType.setB(createFieldElemType(curve.getB()));
+
+ // seed
+ if (params.getS() != null) {
+ curveParamsType.setSeed(bigInteger2byteArray(params.getS()));
+ }
+ explicitParamsType.setCurveParams(curveParamsType);
+
+
+ // BasePoint parameters
+ BasePointParamsType basePointParamsType = ecFactory.createBasePointParamsType();
+ if (!params.getG().isInfinity()) {
+ basePointParamsType.setBasePoint(createPointType(params.getG()));
+ }
+ basePointParamsType.setOrder(params.getR());
+ if(params.getK() != null) {
+ basePointParamsType.setCofactor(params.getK());
+ }
+ explicitParamsType.setBasePointParams(basePointParamsType);
+
+ domainParamsType.setExplicitParams(explicitParamsType);
+ }
+
+ return domainParamsType;
+
+ }
+
+}