/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.societies.security.policynegotiator.requester;
import java.net.URI;
import java.util.List;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.identity.IIdentity;
import org.societies.api.identity.Requestor;
import org.societies.api.identity.RequestorCis;
import org.societies.api.identity.RequestorService;
import org.societies.api.internal.privacytrust.privacyprotection.IPrivacyPolicyNegotiationManager;
import org.societies.api.internal.privacytrust.privacyprotection.negotiation.NegotiationDetails;
import org.societies.api.internal.schema.security.policynegotiator.MethodType;
import org.societies.api.internal.schema.security.policynegotiator.SlaBean;
import org.societies.api.internal.security.policynegotiator.INegotiationCallback;
import org.societies.api.internal.security.policynegotiator.INegotiationProviderCallback;
import org.societies.api.osgi.event.EventTypes;
import org.societies.api.privacytrust.privacy.model.PrivacyException;
import org.societies.api.security.digsig.DigsigException;
import org.societies.security.policynegotiator.sla.SLA;
import org.societies.security.policynegotiator.util.ValueGenerator;
import org.societies.security.policynegotiator.xml.Xml;
import org.societies.security.policynegotiator.xml.XmlException;
/**
* This class receives results from async invocations of
* {@link org.societies.api.internal.security.policynegotiator.INegotiationProvider}
*
* @author Mitja Vardjan
*
*/
public class ProviderCallback implements INegotiationProviderCallback {
private static Logger LOG = LoggerFactory.getLogger(ProviderCallback.class);
private NegotiationRequester requester;
private MethodType method;
private Requestor provider;
private INegotiationCallback finalCallback;
private boolean includePrivacyPolicyNegotiation;
public ProviderCallback(NegotiationRequester requester, Requestor provider,
MethodType method, boolean includePrivacyPolicyNegotiation,
INegotiationCallback callback) {
LOG.debug("ProviderCallback({})", method);
this.requester = requester;
this.method = method;
this.provider = provider;
this.finalCallback = callback;
this.includePrivacyPolicyNegotiation = includePrivacyPolicyNegotiation;
// if (method != MethodType.GET_POLICY_OPTIONS) {
// LOG.warn("Wrong constructor is used");
// }
}
/* (non-Javadoc)
* @see org.societies.api.internal.security.policynegotiator.INegotiationProviderCallback
* #receiveExamplesResult(java.lang.Object)
*/
@Override
public void receiveResult(SlaBean result) {
LOG.debug("receiveResult(): method = ", method);
int sessionId = result.getSessionId();
switch(method) {
case GET_POLICY_OPTIONS:
if (result.isSuccess()) {
String sop;
sop = result.getSla();
try {
String selectedSop = selectSopOption(sop);
IIdentity identity = requester.getGroupMgr().getIdMgr().getThisNetworkNode();
sop = requester.getSignatureMgr().signXml(sop, selectedSop, identity);
ProviderCallback callback = new ProviderCallback(requester, provider,
MethodType.ACCEPT_POLICY_AND_GET_SLA, includePrivacyPolicyNegotiation,
finalCallback);
requester.getGroupMgr().acceptPolicyAndGetSla(
sessionId,
sop,
false,
provider.getRequestorId(),
callback);
} catch (XmlException e) {
LOG.warn("receiveResult(): session {}: ", sessionId, e);
} catch (DigsigException e) {
LOG.warn("receiveResult(): session {}: ", sessionId, e);
}
}
break;
case ACCEPT_POLICY_AND_GET_SLA:
if (result.isSuccess()) {
String sla;
sla = result.getSla();
try {
if (requester.getSignatureMgr().verifyXml(sla).size() >= 3) {
LOG.info("receiveResult(): session = {}, final SLA reached.", sessionId);
LOG.debug("receiveResult(): final SLA size: {}", sessionId, sla == null ? null : sla.length());
LOG.debug("receiveResult(): final SLA: {}", sla);
// Store the SLA into secure storage
String agreementKey = generateKey();
requester.getSecureStorage().putDocument(agreementKey, sla.getBytes());
// Get service URL if applicable
List<URI> fileUris = result.getFileUris();
LOG.debug("URLs = {}", fileUris);
if (fileUris != null) {
for (URI u : fileUris) {
LOG.debug("--> URI = {}", u);
}
}
if (includePrivacyPolicyNegotiation) {
if (requester.isPrivacyPolicyNegotiationMgrAvailable()) {
startPrivacyPolicyNegotiation(provider, agreementKey, fileUris);
}
else {
LOG.warn("Privacy Policy Negotiation Manager not available");
finalCallback.onNegotiationError("Privacy Policy Negotiation Manager not available");
}
}
else {
// Notify successful end of negotiation
LOG.debug("invoking final callback.");
finalCallback.onNegotiationComplete(agreementKey, fileUris);
LOG.info("negotiation finished, final callback invoked");
}
}
else {
LOG.warn("receiveResult(): session = {}, final SLA invalid!", sessionId);
}
} catch (DigsigException e) {
LOG.warn("receiveResult(): session = {}, invalid signature!", sessionId);
}
}
break;
case REJECT:
// No need for action.
// After more tests, the method could be changed back to void to save some bandwidth.
LOG.debug("receiveResult(): session = {}, reject success = ", sessionId, result.isSuccess());
break;
}
}
private void startPrivacyPolicyNegotiation(Requestor provider, String agreementKey, List <URI> fileUris) {
IPrivacyPolicyNegotiationManager ppn = requester.getPrivacyPolicyNegotiationManager();
PrivacyPolicyNegotiationListener listener;
String[] eventTypes = new String[] {
EventTypes.FAILED_NEGOTIATION_EVENT,
EventTypes.PRIVACY_POLICY_NEGOTIATION_EVENT};
int id = ValueGenerator.generateUniqueInt();
NegotiationDetails ppnDetails = new NegotiationDetails(provider, id);
listener = new PrivacyPolicyNegotiationListener(finalCallback, agreementKey, fileUris,
requester.getEventMgr(), eventTypes, id);
requester.getEventMgr().subscribeInternalEvent(listener, eventTypes, null);
try {
if (provider instanceof RequestorService) {
RequestorService providerService = (RequestorService) provider;
LOG.debug("startPrivacyPolicyNegotiation([{}; {}])", providerService.getRequestorId(),
providerService.getRequestorServiceId());
ppn.negotiateServicePolicy(ppnDetails);
}
else if (provider instanceof RequestorCis) {
RequestorCis providerCis = (RequestorCis) provider;
LOG.debug("startPrivacyPolicyNegotiation([{}; {}])", providerCis.getRequestorId(),
providerCis.getCisRequestorId());
ppn.negotiateCISPolicy(ppnDetails);
}
else {
LOG.warn("startPrivacyPolicyNegotiation(): unrecognized provider type: {}", provider.getClass().getName());
return;
}
} catch (PrivacyException e) {
LOG.warn("startPrivacyPolicyNegotiation()", e);
return;
}
}
private String selectSopOption(String sopString) throws XmlException {
Xml xml = new Xml(sopString);
SLA sop = new SLA(xml);
String[] sopName = sop.getSopNames();
String[] providerName = new String[sopName.length];
String[] sopContent = new String[sopName.length];
for (int k = 0; k < sopName.length; k++) {
providerName[k] = sop.getProviderName(sopName[k]);
sopContent[k] = sop.getSopContent(sopName[k]);
LOG.debug("selectSopOption(): SOP = {}, provider = {}", sopName[k], providerName[k]);
}
//SopSuitability suitability = new SopSuitability(personalizationMgr);
//suitability.calculateSuitability(preferenceNames, valuesInSop, weights);
return sopName[0]; // FIXME: display all options in a pop-up GUI and return what user has chosen
}
private String generateKey() {
String key;
if (provider instanceof RequestorService) {
RequestorService providerService = (RequestorService) provider;
key = "policy-sla-" + providerService.getRequestorServiceId().getIdentifier().toString();
}
else if (provider instanceof RequestorCis) {
RequestorCis providerCis = (RequestorCis) provider;
key = "policy-cis_membership-" + providerCis.getCisRequestorId().getJid();
}
else {
LOG.warn("generateKey(): unrecognized provider type: {}", provider.getClass().getName());
Random r = new Random();
key = "policy-unknown-" + Long.toString(r.nextLong());
}
return key;
}
}