From 3aadcf8f877a560bed75af7e0db918aa26ef2a03 Mon Sep 17 00:00:00 2001 From: mcentner Date: Thu, 4 Dec 2008 10:00:31 +0000 Subject: Refactoring of infobox implementation. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@232 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/webapp/WEB-INF/applicationContext.xml | 34 ++ .../src/main/webapp/WEB-INF/applicationContext.xml | 17 + .../main/java/at/gv/egiz/bku/binding/DataUrl.java | 1 + .../bku/binding/LegacyDataUrlConnectionImpl.java | 230 +++++++++ .../java/at/gv/egiz/bku/conf/Configurator.java | 41 +- .../egiz/bku/slcommands/InfoboxUpdateCommand.java | 23 + .../egiz/bku/slcommands/InfoboxUpdateResult.java | 21 + .../slcommands/impl/AbstractAssocArrayInfobox.java | 284 ++++++++++ .../slcommands/impl/AbstractBinaryFileInfobox.java | 68 +++ .../impl/AbstractInfoboxCommandImpl.java | 55 ++ .../bku/slcommands/impl/AbstractInfoboxImpl.java | 26 + .../bku/slcommands/impl/AssocArrayInfobox.java | 27 + .../bku/slcommands/impl/BinaryFileInfobox.java | 27 + .../slcommands/impl/CertificatesInfoboxImpl.java | 112 ++++ .../impl/CreateXMLSignatureCommandImpl.java | 37 +- .../slcommands/impl/IdentityLinkInfoboxImpl.java | 291 +++++++++++ .../at/gv/egiz/bku/slcommands/impl/Infobox.java | 53 ++ .../egiz/bku/slcommands/impl/InfoboxFactory.java | 151 ++++++ .../slcommands/impl/InfoboxReadCommandImpl.java | 569 ++------------------- .../bku/slcommands/impl/InfoboxReadResultImpl.java | 3 +- .../slcommands/impl/InfoboxUpdateCommandImpl.java | 158 ++++++ .../slcommands/impl/InfoboxUpdateResultImpl.java | 43 ++ .../gv/egiz/bku/slcommands/impl/SLCommandImpl.java | 107 +--- .../at/gv/egiz/bku/slcommands/impl/STALHelper.java | 218 ++++++++ .../egiz/bku/slcommands/testApplicationContext.xml | 36 -- .../egiz/bku/slcommands/testApplicationContext.xml | 53 ++ 26 files changed, 1968 insertions(+), 717 deletions(-) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java delete mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml create mode 100644 bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml diff --git a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml index 1d09aa7e..5ac12ece 100644 --- a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml @@ -48,6 +48,40 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml index 9c7194dd..321e1e98 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml @@ -45,6 +45,23 @@ + + + + + + + + + + + + diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java index d462ac60..531772cf 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java @@ -65,5 +65,6 @@ public class DataUrl { public static void setConfiguration(Properties props) { configuration = props; + defaultDataUrlConnection.setConfiguration(configuration); } } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java new file mode 100644 index 00000000..5339d689 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java @@ -0,0 +1,230 @@ +package at.gv.egiz.bku.binding; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLEncoder; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.net.ssl.HttpsURLConnection; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLResult.SLResultType; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.binding.Protocol; + +/** + * not thread-safe thus newInsance always returns a new object + * + */ +public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { + + private final static Log log = LogFactory.getLog(DataUrlConnectionImpl.class); + + public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, + Protocol.HTTPS }; + protected X509Certificate serverCertificate; + protected Protocol protocol; + protected URL url; + private HttpURLConnection connection; + protected Map requestHttpHeaders; + protected Map formParams; + protected String boundary; + protected Properties config = null; + + protected DataUrlResponse result; + + public String getProtocol() { + if (protocol == null) { + return null; + } + return protocol.toString(); + } + + /** + * opens a connection sets the headers gets the server certificate + * + * @throws java.net.SocketTimeoutException + * @throws java.io.IOException + * @pre url != null + * @pre httpHeaders != null + */ + public void connect() throws SocketTimeoutException, IOException { + connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + Set headers = requestHttpHeaders.keySet(); + Iterator headerIt = headers.iterator(); + while (headerIt.hasNext()) { + String name = headerIt.next(); + connection.setRequestProperty(name, requestHttpHeaders.get(name)); + } + log.trace("Connecting to: "+url); + connection.connect(); + if (connection instanceof HttpsURLConnection) { + HttpsURLConnection ssl = (HttpsURLConnection) connection; + X509Certificate[] certs = (X509Certificate[]) ssl.getServerCertificates(); + if ((certs != null) && (certs.length >= 1)) { + log.trace("Server certificate: "+certs[0]); + serverCertificate = certs[0]; + } + } + } + + public X509Certificate getServerCertificate() { + return serverCertificate; + } + + public void setHTTPHeader(String name, String value) { + if (name != null && value != null) { + requestHttpHeaders.put(name, value); + } + } + + public void setHTTPFormParameter(String name, InputStream data, + String contentType, String charSet, String transferEncoding) { + StringBuilder sb = new StringBuilder(); + try { + InputStreamReader reader = new InputStreamReader(data, (charSet != null) ? charSet : "UTF-8"); + char[] c = new char[512]; + for (int l; (l = reader.read(c)) != -1;) { + sb.append(c, 0, l); + } + } catch (IOException e) { + throw new SLRuntimeException("Failed to set HTTP form parameter.", e); + } + formParams.put(name, sb.toString()); + } + + /** + * send all formParameters + * + * @throws java.io.IOException + */ + public void transmit(SLResult slResult) throws IOException { + StringWriter writer = new StringWriter(); + slResult.writeTo(new StreamResult(writer)); + formParams.put( + (slResult.getResultType() == SLResultType.XML) + ? DataUrlConnection.FORMPARAM_XMLRESPONSE + : DataUrlConnection.FORMPARAM_BINARYRESPONSE, + writer.toString()); + + OutputStream os = connection.getOutputStream(); + OutputStreamWriter streamWriter = new OutputStreamWriter(os, HttpUtil.DEFAULT_CHARSET); + + log.trace("Sending data"); + Iterator keys = formParams.keySet().iterator(); + while(keys.hasNext()) { + String key = keys.next(); + streamWriter.write(URLEncoder.encode(key, "UTF-8")); + streamWriter.write("="); + streamWriter.write(URLEncoder.encode(formParams.get(key), "UTF-8")); + if (keys.hasNext()) { + streamWriter.write("&"); + } + } + streamWriter.flush(); + os.close(); + + // MultipartRequestEntity PostMethod + InputStream is = null; + try { + is = connection.getInputStream(); + } catch (IOException iox) { + log.info(iox); + } + log.trace("Reading response"); + result = new DataUrlResponse(url.toString(), connection.getResponseCode(), is); + Map responseHttpHeaders = new HashMap(); + Map> httpHeaders = connection.getHeaderFields(); + for (Iterator keyIt = httpHeaders.keySet().iterator(); keyIt + .hasNext();) { + String key = keyIt.next(); + StringBuffer value = new StringBuffer(); + for (String val : httpHeaders.get(key)) { + value.append(val); + value.append(HttpUtil.SEPERATOR[0]); + } + String valString = value.substring(0, value.length() - 1); + if ((key != null) && (value.length() > 0)) { + responseHttpHeaders.put(key, valString); + } + } + result.setResponseHttpHeaders(responseHttpHeaders); + } + + @Override + public DataUrlResponse getResponse() throws IOException { + return result; + } + + /** + * inits protocol, url, httpHeaders, formParams + * + * @param url + * must not be null + */ + @Override + public void init(URL url) { + + for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) { + if (SUPPORTED_PROTOCOLS[i].toString().equalsIgnoreCase(url.getProtocol())) { + protocol = SUPPORTED_PROTOCOLS[i]; + break; + } + } + if (protocol == null) { + throw new SLRuntimeException("Protocol " + url.getProtocol() + + " not supported for data url"); + } + this.url = url; + requestHttpHeaders = new HashMap(); + if ((config != null) + && (config.getProperty(USER_AGENT_PROPERTY_KEY) != null)) { + requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config + .getProperty(USER_AGENT_PROPERTY_KEY)); + } else { + requestHttpHeaders + .put(HttpUtil.HTTP_HEADER_USER_AGENT, DEFAULT_USERAGENT); + + } + requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, + HttpUtil.APPLICATION_URL_ENCODED); + + formParams = new HashMap(); + } + + @Override + public DataUrlConnectionSPI newInstance() { + DataUrlConnectionSPI uc = new LegacyDataUrlConnectionImpl(); + uc.setConfiguration(config); + return uc; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void setConfiguration(Properties config) { + this.config = config; + } +} \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java index 9ed99190..6078de36 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java @@ -187,28 +187,29 @@ public abstract class Configurator { } public void configureVersion() { - Properties p = new Properties(); - try { - InputStream is = getManifest(); - if (is != null) { - p.load(getManifest()); - String version = p.getProperty("Implementation-Build"); - properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, - "citizen-card-environment/1.2 MOCCA " + version); - DataUrl.setConfiguration(properties); - log - .debug("Setting user agent to: " - + properties - .getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY)); - } else { - log.warn("Cannot read manifest"); - properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, - "citizen-card-environment/1.2 MOCCA UNKNOWN"); - DataUrl.setConfiguration(properties); + if (properties.getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY) == null) { + Properties p = new Properties(); + try { + InputStream is = getManifest(); + if (is != null) { + p.load(getManifest()); + String version = p.getProperty("Implementation-Build"); + properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, + "citizen-card-environment/1.2 MOCCA " + version); + log + .debug("Setting user agent to: " + + properties + .getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY)); + } else { + log.warn("Cannot read manifest"); + properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, + "citizen-card-environment/1.2 MOCCA UNKNOWN"); + } + } catch (IOException e) { + log.error(e); } - } catch (IOException e) { - log.error(e); } + DataUrl.setConfiguration(properties); } public void configure() { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java new file mode 100644 index 00000000..c2974785 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.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.slcommands; + +public interface InfoboxUpdateCommand extends SLCommand { + + public String getInfoboxIdentifier(); + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java new file mode 100644 index 00000000..d180facf --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java @@ -0,0 +1,21 @@ +/* +* 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.slcommands; + +public interface InfoboxUpdateResult extends SLResult { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java new file mode 100644 index 00000000..e49ed6c0 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java @@ -0,0 +1,284 @@ +/* + * 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.slcommands.impl; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxAssocArrayPairType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadDataAssocArrayType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.buergerkarte.namespaces.securitylayer._1.XMLContentType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadKeys; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadPairs; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +/** + * An abstract base class for {@link Infobox} implementations of type associative array. + * + * @author mcentner + */ +public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl + implements AssocArrayInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(AbstractAssocArrayInfobox.class); + + /** + * The search string pattern. + */ + public static final String SEARCH_STRING_PATTERN = ".&&[^/](/.&&[^/])*"; + + /** + * @return the keys available in this infobox. + */ + public abstract String[] getKeys(); + + /** + * @return true if the values are XML entities, or false otherwise. + */ + public abstract boolean isValuesAreXMLEntities(); + + /** + * Returns a key to value mapping for the given keys. + * + * @param keys a list of keys + * @param cmdCtx the command context + * + * @return a key to value mapping for the given keys. + * + * @throws SLCommandException if obtaining the values fails + */ + public abstract Map getValues(List keys, SLCommandContext cmdCtx) throws SLCommandException; + + /** + * Returns all keys that match the given searchString. + * + * @param searchString the search string + * + * @return all keys that match the given searchString + * + * @throws SLCommandException if the given search string is invalid + */ + protected List selectKeys(String searchString) throws SLCommandException { + + if ("*".equals(searchString) || "**".equals(searchString)) { + return Arrays.asList(getKeys()); + } + + if (Pattern.matches(SEARCH_STRING_PATTERN, searchString)) { + +// for (int i = 0; i < searchString.length(); i++) { +// int codePoint = searchString.codePointAt(i); +// +// } + + // TODO : build pattern + return Collections.emptyList(); + } else { + log.info("Got invalid search string '" + searchString + "'"); + throw new SLCommandException(4010); + } + + } + + /** + * Read all keys specified by readKeys. + * + * @param readKeys + * the ReadKeys element + * @param cmdCtx + * the command context + * @return a corresponding InfoboxReadResult + * + * @throws SLCommandException + * if the ReadKeys element is invalid or obtaining the corresponding + * values fails + */ + protected InfoboxReadResult readKeys(ReadKeys readKeys, SLCommandContext cmdCtx) throws SLCommandException { + + List selectedKeys = selectKeys(readKeys.getSearchString()); + + if (readKeys.isUserMakesUnique() && selectedKeys.size() > 1) { + log.info("UserMakesUnique not supported"); + // TODO: give more specific error message + throw new SLCommandException(4010); + } + + ObjectFactory objectFactory = new ObjectFactory(); + + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory + .createInfoboxReadDataAssocArrayType(); + + List keys = infoboxReadDataAssocArrayType.getKey(); + keys.addAll(selectedKeys); + + return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + + } + + /** + * Read all pairs specified by readPairs. + * + * @param readPairs + * the readPairs element + * @param cmdCtx + * the command context + * @return a corresponding InfoboxReadResult + * + * @throws SLCommandException + * if the ReadPairs element is invalid or obtaining the corresponding + * values fails + */ + protected InfoboxReadResult readPairs(ReadPairs readPairs, SLCommandContext cmdCtx) throws SLCommandException { + + if (readPairs.isValuesAreXMLEntities() && !isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readPairs + " but infobox type is binary."); + throw new SLCommandException(4010); + } + + if (!readPairs.isValuesAreXMLEntities() && isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readPairs + " but infobox type is XML."); + throw new SLCommandException(4010); + } + + List selectedKeys = selectKeys(readPairs.getSearchString()); + + if (readPairs.isUserMakesUnique() && selectedKeys.size() > 1) { + log.info("UserMakesUnique not supported"); + // TODO: give more specific error message + throw new SLCommandException(4010); + } + + ObjectFactory objectFactory = new ObjectFactory(); + + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory.createInfoboxReadDataAssocArrayType(); + + Map values = getValues(selectedKeys, cmdCtx); + for (String key : selectedKeys) { + InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); + infoboxAssocArrayPairType.setKey(key); + Object value = values.get(key); + if (value instanceof byte[]) { + infoboxAssocArrayPairType.setBase64Content((byte[]) value); + } else { + infoboxAssocArrayPairType.setXMLContent((XMLContentType) value); + } + infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); + } + + return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + } + + /** + * Read the value specified by readPairs. + * + * @param readValue + * the readValue element + * @param cmdCtx + * the command context + * @return a corresponding InfoboxReadResult + * + * @throws SLCommandException + * if the ReadValue element is invalid or obtaining the corresponding + * values fails + */ + protected InfoboxReadResult readValue(ReadValue readValue, SLCommandContext cmdCtx) throws SLCommandException { + + if (readValue.isValueIsXMLEntity() && !isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readValue + " but infobox type is binary."); + throw new SLCommandException(4010); + } + + if (!readValue.isValueIsXMLEntity() && isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readValue + " but infobox type is XML."); + throw new SLCommandException(4010); + } + + List selectedKeys; + + if (Arrays.asList(getKeys()).contains(readValue.getKey())) { + selectedKeys = Collections.singletonList(readValue.getKey()); + } else { + selectedKeys = Collections.emptyList(); + } + + ObjectFactory objectFactory = new ObjectFactory(); + + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory.createInfoboxReadDataAssocArrayType(); + + Map values = getValues(selectedKeys, cmdCtx); + for (String key : selectedKeys) { + InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); + infoboxAssocArrayPairType.setKey(key); + Object value = values.get(key); + if (value instanceof byte[]) { + infoboxAssocArrayPairType.setBase64Content((byte[]) value); + } else { + infoboxAssocArrayPairType.setXMLContent((XMLContentType) value); + } + infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); + } + + return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + } + + @Override + public InfoboxReadResult read(InfoboxReadRequestType req, + SLCommandContext cmdCtx) throws SLCommandException { + + InfoboxReadParamsAssocArrayType assocArrayParameters = req + .getAssocArrayParameters(); + + if (assocArrayParameters == null) { + log.info("Infobox type is AssocArray but got no AssocArrayParameters."); + throw new SLCommandException(4010); + } + + if (assocArrayParameters.getReadKeys() != null) { + return readKeys(assocArrayParameters.getReadKeys(), cmdCtx); + } + + if (assocArrayParameters.getReadPairs() != null) { + return readPairs(assocArrayParameters.getReadPairs(), cmdCtx); + } + + // ReadValue + if (assocArrayParameters.getReadValue() != null) { + return readValue(assocArrayParameters.getReadValue(), cmdCtx); + } + + log + .info("Infobox type is AssocArray but got invalid AssocArrayParameters."); + throw new SLCommandException(4010); + + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java new file mode 100644 index 00000000..07ca639c --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.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. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsBinaryFileType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; + +/** + * An abstract base class for {@link Infobox} implementations of type binary file. + * + * @author mcentner + */ +public abstract class AbstractBinaryFileInfobox extends AbstractInfoboxImpl implements BinaryFileInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(AbstractBinaryFileInfobox.class); + + /** + * Is this infobox' content an XML entity? + */ + private boolean isXMLEntity = false; + + /** + * @return true if this infobox' content is an XML entity or false otherwise. + */ + public boolean isXMLEntity() { + return isXMLEntity; + } + + /** + * Sets the value returned by {@link #isXMLEntity()} according to the given + * request. + * + * @param request the InfoboxReadRequest + */ + public void setIsXMLEntity(InfoboxReadRequestType request) { + + InfoboxReadParamsBinaryFileType binaryFileParameters = request.getBinaryFileParameters(); + if (binaryFileParameters != null) { + isXMLEntity = binaryFileParameters.isContentIsXMLEntity(); + log.debug("Got ContentIsXMLEntity=" + isXMLEntity + "."); + } + + } + + + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java new file mode 100644 index 00000000..305769a8 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java @@ -0,0 +1,55 @@ +/* +* 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.slcommands.impl; + +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +/** + * An abstract base class for implementations of security layer infobox requests. + * + * @author mcentner + * + * @param + */ +public abstract class AbstractInfoboxCommandImpl extends SLCommandImpl { + + /** + * The infobox implementation. + */ + protected Infobox infobox; + + @Override + public void init(SLCommandContext ctx, Object request) + throws SLCommandException { + super.init(ctx, request); + + String infoboxIdentifier = getInfoboxIdentifier(getRequestValue()); + + infobox = InfoboxFactory.getInstance().createInfobox(infoboxIdentifier); + } + + /** + * Returns the infobox identifier given in request. + * + * @param request the request value + * + * @return the infobox identifier givne in request + */ + protected abstract String getInfoboxIdentifier(T request); + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java new file mode 100644 index 00000000..e5c7afcc --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.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.slcommands.impl; + +/** + * An abstract base class for {@link Infobox} implementations. + * + * @author mcentner + */ +public abstract class AbstractInfoboxImpl implements Infobox { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java new file mode 100644 index 00000000..908d95da --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.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.slcommands.impl; + +/** + * An {@link Infobox} of type associative array as defined in Security Layer + * 1.2. + * + * @author mcentner + */ +public interface AssocArrayInfobox extends Infobox { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java new file mode 100644 index 00000000..c27f9446 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.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.slcommands.impl; + +/** + * An {@link Infobox} of type binary file as defined in Security Layer + * 1.2. + * + * @author mcentner + */ +public interface BinaryFileInfobox extends Infobox { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java new file mode 100644 index 00000000..0208f137 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java @@ -0,0 +1,112 @@ +/* +* 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.slcommands.impl; + +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * An implementation of the {@link Infobox} Certificates as + * specified in Security Layer 1.2. + * + * @author mcentner + */ +public class CertificatesInfoboxImpl extends AbstractAssocArrayInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(CertificatesInfoboxImpl.class); + + /** + * The valid keys. + */ + public static final String[] CERTIFICATES_KEYS = new String[] { + "SecureSignatureKeypair", + "CertifiedKeypair" }; + + @Override + public String getIdentifier() { + return "Certificates"; + } + + @Override + public String[] getKeys() { + return CERTIFICATES_KEYS; + } + + @Override + public boolean isValuesAreXMLEntities() { + return false; + } + + @Override + public Map getValues(List certificates, SLCommandContext cmdCtx) throws SLCommandException { + + STALHelper stalHelper = new STALHelper(cmdCtx.getSTAL()); + + if (certificates != null && !certificates.isEmpty()) { + + List stalRequests = new ArrayList(); + + // get certificates + InfoboxReadRequest infoboxReadRequest; + for (int i = 0; i < certificates.size(); i++) { + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier(certificates.get(i)); + stalRequests.add(infoboxReadRequest); + } + + stalHelper.transmitSTALRequest(stalRequests); + + List x509Certs = stalHelper.getCertificatesFromResponses(); + + Map values = new HashMap(); + + for (int i = 0; i < certificates.size(); i++) { + try { + values.put(certificates.get(i), x509Certs.get(i).getEncoded()); + } catch (CertificateEncodingException e) { + log.error("Failed to encode certificate.", e); + throw new SLCommandException(4000); + } + } + + return values; + + } else { + + return new HashMap(); + + } + + + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java index b2e3b303..01686641 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java @@ -16,13 +16,11 @@ */ package at.gv.egiz.bku.slcommands.impl; -import java.io.ByteArrayInputStream; import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.Date; +import java.util.List; import javax.xml.crypto.MarshalException; import javax.xml.crypto.URIReferenceException; @@ -48,11 +46,8 @@ import at.gv.egiz.bku.slexceptions.SLException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLViewerException; import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.InfoboxReadResponse; import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; /** * This class implements the security layer command @@ -147,33 +142,13 @@ public class CreateXMLSignatureCommandImpl extends InfoboxReadRequest stalRequest = new InfoboxReadRequest(); stalRequest.setInfoboxIdentifier(keyboxIdentifier); - requestSTAL(Collections.singletonList((STALRequest) stalRequest)); - - STALResponse stalResponse = stalResponses.next(); - - if (stalResponse instanceof InfoboxReadResponse) { - byte[] infobox = ((InfoboxReadResponse) stalResponse).getInfoboxValue(); - - try { - CertificateFactory certFactory = CertificateFactory.getInstance("X509"); - signingCertificate = (X509Certificate) certFactory - .generateCertificate(new ByteArrayInputStream(infobox)); - } catch (CertificateException e) { - log.info("Failed to decode signing certificate.", e); - // TODO: issue appropriate error - throw new SLCommandException(4000); - } - - } else if (stalResponse instanceof ErrorResponse) { - ErrorResponse err = (ErrorResponse) stalResponse; - log.info("Received an error response from STAL with code: " - + err.getErrorCode()); - throw new SLCommandException(err.getErrorCode()); - - } else { - log.info("Failed to get signing certificate."); + stalHelper.transmitSTALRequest(Collections.singletonList((STALRequest) stalRequest)); + List certificates = stalHelper.getCertificatesFromResponses(); + if (certificates == null || certificates.size() != 1) { + log.info("Got an unexpected number of certificates from STAL."); throw new SLCommandException(4000); } + signingCertificate = certificates.get(0); } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java new file mode 100644 index 00000000..20d20c9d --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java @@ -0,0 +1,291 @@ +/* +* 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.slcommands.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType; +import at.buergerkarte.namespaces.securitylayer._1.AnyChildrenType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.idlink.CompressedIdentityLinkFactory; +import at.gv.egiz.idlink.IdentityLinkTransformer; +import at.gv.egiz.idlink.ans1.IdentityLink; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * An implementation of the {@link Infobox} IdentityLink as + * specified in Security Layer 1.2 + * + * @author mcentner + */ +public class IdentityLinkInfoboxImpl extends AbstractBinaryFileInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(IdentityLinkInfoboxImpl.class); + + /** + * The box specific parameter IdentityLinkDomainIdentifier. + */ + public static final String BOX_SPECIFIC_PARAMETER_IDENTITY_LINK_DOMAIN_IDENTIFIER = "IdentityLinkDomainIdentifier"; + + /** + * The value of the box specific parameter IdentityLinkDomainIdentifier. + */ + private String domainIdentifier; + + @Override + public String getIdentifier() { + return "IdentityLink"; + } + + /** + * @return the value of the box specific parameter IdentityLinkDomainIdentifier + */ + public String getDomainIdentifier() { + return domainIdentifier; + } + + @Override + public InfoboxReadResult read(InfoboxReadRequestType req, SLCommandContext cmdCtx) throws SLCommandException { + + AnyChildrenType boxSpecificParameters = req.getBoxSpecificParameters(); + + if (boxSpecificParameters != null) { + // check BoxSpecificParameters + List parameter = boxSpecificParameters.getAny(); + JAXBElement element; + if (parameter != null + && parameter.size() == 1 + && parameter.get(0) instanceof JAXBElement + && SLCommand.NAMESPACE_URI.equals((element = (JAXBElement) parameter.get(0)).getName().getNamespaceURI()) + && BOX_SPECIFIC_PARAMETER_IDENTITY_LINK_DOMAIN_IDENTIFIER.equals(element.getName().getLocalPart()) + && element.getValue() instanceof String) { + domainIdentifier = (String) element.getValue(); + log.debug("Got sl:IdentityLinkDomainIdentifier: " + domainIdentifier); + } else { + log.info("Got invalid BoxSpecificParameters."); + throw new SLCommandException(4010); + } + } + + setIsXMLEntity(req); + + STALHelper stalHelper = new STALHelper(cmdCtx.getSTAL()); + + List stalRequests = new ArrayList(); + + InfoboxReadRequest infoboxReadRequest; + // get raw identity link + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier(getIdentifier()); + infoboxReadRequest.setDomainIdentifier(domainIdentifier); + stalRequests.add(infoboxReadRequest); + + // get certificates + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier("SecureSignatureKeypair"); + stalRequests.add(infoboxReadRequest); + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier("CertifiedKeypair"); + stalRequests.add(infoboxReadRequest); + + stalHelper.transmitSTALRequest(stalRequests); + log.trace("Got STAL response"); + + IdentityLink identityLink = stalHelper.getIdentityLinkFromResponses(); + List certificates = stalHelper.getCertificatesFromResponses(); + + + CompressedIdentityLinkFactory idLinkFactory = CompressedIdentityLinkFactory.getInstance(); + JAXBElement compressedIdentityLink = idLinkFactory + .createCompressedIdentityLink(identityLink, certificates, getDomainIdentifier()); + + IdentityLinkTransformer identityLinkTransformer = IdentityLinkTransformer.getInstance(); + String issuerTemplate = identityLink.getIssuerTemplate(); + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db; + try { + db = dbf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + log.error("Failed to create XML document.", e); + throw new SLRuntimeException(e); + } + + Document document = db.newDocument(); + try { + idLinkFactory.marshallCompressedIdentityLink(compressedIdentityLink, document, null, true); + } catch (JAXBException e) { + log.info("Failed to marshall CompressedIdentityLink.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { getIdentifier() }); + } + + InfoboxReadResultFileImpl result = new InfoboxReadResultFileImpl(); + ByteArrayOutputStream resultBytes = null; + Result xmlResult = (isXMLEntity() || getDomainIdentifier() != null) + ? result.getXmlResult(true) + : new StreamResult((resultBytes = new ByteArrayOutputStream())); + try { + log.trace("Trying to transform identitylink"); + identityLinkTransformer.transformIdLink(issuerTemplate, new DOMSource(document), xmlResult); + } catch (MalformedURLException e) { + log.warn("Malformed issuer template URL '" + issuerTemplate + "'."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (IOException e) { + log.warn("Failed to dereferene issuer template URL '" + issuerTemplate + "'." ,e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (TransformerConfigurationException e) { + log.warn("Failed to create transformation template from issuer template URL '" + issuerTemplate + "'", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (TransformerException e) { + log.info("Faild to transform CompressedIdentityLink.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + + // TODO: Report BUG in IssuerTemplates + // Some IssuerTemplate stylesheets do not consider the pr:Type-Element of the CompressedIdentityLink ... + if (getDomainIdentifier() != null) { + if (xmlResult instanceof DOMResult) { + Node node = ((DOMResult) xmlResult).getNode(); + Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); + Node idLinkNode; + if (nextSibling != null) { + idLinkNode = nextSibling.getPreviousSibling(); + } else if (node != null) { + idLinkNode = node.getFirstChild(); + } else { + log + .error("An IdentityLinkDomainIdentifier of '" + + getDomainIdentifier() + + "' has been given. However, it cannot be set, as the transformation result does not contain a node."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + IdentityLinkTransformer.setDomainIdentifier(idLinkNode, getDomainIdentifier()); + } else { + log + .error("An IdentityLinkDomainIdentifier of '" + + getDomainIdentifier() + + "' has been given. However, it cannot be set, as the transformation result is not of type DOM."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + } + + if (!isXMLEntity()) { + if (resultBytes == null) { + resultBytes = new ByteArrayOutputStream(); + + if (xmlResult instanceof DOMResult) { + Node node = ((DOMResult) xmlResult).getNode(); + Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); + + DOMSource xmlSource; + if (nextSibling != null) { + xmlSource = new DOMSource(nextSibling.getPreviousSibling()); + } else if (node != null) { + xmlSource = new DOMSource(node.getFirstChild()); + } else { + log + .error("IssuerTemplate transformation returned no node."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + try { + Transformer transformer = transformerFactory.newTransformer(); + transformer.transform(xmlSource, new StreamResult(resultBytes)); + } catch (TransformerConfigurationException e) { + log.error(e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (TransformerException e) { + log.error(e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + } else if (xmlResult instanceof StreamResult) { + OutputStream outputStream = ((StreamResult) xmlResult).getOutputStream(); + if (outputStream instanceof ByteArrayOutputStream) { + result.setResultBytes(((ByteArrayOutputStream) outputStream).toByteArray()); + } else { + log.error("ContentIsXMLEntity is set to 'false'. However, an XMLResult has already been set."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + } + } else { + result.setResultBytes(resultBytes.toByteArray()); + } + } + + return result; + + } + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java new file mode 100644 index 00000000..a6f8cbb2 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java @@ -0,0 +1,53 @@ +/* + * 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.slcommands.impl; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +/** + * An implementation of this interface represents a infobox as defined in + * Security-Layer 1.2. + * + * @author mcentner + */ +public interface Infobox { + + /** + * @return the identifier of this infobox + */ + public String getIdentifier(); + + /** + * Read data from this infobox. + * + * @param request + * the InfoboxReadRequest + * @param cmdCtx + * the command context + * + * @return the data read from this infobox as InfoboxReadResult + * + * @throws SLCommandException + * if reading from this infobox fails + */ + public InfoboxReadResult read(InfoboxReadRequestType request, + SLCommandContext cmdCtx) throws SLCommandException; + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java new file mode 100644 index 00000000..4a03fe74 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java @@ -0,0 +1,151 @@ +/* +* 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.slcommands.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; + +/** + * A factory for creating {@link Infobox}es. + * + * @author mcentner + */ +public class InfoboxFactory { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(InfoboxFactory.class); + + /** + * The singleton instance of this InfoboxFactory. + */ + private static InfoboxFactory instance; + + /** + * @return an instance of this InfoboxFactory + */ + public synchronized static InfoboxFactory getInstance() { + if (instance == null) { + instance = new InfoboxFactory(); + } + return instance; + } + + /** + * The mapping of infobox identifier to implementation class. + */ + private HashMap> implementations; + + /** + * Private constructor. + */ + private InfoboxFactory() { + } + + /** + * Sets the mapping of infobox identifier to implementation class name. + * + * @param infoboxImplMap + * a mapping of infobox identifiers to implementation class names + * + * @throws ClassNotFoundException + * if implementation class is not an instance of {@link Infobox} + */ + @SuppressWarnings("unchecked") + public void setInfoboxImpl(Map infoboxImplMap) throws ClassNotFoundException { + HashMap> implMap = new HashMap>(); + ClassLoader cl = getClass().getClassLoader(); + for (String key : infoboxImplMap.keySet()) { + Class impl = (Class) cl.loadClass(infoboxImplMap.get(key)); + log.debug("Registering infobox '" + key + "' implementation '" + impl.getCanonicalName() + "'."); + implementations.put(key, impl); + } + implementations = implMap; + } + + /** + * Returns the configured implementation class for the given + * infoboxIdentifier. + * + * @param infoboxIdentifier + * the infobox identifier + * + * @return the implementation class for the given infobox identifier or + * null if there is no implementation class configured + */ + public Class getImplClass(String infoboxIdentifier) { + if (implementations != null) { + return implementations.get(infoboxIdentifier); + } else { + return null; + } + } + + /** + * Create a new {@link Infobox} instance for the given + * infoboxIdentifier. + * + * @param infoboxIdentifier + * the infobox identifier + * + * @return an {@link Infobox} implementation for the given infobox identifier + * + * @throws SLCommandException + * if there is no implementation for the given infobox identifier + * @throws SLRuntimeException + * if creating an {@link Infobox} instance fails + */ + public Infobox createInfobox(String infoboxIdentifier) throws SLCommandException, SLRuntimeException { + + Class implClass = getImplClass(infoboxIdentifier); + if (implClass == null) { + // infobox not supported + log.info("Unsupported infobox '" + infoboxIdentifier + "."); + throw new SLCommandException(4002, + SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, + new Object[] { infoboxIdentifier }); + } + + // try to instantiate + Infobox infobox; + try { + infobox = implClass.newInstance(); + log.debug("Infobox '" + infobox.getIdentifier() + "' created."); + } catch (InstantiationException e) { + // unexpected error + log.error("Failed to instantiate infobox implementation.", e); + throw new SLRuntimeException(e); + } catch (IllegalAccessException e) { + // unexpected error + log.error("Failed to instantiate infobox implementation.", e); + throw new SLRuntimeException(e); + } + + return infobox; + + } + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java index c7bb5205..aaa786a6 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java @@ -16,67 +16,14 @@ */ package at.gv.egiz.bku.slcommands.impl; -import iaik.asn1.CodingException; -import iaik.asn1.DerCoder; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Result; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType; -import at.buergerkarte.namespaces.securitylayer._1.AnyChildrenType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxAssocArrayPairType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadDataAssocArrayType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsBinaryFileType; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; -import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadKeys; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadPairs; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue; import at.gv.egiz.bku.slcommands.InfoboxReadCommand; -import at.gv.egiz.bku.slcommands.SLCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLExceptionMessages; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.idlink.CompressedIdentityLinkFactory; -import at.gv.egiz.idlink.IdentityLinkTransformer; -import at.gv.egiz.idlink.ans1.IdentityLink; -import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.InfoboxReadResponse; -import at.gv.egiz.stal.STALRequest; /** * This class implements the security layer command @@ -88,7 +35,7 @@ import at.gv.egiz.stal.STALRequest; * * @author mcentner */ -public class InfoboxReadCommandImpl extends SLCommandImpl implements +public class InfoboxReadCommandImpl extends AbstractInfoboxCommandImpl implements InfoboxReadCommand { /** @@ -96,511 +43,63 @@ public class InfoboxReadCommandImpl extends SLCommandImplInfoboxIdentifier - */ - protected String infoboxIdentifier; - - /** - * The IdentityLinkDomainIdentifier value of an IdentyLink infobox. - */ - protected String identityLinkDomainIdentifier; - - /** - * The list of certificates to be read from an Certificates infobox. - */ - protected List certificates; - - /** - * The result type. - */ - protected int assocArrayResult; - - /** - * Is content XML entity? - */ - protected boolean isXMLEntity; - @Override public String getName() { return "InfoboxReadRequest"; } - /** - * @return the infoboxIdentifier - */ - public String getInfoboxIdentifier() { - return infoboxIdentifier; - } - + @Override + protected String getInfoboxIdentifier(InfoboxReadRequestType request) { + return request.getInfoboxIdentifier(); + } + @Override public void init(SLCommandContext ctx, Object request) throws SLCommandException { super.init(ctx, request); InfoboxReadRequestType req = getRequestValue(); - - infoboxIdentifier = req.getInfoboxIdentifier(); - - if (INFOBOX_IDENTIFIER_IDENTITY_LINK.equals(infoboxIdentifier)) { - - if (req.getAssocArrayParameters() != null) { - log.info("Got AssocArrayParameters but Infobox type is BinaryFile."); - throw new SLCommandException(4010); - } - - InfoboxReadParamsBinaryFileType binaryFileParameters = req.getBinaryFileParameters(); - if (binaryFileParameters != null) { - isXMLEntity = binaryFileParameters.isContentIsXMLEntity(); - log.debug("Got ContentIsXMLEntity=" + isXMLEntity + "."); - } - - AnyChildrenType boxSpecificParameters = req.getBoxSpecificParameters(); - - if (boxSpecificParameters != null) { - // check BoxSpecificParameters - List parameter = boxSpecificParameters.getAny(); - JAXBElement element; - if (parameter != null - && parameter.size() == 1 - && parameter.get(0) instanceof JAXBElement - && SLCommand.NAMESPACE_URI.equals((element = (JAXBElement) parameter.get(0)).getName().getNamespaceURI()) - && BOX_SPECIFIC_PARAMETER_IDENTITY_LINK_DOMAIN_IDENTIFIER.equals(element.getName().getLocalPart()) - && element.getValue() instanceof String) { - identityLinkDomainIdentifier = (String) element.getValue(); - log.debug("Got sl:IdentityLinkDomainIdentifier: " + identityLinkDomainIdentifier); - } else { - log.info("Got invalid BoxSpecificParameters."); - throw new SLCommandException(4010); - } - } - } else if (INFOBOX_IDENTIFIER_CERTIFICATES.equals(infoboxIdentifier)) { - - if (req.getBinaryFileParameters() != null) { - log.info("Got BinaryFileParameters but Infobox type is AssocArray."); - throw new SLCommandException(4010); - } - - if (req.getBoxSpecificParameters() != null) { - log.info("Got invalid BoxSpecificParameters."); - throw new SLCommandException(4010); - } - - InfoboxReadParamsAssocArrayType assocArrayParameters = req - .getAssocArrayParameters(); - if (assocArrayParameters == null) { - log.info("Infobox type is AssocArray but got no AssocArrayParameters."); - throw new SLCommandException(4010); - } - - // RreadKeys? - if (assocArrayParameters.getReadKeys() != null) { - assocArrayResult = ASSOC_ARRAY_READ_KEYS; - ReadKeys readKeys = assocArrayParameters.getReadKeys(); - certificates = findCertificates(readKeys.getSearchString()); - if (readKeys.isUserMakesUnique() && certificates.size() > 1) { - log.info("UserMakesUnique not supported"); - // TODO: give more specific error message - throw new SLCommandException(4010); - } - } - - // ReadPairs? - if (assocArrayParameters.getReadPairs() != null) { - assocArrayResult = ASSOC_ARRAY_READ_PAIRS; - ReadPairs readPairs = assocArrayParameters.getReadPairs(); - if (readPairs.isValuesAreXMLEntities()) { - log.info("Got valuesAreXMLEntities but infobox type is binary."); - throw new SLCommandException(4010); - } - certificates = findCertificates(readPairs.getSearchString()); - if (readPairs.isUserMakesUnique() && certificates.size() > 1) { - log.info("UserMakesUnique not supported"); - // TODO: give more specific error message - throw new SLCommandException(4010); - } - } - - // ReadValue - if (assocArrayParameters.getReadValue() != null) { - assocArrayResult = ASSOC_ARRAY_READ_VALUE; - ReadValue readValue = assocArrayParameters.getReadValue(); - if (readValue.isValueIsXMLEntity()) { - log.info("Got valuesAreXMLEntities but infobox type is binary."); - throw new SLCommandException(4010); - } - String key = readValue.getKey(); - if (Arrays.asList(INFOXBOX_CERTIFICATES_KEYS).contains(key)) { - certificates = Collections.singletonList(key); - } else { - certificates = Collections.emptyList(); - } - } - - if (assocArrayResult == 0) { - log.info("Infobox type is AssocArray but got invalid AssocArrayParameters."); - throw new SLCommandException(4010); - } - - } else { - throw new SLCommandException(4002, - SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, - new Object[] { infoboxIdentifier }); - } + if (req.getAssocArrayParameters() != null && + !(infobox instanceof AssocArrayInfobox)) { + log.info("Got AssocArrayParameters but Infobox type is not AssocArray."); + throw new SLCommandException(4010); + } + + if (req.getBinaryFileParameters() != null && + !(infobox instanceof BinaryFileInfobox)) { + log.info("Got BinaryFileParameters but Infobox type is not BinaryFile."); + throw new SLCommandException(4010); + } } @Override public SLResult execute() { - try { - if (INFOBOX_IDENTIFIER_IDENTITY_LINK.equals(infoboxIdentifier)) { - return readIdentityLink(); - } else if (INFOBOX_IDENTIFIER_CERTIFICATES.equals(infoboxIdentifier)) { - return readCertificates(); - } else { - throw new SLCommandException(4000); - } - } catch (SLCommandException e) { - return new ErrorResultImpl(e, cmdCtx.getLocale()); - } - } - - /** - * Gets the IdentitiyLink form the next STAL response. - * - * @return the IdentityLink - * - * @throws SLCommandException if getting the IdentitiyLink fails - */ - private IdentityLink getIdentityLinkFromResponses() throws SLCommandException { - - // IdentityLink - InfoboxReadResponse response; - if (hasNextResponse()) { - response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); - byte[] idLink = response.getInfoboxValue(); - try { - return new IdentityLink(DerCoder.decode(idLink)); - } catch (CodingException e) { - log.info("Failed to decode infobox '" + INFOBOX_IDENTIFIER_IDENTITY_LINK + "'.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, - new Object[] { INFOBOX_IDENTIFIER_IDENTITY_LINK }); - } - } else { - log.info("No infobox '" + INFOBOX_IDENTIFIER_IDENTITY_LINK + "' returned from STAL."); - throw new SLCommandException(4000); - } - - } - - /** - * Gets the list of certificates from the next STAL responses. - * - * @return the list of certificates - * - * @throws SLCommandException if getting the list of certificates fails - */ - private List getCertificatesFromResponses() throws SLCommandException { - - List certificates = new ArrayList(); - - CertificateFactory certFactory; - try { - certFactory = CertificateFactory.getInstance("X509"); - } catch (CertificateException e) { - // we should always be able to get an X509 certificate factory - log.error("CertificateFactory.getInstance(\"X509\") failed.", e); - throw new SLRuntimeException(e); - } - - InfoboxReadResponse response; - while(hasNextResponse()) { - response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); - byte[] cert = response.getInfoboxValue(); - try { - certificates.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(cert))); - } catch (CertificateException e) { - log.info("Failed to decode certificate.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, - new Object[] { INFOBOX_IDENTIFIER_CERTIFICATES }); - } - } - - return certificates; - - } - - /** - * Uses STAL to read the IdentityLink. - * - * @return the corresponding security layer result - * - * @throws SLCommandException if reading the IdentityLink fails - */ - private SLResult readIdentityLink() throws SLCommandException { - - List stalRequests = new ArrayList(); - - InfoboxReadRequest infoboxReadRequest; - // get raw identity link - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier(INFOBOX_IDENTIFIER_IDENTITY_LINK); - infoboxReadRequest.setDomainIdentifier(identityLinkDomainIdentifier); - stalRequests.add(infoboxReadRequest); - - // get certificates - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier("SecureSignatureKeypair"); - stalRequests.add(infoboxReadRequest); - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier("CertifiedKeypair"); - stalRequests.add(infoboxReadRequest); - - requestSTAL(stalRequests); - log.trace("Got STAL response"); - - IdentityLink identityLink = getIdentityLinkFromResponses(); - List certificates = getCertificatesFromResponses(); - - - CompressedIdentityLinkFactory idLinkFactory = CompressedIdentityLinkFactory.getInstance(); - JAXBElement compressedIdentityLink = idLinkFactory - .createCompressedIdentityLink(identityLink, certificates, identityLinkDomainIdentifier); - - IdentityLinkTransformer identityLinkTransformer = IdentityLinkTransformer.getInstance(); - String issuerTemplate = identityLink.getIssuerTemplate(); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db; - try { - db = dbf.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - log.error("Failed to create XML document.", e); - throw new SLRuntimeException(e); - } - - Document document = db.newDocument(); - try { - idLinkFactory.marshallCompressedIdentityLink(compressedIdentityLink, document, null, true); - } catch (JAXBException e) { - log.info("Failed to marshall CompressedIdentityLink.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, - new Object[] { INFOBOX_IDENTIFIER_IDENTITY_LINK }); - } - - InfoboxReadResultFileImpl result = new InfoboxReadResultFileImpl(); - ByteArrayOutputStream resultBytes = null; - Result xmlResult = (isXMLEntity || identityLinkDomainIdentifier != null) - ? result.getXmlResult(true) - : new StreamResult((resultBytes = new ByteArrayOutputStream())); + try { - log.trace("Trying to transform identitylink"); - identityLinkTransformer.transformIdLink(issuerTemplate, new DOMSource(document), xmlResult); - } catch (MalformedURLException e) { - log.warn("Malformed issuer template URL '" + issuerTemplate + "'."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (IOException e) { - log.warn("Failed to dereferene issuer template URL '" + issuerTemplate + "'." ,e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (TransformerConfigurationException e) { - log.warn("Failed to create transformation template from issuer template URL '" + issuerTemplate + "'", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (TransformerException e) { - log.info("Faild to transform CompressedIdentityLink.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - - // TODO: Report BUG in IssuerTemplates - // Some IssuerTemplate stylesheets do not consider the pr:Type-Element of the CompressedIdentityLink ... - if (identityLinkDomainIdentifier != null) { - if (xmlResult instanceof DOMResult) { - Node node = ((DOMResult) xmlResult).getNode(); - Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); - Node idLinkNode; - if (nextSibling != null) { - idLinkNode = nextSibling.getPreviousSibling(); - } else if (node != null) { - idLinkNode = node.getFirstChild(); - } else { - log - .error("An IdentityLinkDomainIdentifier of '" - + identityLinkDomainIdentifier - + "' has been given. However, it cannot be set, as the transformation result does not contain a node."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - IdentityLinkTransformer.setDomainIdentifier(idLinkNode, identityLinkDomainIdentifier); - } else { - log - .error("An IdentityLinkDomainIdentifier of '" - + identityLinkDomainIdentifier - + "' has been given. However, it cannot be set, as the transformation result is not of type DOM."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - } - - if (!isXMLEntity) { - if (resultBytes == null) { - resultBytes = new ByteArrayOutputStream(); - - if (xmlResult instanceof DOMResult) { - Node node = ((DOMResult) xmlResult).getNode(); - Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); - - DOMSource xmlSource; - if (nextSibling != null) { - xmlSource = new DOMSource(nextSibling.getPreviousSibling()); - } else if (node != null) { - xmlSource = new DOMSource(node.getFirstChild()); - } else { - log - .error("IssuerTemplate transformation returned no node."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - try { - Transformer transformer = transformerFactory.newTransformer(); - transformer.transform(xmlSource, new StreamResult(resultBytes)); - } catch (TransformerConfigurationException e) { - log.error(e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (TransformerException e) { - log.error(e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - } else if (xmlResult instanceof StreamResult) { - OutputStream outputStream = ((StreamResult) xmlResult).getOutputStream(); - if (outputStream instanceof ByteArrayOutputStream) { - result.setResultBytes(((ByteArrayOutputStream) outputStream).toByteArray()); - } else { - log.error("ContentIsXMLEntity is set to 'false'. However, an XMLResult has already been set."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - } - } else { - result.setResultBytes(resultBytes.toByteArray()); - } - } - - - return result; - - } - - protected List findCertificates(String searchString) throws SLCommandException { - - if ("*".equals(searchString) || "**".equals(searchString)) { - return Arrays.asList(INFOXBOX_CERTIFICATES_KEYS); + return infobox.read(getRequestValue(), getCmdCtx()); + } catch (SLCommandException e) { + return new ErrorResultImpl(e, getCmdCtx().getLocale()); } - if (Pattern.matches(SEARCH_STRING_PATTERN, searchString)) { - -// for (int i = 0; i < searchString.length(); i++) { -// int codePoint = searchString.codePointAt(i); -// -// } - - // TODO : build pattern - return Collections.emptyList(); + } + + + @Override + public String getIdentityLinkDomainId() { + if (infobox instanceof IdentityLinkInfoboxImpl) { + return ((IdentityLinkInfoboxImpl) infobox).getDomainIdentifier(); } else { - log.info("Got invalid search string '" + searchString + "'"); - throw new SLCommandException(4010); + return null; } - } - private SLResult readCertificates() throws SLCommandException { - - ObjectFactory objectFactory = new ObjectFactory(); - - InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory - .createInfoboxReadDataAssocArrayType(); - - if (assocArrayResult == ASSOC_ARRAY_READ_KEYS) { - - List keys = infoboxReadDataAssocArrayType.getKey(); - keys.addAll(certificates); - + @Override + public String getInfoboxIdentifier() { + if (infobox != null) { + return infobox.getIdentifier(); } else { - - if (certificates != null && !certificates.isEmpty()) { - - List stalRequests = new ArrayList(); - - // get certificates - InfoboxReadRequest infoboxReadRequest; - for (int i = 0; i < certificates.size(); i++) { - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier(certificates.get(i)); - stalRequests.add(infoboxReadRequest); - } - - requestSTAL(stalRequests); - - List x509Certs = getCertificatesFromResponses(); - - for (int i = 0; i < certificates.size(); i++) { - InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); - infoboxAssocArrayPairType.setKey(certificates.get(i)); - try { - infoboxAssocArrayPairType.setBase64Content(x509Certs.get(i).getEncoded()); - } catch (CertificateEncodingException e) { - log.error("Failed to encode certificate.", e); - throw new SLCommandException(4000); - } - infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); - } - - } - + return null; } - - return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); - - } - - @Override - public String getIdentityLinkDomainId() { - return identityLinkDomainIdentifier; } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java index 8904eac6..a2b8ac9f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java @@ -23,8 +23,9 @@ import javax.xml.transform.Templates; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadDataAssocArrayType; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadResponseType; import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; -public class InfoboxReadResultImpl extends SLResultImpl { +public class InfoboxReadResultImpl extends SLResultImpl implements InfoboxReadResult { /** * The InfoboxReadResponse diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java new file mode 100644 index 00000000..6d281686 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java @@ -0,0 +1,158 @@ +/* +* 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.slcommands.impl; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.cardchannel.CommandAPDUType; +import at.buergerkarte.namespaces.cardchannel.ResetType; +import at.buergerkarte.namespaces.cardchannel.ScriptType; +import at.buergerkarte.namespaces.cardchannel.VerifyAPDUType; +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLContentType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateRequestType; +import at.gv.egiz.bku.slcommands.InfoboxUpdateCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; + +public class InfoboxUpdateCommandImpl extends + SLCommandImpl implements InfoboxUpdateCommand { + + private static Log log = LogFactory.getLog(InfoboxUpdateCommandImpl.class); + + public static final String INFOBOX_IDENTIFIER_CARD_CHANNEL = "CardChannel"; + + protected String infoboxIdentifier; + + protected List cardChannelScript; + + @Override + public String getInfoboxIdentifier() { + return infoboxIdentifier; + } + + @Override + public void init(SLCommandContext ctx, Object request) + throws SLCommandException { + super.init(ctx, request); + + InfoboxUpdateRequestType req = getRequestValue(); + + infoboxIdentifier = req.getInfoboxIdentifier(); + + if (INFOBOX_IDENTIFIER_CARD_CHANNEL.equals(infoboxIdentifier)) { + + if (req.getAssocArrayParameters() != null) { + log.info("Got AssocArrayParameters but Infobox type is BinaryFile."); + throw new SLCommandException(4010); + } + + Base64XMLContentType binaryFileParameters = req.getBinaryFileParameters(); + if (binaryFileParameters == null) { + log.info("Got no BinaryFileParameters but Infobox type is BinaryFile."); + throw new SLCommandException(4010); + } + + if (binaryFileParameters.getBase64Content() == null) { + log.info("Got Base64Content but ContentIsXMLEntity is true."); + throw new SLCommandException(4010); + } + + List content = binaryFileParameters.getXMLContent().getContent(); + if (content.isEmpty()) { + log.info("Got no XMLContent but ContentIsXMLEntity is true."); + throw new SLCommandException(4010); + } + + for (Object element : content) { + if (!(element instanceof ScriptType)) { + log.info("Infobox identifier is '" + infoboxIdentifier + "' but XMLContent does not contain 'Script'."); + throw new SLCommandException(4010); + } + + setCardChannelScript(((ScriptType) element).getResetOrCommandAPDUOrVerifyAPDU()); + } + + if (getCardChannelScript() == null) { + log.info("Infobox identifier is '" + infoboxIdentifier + "' but XMLContent does not contain 'Script'."); + throw new SLCommandException(4010); + } + + } else { + throw new SLCommandException(4002, + SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, + new Object[] { infoboxIdentifier }); + } + + } + + public List getCardChannelScript() { + return cardChannelScript; + } + + public void setCardChannelScript(List cardChannelScript) { + this.cardChannelScript = cardChannelScript; + } + + @Override + public SLResult execute() { + + try { + if (INFOBOX_IDENTIFIER_CARD_CHANNEL.equals(getInfoboxIdentifier())) { + + executeCardChannelScript(); + return new InfoboxUpdateResultImpl(); + + } else { + throw new SLCommandException(4002, + SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, + new Object[] { infoboxIdentifier }); + } + } catch (SLCommandException e) { + return new ErrorResultImpl(e, cmdCtx.getLocale()); + } + + } + + protected void executeCardChannelScript() throws SLCommandException { + + if (cardChannelScript != null) { + + for (Object element : cardChannelScript) { + if (element instanceof ResetType) { + + } else if (element instanceof CommandAPDUType) { + + } else if (element instanceof VerifyAPDUType) { + + } + } + + } + + } + + @Override + public String getName() { + return "InfoboxUpdateRequest"; + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java new file mode 100644 index 00000000..15064756 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java @@ -0,0 +1,43 @@ +/* +* 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.slcommands.impl; + +import javax.xml.bind.JAXBElement; +import javax.xml.transform.Result; +import javax.xml.transform.Templates; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateResponseType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.gv.egiz.bku.slcommands.InfoboxUpdateResult; + +public class InfoboxUpdateResultImpl extends SLResultImpl implements + InfoboxUpdateResult { + + protected static JAXBElement RESPONSE; + + static { + ObjectFactory factory = new ObjectFactory(); + InfoboxUpdateResponseType type = factory.createInfoboxUpdateResponseType(); + RESPONSE = factory.createInfoboxUpdateResponse(type); + } + + @Override + public void writeTo(Result result, Templates templates) { + writeTo(RESPONSE, result, templates); + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java index 9a3a2984..ed055b69 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java @@ -16,22 +16,11 @@ */ package at.gv.egiz.bku.slcommands.impl; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import javax.xml.bind.JAXBElement; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.slcommands.SLCommand; -import at.gv.egiz.bku.slcommands.SLCommandContext; -import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.STAL; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; +import javax.xml.bind.JAXBElement; + +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; /** * This class serves as abstract base class for the implementation of a security @@ -47,19 +36,18 @@ public abstract class SLCommandImpl implements SLCommand { /** * The SLCommandContext for this SLCommand. */ - protected SLCommandContext cmdCtx; + protected SLCommandContext cmdCtx; + + /** + * The STAL helper. + */ + protected STALHelper stalHelper; /** * The request element of this command. */ protected JAXBElement request; - /** - * An iterator over the STALResponses received in - * {@link SLCommandImpl#requestSTAL(List)}. - */ - protected Iterator stalResponses; - @SuppressWarnings("unchecked") @Override public void init(SLCommandContext ctx, Object request) @@ -67,8 +55,8 @@ public abstract class SLCommandImpl implements SLCommand { this.request = (JAXBElement) request; - this.cmdCtx = ctx; - assert this.cmdCtx != null; + this.cmdCtx = ctx; + stalHelper = new STALHelper(cmdCtx.getSTAL()); } @@ -90,73 +78,4 @@ public abstract class SLCommandImpl implements SLCommand { protected SLCommandContext getCmdCtx() { return cmdCtx; } - - /** - * Calls {@link STAL#handleRequest(List)} with the given - * stalRequests. - * - * @param stalRequests - * @throws SLCommandException - */ - protected void requestSTAL(List stalRequests) throws SLCommandException { - List responses = cmdCtx.getSTAL().handleRequest(stalRequests); - if (responses == null) { - Log log = LogFactory.getLog(this.getClass()); - log.info("Received no responses from STAL."); - throw new SLCommandException(4000); - } else if (responses.size() != stalRequests.size()) { - Log log = LogFactory.getLog(this.getClass()); - log.info("Received invalid count of responses from STAL. Expected " - + stalRequests.size() + ", but got " + responses.size() + "."); - // throw new SLCommandException(4000); - } - stalResponses = responses.iterator(); - } - - /** - * @return true if there are more {@link STALResponse}s to be - * fetched with {@link #nextResponse(Class)}, or false - * otherwise. - */ - protected boolean hasNextResponse() { - return (stalResponses != null) ? stalResponses.hasNext() : false; - } - - /** - * Returns the next response of type responseClass that has been - * received by {@link #requestSTAL(List)}. - * - * @param responseClass - * the response must be an instance of - * @return the next response of type responseClass - * - * @throws NoSuchElementException - * if there is no more response - * @throws SLCommandException - * if the next response is of type {@link ErrorResponse} or not of - * type responseClass - */ - protected STALResponse nextResponse( - Class responseClass) throws SLCommandException { - - if (stalResponses == null) { - throw new NoSuchElementException(); - } - - STALResponse response = stalResponses.next(); - - if (response instanceof ErrorResponse) { - throw new SLCommandException(((ErrorResponse) response).getErrorCode()); - } - - if (!(responseClass.isAssignableFrom(response.getClass()))) { - Log log = LogFactory.getLog(this.getClass()); - log.info("Received " + response.getClass() + " from STAL but expected " - + responseClass); - throw new SLCommandException(4000); - } - - return response; - - } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java new file mode 100644 index 00000000..969288c1 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java @@ -0,0 +1,218 @@ +/* +* 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.slcommands.impl; + +import iaik.asn1.CodingException; +import iaik.asn1.DerCoder; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.idlink.ans1.IdentityLink; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +/** + * A helper class for transmitting {@link STALRequest}s and obtaining their + * respective {@link STALResponse}s. + * + * @author mcentner + */ +public class STALHelper { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(STALHelper.class); + + /** + * The STAL implementation. + */ + private STAL stal; + + /** + * An iterator over the STALResponses received in + * {@link SLCommandImpl#transmitSTALRequest(List)}. + */ + protected Iterator stalResponses; + + /** + * Creates a new instance of this STALHelper with the given + * stal. + * + * @param stal the STAL to be used + */ + public STALHelper(STAL stal) { + if (stal == null) { + throw new NullPointerException("Argument 'stal' must not be null."); + } + this.stal = stal; + } + + /** + * Calls {@link STAL#handleRequest(List)} with the given + * stalRequests. + * + * @param stalRequests + * @throws SLCommandException + */ + public void transmitSTALRequest(List stalRequests) throws SLCommandException { + List responses = stal.handleRequest(stalRequests); + if (responses == null) { + Log log = LogFactory.getLog(this.getClass()); + log.info("Received no responses from STAL."); + throw new SLCommandException(4000); + } else if (responses.size() != stalRequests.size()) { + Log log = LogFactory.getLog(this.getClass()); + log.info("Received invalid count of responses from STAL. Expected " + + stalRequests.size() + ", but got " + responses.size() + "."); + // throw new SLCommandException(4000); + } + stalResponses = responses.iterator(); + } + + /** + * @return true if there are more {@link STALResponse}s to be + * fetched with {@link #nextResponse(Class)}, or false + * otherwise. + */ + public boolean hasNextResponse() { + return (stalResponses != null) ? stalResponses.hasNext() : false; + } + + /** + * Returns the next response of type responseClass that has been + * received by {@link #transmitSTALRequest(List)}. + * + * @param responseClass + * the response must be an instance of + * @return the next response of type responseClass + * + * @throws NoSuchElementException + * if there is no more response + * @throws SLCommandException + * if the next response is of type {@link ErrorResponse} or not of + * type responseClass + */ + public STALResponse nextResponse( + Class responseClass) throws SLCommandException { + + if (stalResponses == null) { + throw new NoSuchElementException(); + } + + STALResponse response = stalResponses.next(); + + if (response instanceof ErrorResponse) { + throw new SLCommandException(((ErrorResponse) response).getErrorCode()); + } + + if (!(responseClass.isAssignableFrom(response.getClass()))) { + Log log = LogFactory.getLog(this.getClass()); + log.info("Received " + response.getClass() + " from STAL but expected " + + responseClass); + throw new SLCommandException(4000); + } + + return response; + + } + + /** + * Gets the list of certificates from the next STAL responses. + * + * @return the list of certificates + * + * @throws SLCommandException if getting the list of certificates fails + */ + public List getCertificatesFromResponses() throws SLCommandException { + + List certificates = new ArrayList(); + + CertificateFactory certFactory; + try { + certFactory = CertificateFactory.getInstance("X509"); + } catch (CertificateException e) { + // we should always be able to get an X509 certificate factory + log.error("CertificateFactory.getInstance(\"X509\") failed.", e); + throw new SLRuntimeException(e); + } + + InfoboxReadResponse response; + while(hasNextResponse()) { + response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); + byte[] cert = response.getInfoboxValue(); + try { + certificates.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(cert))); + } catch (CertificateException e) { + log.info("Failed to decode certificate.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { "Certificates" }); + } + } + + return certificates; + + } + + /** + * Gets the IdentitiyLink form the next STAL response. + * + * @return the IdentityLink + * + * @throws SLCommandException if getting the IdentitiyLink fails + */ + public IdentityLink getIdentityLinkFromResponses() throws SLCommandException { + + // IdentityLink + InfoboxReadResponse response; + if (hasNextResponse()) { + response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); + byte[] idLink = response.getInfoboxValue(); + try { + return new IdentityLink(DerCoder.decode(idLink)); + } catch (CodingException e) { + log.info("Failed to decode infobox 'IdentityLink'.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { "IdentityLink" }); + } + } else { + log.info("No infobox 'IdentityLink' returned from STAL."); + throw new SLCommandException(4000); + } + + } + + +} diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml deleted file mode 100644 index 885e35f3..00000000 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml new file mode 100644 index 00000000..13365931 --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3