package org.dcache.pool.classic; import com.google.common.collect.ImmutableMap; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import diskCacheV111.vehicles.ProtocolInfo; import dmg.cells.nucleus.CellArgsAware; import dmg.cells.nucleus.CellCommandListener; import dmg.cells.nucleus.CellEndpoint; import dmg.cells.nucleus.EnvironmentAware; import dmg.util.command.Argument; import dmg.util.command.Command; import org.dcache.pool.movers.MoverProtocol; public class MoverMapTransferService extends AbstractMoverProtocolTransferService implements CellCommandListener, EnvironmentAware { private final ConcurrentMap<String, Class<? extends MoverProtocol>> _movermap = new ConcurrentHashMap<>(); private Map<String,Object> _environment; @Override public void setEnvironment(Map<String,Object> environment) { _environment = ImmutableMap.copyOf(environment); } private Class<? extends MoverProtocol> getMoverProtocolClass(ProtocolInfo info) throws ClassNotFoundException { String protocolName = info.getProtocol() + "-" + info.getMajorVersion(); Class<? extends MoverProtocol> moverClass = _movermap.get(protocolName); if (moverClass == null) { String moverClassName = "org.dcache.pool.movers." + info.getProtocol() + "Protocol_" + info.getMajorVersion(); moverClass = Class.forName(moverClassName).asSubclass(MoverProtocol.class); Class<? extends MoverProtocol> oldClass = _movermap.putIfAbsent(protocolName, moverClass); if (oldClass != null) { moverClass = oldClass; } } return moverClass; } @Override protected MoverProtocol createMoverProtocol(ProtocolInfo info) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException { Class<? extends MoverProtocol> moverClass = getMoverProtocolClass(info); Constructor<? extends MoverProtocol> moverCon = moverClass.getConstructor(CellEndpoint.class); MoverProtocol mover = moverCon.newInstance(getCellEndpoint()); if (mover instanceof EnvironmentAware) { ((EnvironmentAware)mover).setEnvironment(_environment); } if (mover instanceof CellArgsAware) { ((CellArgsAware)mover).setCellArgs(getArgs()); } return mover; } @Command(name = "movermap define", description = "Adds a transfer protocol mapping") class DefineCommand implements Callable<String> { @Argument(index = 0, valueSpec = "PROTOCOL-MAJOR", usage = "Protocol identification string") String protocol; @Argument(index = 1, metaVar = "moverclassname", usage = "A class implementing the MoverProtocol interface.") String moverClassName; @Override public String call() throws ClassNotFoundException { _movermap.put(protocol, Class.forName(moverClassName).asSubclass(MoverProtocol.class)); return ""; } } @Command(name = "movermap undefine", description = "Removes a transfer protocol mapping") class UndefineCommand implements Callable<String> { @Argument(valueSpec = "PROTOCOL-MAJOR", usage = "Protocol identification string") String protocol; @Override public String call() { _movermap.remove(protocol); return ""; } } @Command(name = "movermap ls", description = "Lists all defined protocol mappings.") class ListCommand implements Callable<String> { @Override public String call() throws Exception { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, Class<? extends MoverProtocol>> entry : _movermap.entrySet()) { sb.append(entry.getKey()).append(" -> ").append(entry.getValue().getName()).append("\n"); } return sb.toString(); } } }