package org.dcache.srm.shell; import com.google.common.collect.ImmutableMap; import eu.emi.security.authn.x509.X509Credential; import org.apache.axis.types.URI; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.ServiceLoader; /** * A FileTransferAgent that delegates the actual activity to some other * FileTransferAgent based on Java SPI. This class also supports the * MultiProtocolFileTransfer interface by injecting itself as the * FileTransferAgent the transfer should use. */ public class ExtendableFileTransferAgent implements FileTransferAgent, CredentialAware { private final ServiceLoader<FileTransferAgent> agents = ServiceLoader.load(FileTransferAgent.class); private ImmutableMap<String,FileTransferAgent> _protocolAgent; private ImmutableMap<String,Integer> _protocolPriority; private X509Credential _credential; @Override public void setCredential(X509Credential credential) { _credential = credential; } @Override public String getTransportName() { return "multi-protocol"; } @Override public Map<String,String> getOptions() { Map<String,String> options = new HashMap<>(); for (FileTransferAgent agent : agents) { String name = agent.getTransportName(); if (name != null) { for (Map.Entry<String,String> e : agent.getOptions().entrySet()) { options.put(name+"."+e.getKey(), e.getValue()); } } } return options; } @Override public void setOption(String key, String value) { int index = key.indexOf('.'); if (index == -1 || index == 0 || index == key.length()-1) { throw new IllegalArgumentException("Unknown key: " + key); } String transport = key.substring(0, index); for (FileTransferAgent agent : agents) { if (transport.equals(agent.getTransportName())) { agent.setOption(key.substring(index+1), value); return; } } throw new IllegalArgumentException("Unknown key: " + key); } @Override public void start() { for (FileTransferAgent agent : agents) { if (agent instanceof CredentialAware) { ((CredentialAware)agent).setCredential(_credential); } agent.start(); } buildProtocols(); } private void buildProtocols() { Map<String,FileTransferAgent> protocolAgent = new HashMap<>(); Map<String,Integer> protocolPriority = new HashMap<>(); for (FileTransferAgent agent : agents) { for (Map.Entry<String,Integer> e : agent.getSupportedProtocols().entrySet()) { String protocol = e.getKey(); int priority = e.getValue(); Integer existing = protocolPriority.get(protocol); if (existing == null || existing < priority) { protocolPriority.put(protocol, priority); protocolAgent.put(protocol, agent); } } } _protocolAgent = ImmutableMap.copyOf(protocolAgent); _protocolPriority = ImmutableMap.copyOf(protocolPriority); } @Override public FileTransfer download(URI source, File destination) { FileTransferAgent agent = _protocolAgent.get(source.getScheme()); if (agent == null) { throw new IllegalArgumentException("Scheme " + source.getScheme() + " not supported."); } return agent.download(source, destination); } @Override public FileTransfer upload(File source, URI destination) { FileTransferAgent agent = _protocolAgent.get(destination.getScheme()); if (agent == null) { throw new IllegalArgumentException("Scheme " + destination.getScheme() + " not supported."); } return agent.upload(source, destination); } @Override public void close() throws Exception { for (FileTransferAgent agent : agents) { agent.close(); } } @Override public Map<String,Integer> getSupportedProtocols() { return _protocolPriority; } }