/****************************************************************************
* Copyright (C) 2012 HS Coburg.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.control.module.status;
import iso.std.iso_iec._24727.tech.schema.CardApplicationType;
import iso.std.iso_iec._24727.tech.schema.CardInfoType;
import iso.std.iso_iec._24727.tech.schema.ChannelHandleType;
import iso.std.iso_iec._24727.tech.schema.ConnectionHandleType;
import iso.std.iso_iec._24727.tech.schema.DIDInfoType;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.openecard.addon.EventHandler;
import org.openecard.common.Version;
import org.openecard.common.sal.state.CardStateEntry;
import org.openecard.common.sal.state.CardStateMap;
import org.openecard.recognition.CardRecognition;
import org.openecard.ws.schema.Status;
import org.openecard.ws.schema.StatusType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handles the generic part of status requests.
*
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
*/
public class StatusHandler {
private static final Logger logger = LoggerFactory.getLogger(StatusHandler.class);
private CardStateMap cardStates;
private EventHandler eventHandler;
private List<String> protocols;
private CardRecognition rec;
/**
* Create a new StatusHandler.
*
* @param cardStates CardStateMap of the client for querying all ConnectionHandles
* @param eventHandler for adding eventQueues
* @param protocols
* @param rec
*/
public StatusHandler(CardStateMap cardStates, EventHandler eventHandler, List<String> protocols, CardRecognition rec) {
this.cardStates = cardStates;
this.eventHandler = eventHandler;
this.protocols = protocols;
this.rec = rec;
}
/**
* Handles a Status-Request by returning a status including list of all known ConnectionHandles (including
* unrecognized cards).
*
* @param statusRequest Status Request containing an optional session identifier
* @return Status including list of all known ConnectionHandles
*/
public Status handleRequest(StatusRequest statusRequest) {
String sessionIdentifier = statusRequest.getSessionIdentifier();
Status status = new Status();
ConnectionHandleType handle = new ConnectionHandleType();
// fill in static values
// user agent
StatusType.UserAgent ua = new StatusType.UserAgent();
ua.setName("Open eCard App");
ua.setVersionMajor(BigInteger.valueOf(Version.getMajor()));
ua.setVersionMinor(BigInteger.valueOf(Version.getMinor()));
ua.setVersionSubminor(BigInteger.valueOf(Version.getPatch()));
status.setUserAgent(ua);
// API versions
StatusType.SupportedAPIVersions apiVersion = new StatusType.SupportedAPIVersions();
apiVersion.setName("http://www.bsi.bund.de/ecard/api");
apiVersion.setVersionMajor(BigInteger.ONE);
apiVersion.setVersionMinor(BigInteger.ONE);
status.getSupportedAPIVersions().add(apiVersion);
// TODO: supported cards
List<CardInfoType> cifs = rec.getCardInfos();
List<StatusType.SupportedCards> supportedCards = getSupportedCards(protocols, cifs);
status.getSupportedCards().addAll(supportedCards);
// supported DID protocols
status.getSupportedDIDProtocols().addAll(protocols);
// TODO: additional features
if (sessionIdentifier != null) {
ChannelHandleType channelHandle = new ChannelHandleType();
channelHandle.setSessionIdentifier(sessionIdentifier);
handle.setChannelHandle(channelHandle);
eventHandler.addQueue(sessionIdentifier);
}
Set<CardStateEntry> entries = this.cardStates.getMatchingEntries(handle);
for (CardStateEntry entry : entries) {
status.getConnectionHandle().add(entry.handleCopy());
}
return status;
}
/**
*
* @param requestURI Status request URI
* @return StatusRequest containing an optional session identifier
* @throws UnsupportedEncodingException
* @throws MalformedURLException If mandatory parameters or values are missing
*/
public StatusRequest parseStatusRequestURI(URI requestURI) throws UnsupportedEncodingException,
MalformedURLException {
StatusRequest statusRequest = new StatusRequest();
if (requestURI.getQuery() == null) {
return statusRequest;
}
String[] query = requestURI.getQuery().split("&");
for (String q : query) {
String name = q.substring(0, q.indexOf('='));
String value = q.substring(q.indexOf('=') + 1, q.length());
if (name.startsWith("session")) {
if (!value.isEmpty()) {
value = URLDecoder.decode(value, "UTF-8");
statusRequest.setSessionIdentifier(value);
} else {
throw new MalformedURLException("Value for session parameter is missing.");
}
} else {
logger.debug("Unknown query element: {}", name);
}
}
return statusRequest;
}
private static List<StatusType.SupportedCards> getSupportedCards(List<String> protocols, List<CardInfoType> cifs) {
List<StatusType.SupportedCards> result = new ArrayList<StatusType.SupportedCards>();
for (CardInfoType cif : cifs) {
StatusType.SupportedCards supportedCard = new StatusType.SupportedCards();
result.add(supportedCard);
String name = cif.getCardType().getObjectIdentifier();
supportedCard.setCardType(name);
for (CardApplicationType app : cif.getApplicationCapabilities().getCardApplication()) {
for (DIDInfoType did : app.getDIDInfo()) {
String proto = did.getDifferentialIdentity().getDIDProtocol();
// add protocol to list only if it is supported by the application and not yet added
if (protocols.contains(proto) && ! supportedCard.getDIDProtocols().contains(proto)) {
supportedCard.getDIDProtocols().add(proto);
}
}
}
}
return result;
}
}