package org.gcube.data.spd.remoteplugin; import static org.gcube.data.streams.dsl.Streams.convert; import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.data.spd.Constants; import org.gcube.data.spd.exception.ServiceException; import org.gcube.data.spd.model.Condition; import org.gcube.data.spd.model.Conditions; import org.gcube.data.spd.model.PluginDescription; import org.gcube.data.spd.model.RepositoryInfo; import org.gcube.data.spd.model.binding.Bindings; import org.gcube.data.spd.model.products.ResultItem; import org.gcube.data.spd.model.service.types.SearchCondition; import org.gcube.data.spd.model.util.Capabilities; import org.gcube.data.spd.plugin.fwk.AbstractPlugin; import org.gcube.data.spd.plugin.fwk.capabilities.ClassificationCapability; import org.gcube.data.spd.plugin.fwk.capabilities.ExpansionCapability; import org.gcube.data.spd.plugin.fwk.capabilities.MappingCapability; import org.gcube.data.spd.plugin.fwk.capabilities.OccurrencesCapability; import org.gcube.data.spd.plugin.fwk.capabilities.UnfoldCapability; import org.gcube.data.spd.plugin.fwk.writers.ObjectWriter; import org.gcube.data.streams.Stream; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.thoughtworks.xstream.XStream; public class RemotePlugin extends AbstractPlugin { volatile static Logger logger = LoggerFactory.getLogger(RemotePlugin.class); private ClassificationCapability classification; private MappingCapability mapping; private ExpansionCapability expand; private OccurrencesCapability occurrences; private UnfoldCapability unfold; private String name; private String description; private Set remoteUris = new HashSet(); private RepositoryInfo info; private Set supportedCapabilities = new HashSet(); private static Map cacheGCoreEnpointsRemoteDispatcherPT = new HashMap(); @Override public RepositoryInfo getRepositoryInfo() { return info; } protected static String getRemoteDispatcher(Collection endpointIds) throws ServiceException{ if (endpointIds==null || endpointIds.size()==0) throw new ServiceException("remote service endpoints are empty"); boolean notCachedFound = false; Set uris = new HashSet(); StringBuffer inBuf = new StringBuffer("("); for (String endpointId : endpointIds){ if (cacheGCoreEnpointsRemoteDispatcherPT.containsKey(endpointId)) uris.add(new RemoteUri(endpointId, cacheGCoreEnpointsRemoteDispatcherPT.get(endpointId))); else{ inBuf.append("'").append(endpointId).append("'").append(","); notCachedFound = true; } } if (notCachedFound){ inBuf.replace(inBuf.lastIndexOf(","), inBuf.length(), ")"); try{ SimpleQuery query = queryFor(GCoreEndpoint.class); query.addCondition("$resource/Profile/ServiceName/text() eq '"+Constants.SERVICE_NAME+"'") .addCondition("$resource/Profile/ServiceClass/text() eq '"+Constants.SERVICE_CLASS+"'") .addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'") .addCondition("$resource/ID/text() in "+inBuf.toString()); query.setResult("{$resource/ID/text()}" + "{$resource/Profile/AccessPoint/RunningInstanceInterfaces//Enpoint[@EntryName/text() eq 'remote-dispatcher'][0]}"); DiscoveryClient client = clientFor(RemoteUri.class); List discoveredUris = client.submit(query); for (RemoteUri discoveredUri: discoveredUris){ uris.add(discoveredUri); cacheGCoreEnpointsRemoteDispatcherPT.put(discoveredUri.getEndpointId(), discoveredUri.getUri()); } }catch(Exception e){ logger.warn("error discoverying remote gCoreEnpoints",e); } } for (RemoteUri uri : uris){ try{ return uri.getUri(); }catch(Exception e){ logger.warn("remote dispatcher at "+uri+" is unreachable, it'll be discarded and removed from cache"); cacheGCoreEnpointsRemoteDispatcherPT.remove(uri.getEndpointId()); } } throw new ServiceException("no valid uri found for this remote plugin"); } public void addUrl(String url){ this.remoteUris.add(url); } public void removeUrl(String url){ this.remoteUris.remove(url); } @Override public void searchByScientificName(String word, ObjectWriter writer, Condition... properties) { //transforming properties logger.trace("("+this.getRepositoryName()+" - REMOTE) call arrived in scope "+ScopeProvider.instance.get()); List props = Collections.emptyList(); if (properties!=null && properties.length>0){ props = new ArrayList(properties.length); for (int i = 0 ; i items = convert(URI.create(locator)).ofStrings().withDefaults(); while(items.hasNext()) try{ writer.write((ResultItem) Bindings.fromXml(items.next())); }catch (Exception e) { logger.error("error binding result item",e); } }catch (Exception e) { logger.error("error executing search",e); } } public void remoteIntitializer(PluginDescription pd, String uri) throws Exception{ this.setUseCache(true); this.name = pd.getName(); this.description = pd.getDescription(); this.remoteUris.add(uri); this.info = pd.getInfo(); //adding supported capabilities for (Entry> capabilityDescriptions: pd.getSupportedCapabilities().entrySet()){ Conditions[] properties = capabilityDescriptions.getValue().toArray(new Conditions[capabilityDescriptions.getValue().size()]); switch (capabilityDescriptions.getKey()) { case Classification: this.classification = new RemoteClassificationCapability(properties, this.name, remoteUris); break; case NamesMapping: this.mapping = new RemoteNamesMappingCapability(properties, this.name,remoteUris); break; case Occurrence: this.occurrences = new RemoteOccurrencesCapability(properties, this.name, remoteUris); break; case Expansion: this.expand = new RemoteExpandCapability(properties, this.name, remoteUris); break; case Unfold: this.unfold = new RemoteUnfoldCapability(properties, this.name, remoteUris); break; default: break; } supportedCapabilities.add(capabilityDescriptions.getKey()); } } @Override public ClassificationCapability getClassificationInterface() { return classification; } @Override public OccurrencesCapability getOccurrencesInterface() { return occurrences; } @Override public MappingCapability getMappingInterface() { return mapping; } @Override public ExpansionCapability getExpansionInterface() { return expand; } @Override public UnfoldCapability getUnfoldInterface() { return unfold; } @Override public Set getSupportedCapabilities() { return this.supportedCapabilities; } public boolean isRemote(){ return true; } @Override public String getRepositoryName() { return name; } @Override public String getDescription() { return description; } public Collection getRemoteUris() { return remoteUris; } }