/* * Copyright 1999-2006 University of Chicago * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.dcache.ftp.client.dc; import java.util.Map; import java.util.HashMap; import org.dcache.ftp.client.GridFTPSession; import org.dcache.ftp.client.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractDataChannel implements DataChannel { private static final Logger logger = LoggerFactory.getLogger(AbstractDataChannel.class); protected final Session session; protected static Map dataHandlers; private static final int SOURCE = 1; private static final int SINK = 2; static { try { // Stream [Image/Ascii] Reader and Writer support registerHandler(Session.MODE_STREAM, Session.TYPE_IMAGE, SOURCE, StreamImageDCReader.class); registerHandler(Session.MODE_STREAM, Session.TYPE_ASCII, SOURCE, StreamAsciiDCReader.class); registerHandler(Session.MODE_STREAM, Session.TYPE_IMAGE, SINK, StreamImageDCWriter.class); registerHandler(Session.MODE_STREAM, Session.TYPE_ASCII, SINK, StreamAsciiDCWriter.class); // EBlock registerHandler(GridFTPSession.MODE_EBLOCK, Session.TYPE_IMAGE, SOURCE, EBlockImageDCReader.class); registerHandler(GridFTPSession.MODE_EBLOCK, Session.TYPE_IMAGE, SINK, EBlockImageDCWriter.class); // EBlock ASCII modes not supported } catch (Exception e) { throw new RuntimeException("Failed to install default data channel handlers: " + e.getMessage()); } } public AbstractDataChannel(Session session) { this.session = session; } public static void registerHandler(int transferMode, int transferType, int type, Class clazz) throws Exception { switch (type) { case SOURCE: if (!DataChannelReader.class.isAssignableFrom(clazz)) { throw new Exception("Incorrect type"); } break; case SINK: if (!DataChannelWriter.class.isAssignableFrom(clazz)) { throw new Exception("Incorrect type"); } break; default: throw new IllegalArgumentException("Type not supported: " + type); } String id = getHandlerID(transferMode, transferType, type); if (dataHandlers == null) { dataHandlers = new HashMap(); } // Allow for overwrites /* if (dataHandlers.get(id) != null) { throw new Exception("Handler already registered."); } */ logger.debug("registering handler for class " + clazz.toString() + "; id = " + id); dataHandlers.put(id, clazz); } /** * Tests if the client supports specified transfer type and mode * (the client can read data in specific type & mode from the * data connection) */ public boolean isDataSourceModeSupported() { String id = getHandlerID(session.transferMode, session.transferType, SOURCE); return (dataHandlers.get(id) != null); } /** * Tests if the client supports specified transfer type and mode * (the client can write data in specific type & mode to the * data connection) */ public boolean isDataSinkModeSupported() { String id = getHandlerID(session.transferMode, session.transferType, SINK); return (dataHandlers.get(id) != null); } // currently context is only needed in case of EBlock mode public DataChannelReader getDataChannelSource(TransferContext context) throws Exception { String id = getHandlerID(session.transferMode, session.transferType, SOURCE); logger.debug("type/mode: " + id); Class clazz = (Class) dataHandlers.get(id); if (clazz == null) { throw new Exception("No data reader for type/mode" + id); } DataChannelReader reader = (DataChannelReader) clazz.newInstance(); if (reader instanceof EBlockAware) { ((EBlockAware) reader).setTransferContext((EBlockParallelTransferContext) context); } return reader; } public DataChannelWriter getDataChannelSink(TransferContext context) throws Exception { String id = getHandlerID(session.transferMode, session.transferType, SINK); Class clazz = (Class) dataHandlers.get(id); if (clazz == null) { throw new Exception("No data reader for type/mode"); } DataChannelWriter writer = (DataChannelWriter) clazz.newInstance(); if (writer instanceof EBlockAware) { ((EBlockAware) writer).setTransferContext((EBlockParallelTransferContext) context); } return writer; } // it is important for this method to handle all possible // mode/transfer types private static String getHandlerID(int transferMode, int transferType, int type) { String id = ""; switch (transferMode) { case Session.MODE_STREAM: id += "S-"; break; case GridFTPSession.MODE_EBLOCK: id += "E-"; break; default: throw new IllegalArgumentException("Mode not supported: " + transferMode); } switch (transferType) { case Session.TYPE_IMAGE: id += "I-"; break; case Session.TYPE_ASCII: id += "A-"; break; default: throw new IllegalArgumentException("Type not supported: " + transferType); } switch (type) { case SOURCE: id += "R"; break; case SINK: id += "W"; break; default: throw new IllegalArgumentException("Type not supported: " + type); } if (id.equals("")) { return null; } return id; } }