/* * 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; import java.util.Vector; import java.util.StringTokenizer; import java.util.NoSuchElementException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Represents GridFTP restart marker, which contains unordered set * of byte ranges representing transferred data. * The ranges are preserved exactly as received * from the server, which may not be very useful. * For additional processing on byte ranges, * use ByteRangeList. * Typical usage: * <pre> * list = new ByteRangeList(); * marker = new GridFTPRestartMarker(reply.getMessage()); * list.merge(marker.getVector()); * </pre> * * @see ByteRangeList **/ public class GridFTPRestartMarker implements Marker { private static Logger logger = LoggerFactory.getLogger(GridFTPRestartMarker.class); final Vector vector; /** * Constructs the restart marker by parsing the parameter string. * * @param msg The string in the format of FTP reply 111 message, * for instance "Range Marker 0-29,30-89" * @throws IllegalArgumentException if the parameter is in bad format **/ public GridFTPRestartMarker(String msg) throws IllegalArgumentException { // expecting msg like "Range Marker 0-29,30-89" vector = new Vector(); StringTokenizer tokens = new StringTokenizer(msg); if (!tokens.hasMoreTokens()) { badMsg("message empty", msg); } if (!tokens.nextToken(" ").equals("Range")) { badMsg("should start with Range Marker", msg); } if (!tokens.nextToken(" ").equals("Marker")) { badMsg("should start with Range Marker", msg); } while (tokens.hasMoreTokens()) { long from = 0; long to = 0; try { String rangeStr = tokens.nextToken(","); StringTokenizer rangeTok = new StringTokenizer(rangeStr, "-"); from = Long.parseLong(rangeTok.nextToken().trim()); to = Long.parseLong(rangeTok.nextToken().trim()); if (rangeTok.hasMoreElements()) { badMsg("A range is followed by '-'", msg); } } catch (NoSuchElementException nse) { // range does not look like "from-to" badMsg("one of the ranges is malformatted", msg); } catch (NumberFormatException nfe) { badMsg("one of the integers is malformatted", msg); } try { vector.add(new ByteRange(from, to)); } catch (IllegalArgumentException iae) { // to < from badMsg("range beginning > range end", msg); } } //vector now contains all ranges if (vector.size() == 0) { badMsg("empty range list", msg); } } private void badMsg(String why, String msg) { throw new IllegalArgumentException( "argument is not FTP 111 reply message (" + why + ": ->" + msg + "<-"); } /** * Returns Vector representation of this object. Its elements * are be ByteRange objects. They are in the order exactly as received * in the FTP reply; no additional processing has been done on them. * To order and merge them, use ByteRangeList. * Subsequent calls of this method will return * the same Vector object. * * @return Vector representation of this object. **/ public Vector toVector() { return vector; } }