/**
* 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.privacytrust.privacyprotection.assessment.util;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.internal.privacytrust.privacyprotection.model.privacyassessment.AssessmentException;
import org.societies.api.internal.servicelifecycle.IServiceDiscovery;
import org.societies.api.internal.servicelifecycle.ServiceModelUtils;
import org.societies.api.schema.servicelifecycle.model.Service;
import org.societies.api.schema.servicelifecycle.model.ServiceResourceIdentifier;
import org.springframework.osgi.context.BundleContextAware;
import org.springframework.osgi.service.ServiceUnavailableException;
/**
* Mapper for Java classes, OSGi bundles, and SOCIETIES 3rd party services.
*
* @author mitjav
*
*/
public class ServiceResolver implements BundleContextAware {
private static Logger LOG = LoggerFactory.getLogger(ServiceResolver.class);
private BundleContext bundleContext;
private IServiceDiscovery serviceDiscovery;
private boolean scanAllBundles;
private Map<String, List<String>> class2bundleMap = new HashMap<String, List<String>>();
public ServiceResolver() {
LOG.debug("constructor()");
}
@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
public void init() {
LOG.debug("init()");
}
/**
* Setter to be called only automatically by Spring dependency injection.
*
* @param serviceDiscovery the serviceDiscovery to set
*/
public void setServiceDiscovery(IServiceDiscovery serviceDiscovery) {
LOG.debug("setServiceDiscovery()");
this.serviceDiscovery = serviceDiscovery;
}
public void setScanAllBundles(boolean scanAllBundles) {
LOG.debug("setScanAllBundles({})", scanAllBundles);
this.scanAllBundles = scanAllBundles;
}
// public String getServiceIdFromBundle(String bundleSymbolicName) {
//
// }
//
// public List<String> getServiceIdFromClass(String className) {
//
// }
public List<String> getBundleSymbolicName(String className) {
LOG.debug("getBundleSymbolicName({})", className);
long startTime = new Date().getTime();
List<String> bundleSymNames = class2bundleMap.get(className);
if (bundleSymNames != null) {
return bundleSymNames;
}
Enumeration<URL> entries;
URL entry;
String cn;
int index;
List<String> result = new ArrayList<String>();
if (bundleContext == null) {
LOG.warn("bundleContext is null. This is OK only if it happened during JUnit test");
return result;
}
if (className == null) {
return result;
}
Bundle[] bundles = bundleContext.getBundles();
//LOG.debug("Number of all bundles: {}", bundles.length);
for (int k = bundles.length - 1; k >= 0; k--) {
//LOG.debug("Getting entries for bundle ID {}: {}", bundle.getBundleId(), bundle.getSymbolicName());
LOG.debug("Bundle ID: {}", bundles[k].getBundleId());
entries = bundles[k].findEntries("/", "*.class", true);
while (entries != null && entries.hasMoreElements()) {
entry = entries.nextElement();
//LOG.debug("Found entry: {}", entry);
cn = entry.toString().replaceFirst("bundleentry://", "");
index = cn.indexOf("/");
if (index > 0) {
if (cn.length() > (index + 1)) {
++index;
}
cn = cn.substring(index);
cn = cn.replaceAll("/", ".");
index = cn.lastIndexOf(".class");
if (index > 0) {
cn = cn.substring(0, index);
}
}
//LOG.debug("Entry class name: {}", cn);
if (className.equals(cn)) {
// Can't get anything better than bundle symbolic name.
// Method Bundle.getLocation() does not return anything user friendly.
LOG.debug("Found matching class name in {}", bundles[k].getSymbolicName());
try {
ServiceResourceIdentifier serviceId;
serviceId = getServiceId(bundles[k]);
result.add(serviceId.getIdentifier().toASCIIString());
} catch (AssessmentException e) {
result.add(bundles[k].getSymbolicName());
}
// Stop searching this bundle and go to next bundle
break;
}
}
if (!result.isEmpty() && !scanAllBundles) {
break;
}
}
if (result.size() > 1) {
LOG.warn("Class {} is present in multiple ({}) bundles", className, result.size());
}
class2bundleMap.put(className, result);
LOG.debug("Stored mapping for class {}. Map size: {}", className, class2bundleMap.size());
LOG.debug("getBundleSymbolicName({}) took {} ms", className, new Date().getTime() - startTime);
return result;
}
private ServiceResourceIdentifier getServiceId(Bundle bundle) throws AssessmentException {
try {
// The proxy is not null even if the service is not available, this
// is used mainly to trigger ServiceUnavailableException
if (serviceDiscovery != null) {
LOG.debug("getServiceId(): Using service discovery to map bundle {} to service ID",
bundle.getSymbolicName());
Service service = ServiceModelUtils.getServiceFromBundle(bundle, serviceDiscovery);
if (service == null) {
throw new AssessmentException("Bundle " + bundle.getSymbolicName() +
" does not seem to be a SOCIETIES 3P service");
}
return service.getServiceIdentifier();
}
else {
LOG.warn("getServiceId(): Service discovery proxy is null.");
throw new AssessmentException("Service discovery proxy is null.");
}
} catch (ServiceUnavailableException e) {
LOG.debug("getServiceId(): Service discovery not available, cannot map bundle {} to service ID",
bundle.getSymbolicName());
throw new AssessmentException("Service discovery not available, cannot map bundle to service ID");
}
}
// public static String getBundleSymbolicName(Class<?> clazz) throws AssessmentException {
//
// Bundle bundle;
//
// if (clazz == null) {
// return null;
// }
//
// try {
// bundle = FrameworkUtil.getBundle(clazz);
// } catch (Exception e) {
// throw new AssessmentException("Could not get bundle information for class " +
// (clazz == null ? null : clazz.getName()));
// }
//
// if (bundle == null) {
// throw new AssessmentException("No OSGi bundle contains class " +
// (clazz == null ? null : clazz.getName()));
// }
// else {
// return bundle.getSymbolicName();
// }
// }
}