1 /** 2 * This file is part of Waarp Project. 3 * 4 * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the 5 * COPYRIGHT.txt in the distribution for a full listing of individual contributors. 6 * 7 * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of 8 * the GNU General Public License as published by the Free Software Foundation, either version 3 of 9 * the License, or (at your option) any later version. 10 * 11 * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even 12 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 13 * Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along with Waarp . If not, see 16 * <http://www.gnu.org/licenses/>. 17 */ 18 package org.waarp.ftp.core.data.handler; 19 20 import java.util.List; 21 22 import io.netty.channel.ChannelHandler.Sharable; 23 import io.netty.channel.ChannelHandlerContext; 24 import io.netty.handler.codec.MessageToMessageCodec; 25 26 import org.waarp.common.exception.InvalidArgumentException; 27 import org.waarp.common.file.DataBlock; 28 import org.waarp.ftp.core.command.FtpArgumentCode.TransferStructure; 29 30 /** 31 * Third CODEC :<br> 32 * - encode/decode : takes {@link DataBlock} and transforms it to a {@link DataBlock}<br> 33 * FILE and RECORD are implemented (DataNetworkHandler will do the real job). PAGE is not 34 * implemented.<br> 35 * Note that real actions are taken in the DataNetworkHandler according to the implementation of 36 * FtpFile. 37 * 38 * @author Frederic Bregier 39 * 40 */ 41 @Sharable 42 class FtpDataStructureCodec extends MessageToMessageCodec<DataBlock, DataBlock> { 43 /* 44 * 3.1.2. DATA STRUCTURES In addition to different representation types, FTP allows the 45 * structure of a file to be specified. Three file structures are defined in FTP: 46 * file-structure, where there is no internal structure and the file is considered to be a 47 * continuous sequence of data bytes, record-structure, where the file is made up of sequential 48 * records, and page-structure, where the file is made up of independent indexed pages. 49 * FileInterface-structure is the default to be assumed if the STRUcture command has not been 50 * used but both file and record structures must be accepted for "text" files (i.e., files with 51 * TYPE ASCII or EBCDIC) by all FTP implementations. The structure of a file will affect both 52 * the transfer mode of a file (see the Section on Transmission Modes) and the interpretation 53 * and storage of the file. The "natural" structure of a file will depend on which host stores 54 * the file. A source-code file will usually be stored on an IBM Mainframe in fixed length 55 * records but on a DEC TOPS-20 as a stream of characters partitioned into lines, for example by 56 * <CRLF>. If the transfer of files between such disparate sites is to be useful, there must be 57 * some way for one site to recognize the other's assumptions about the file. With some sites 58 * being naturally file-oriented and others naturally record-oriented there may be problems if a 59 * file with one structure is sent to a host oriented to the other. If a text file is sent with 60 * record-structure to a host which is file oriented, then that host should apply an internal 61 * transformation to the file based on the record structure. Obviously, this transformation 62 * should be useful, but it must also be invertible so that an identical file may be retrieved 63 * using record structure. In the case of a file being sent with file-structure to a 64 * record-oriented host, there exists the question of what criteria the host should use to 65 * divide the file into records which can be processed locally. If this division is necessary, 66 * the FTP implementation should use the end-of-line sequence, <CRLF> for ASCII, or <NL> for 67 * EBCDIC text files, as the delimiter. If an FTP implementation adopts this technique, it must 68 * be prepared to reverse the transformation if the file is retrieved with file-structure. 69 * 3.1.2.1. FILE STRUCTURE FileInterface structure is the default to be assumed if the STRUcture 70 * command has not been used. In file-structure there is no internal structure and the file is 71 * considered to be a continuous sequence of data bytes. 3.1.2.2. RECORD STRUCTURE Record 72 * structures must be accepted for "text" files (i.e., files with TYPE ASCII or EBCDIC) by all 73 * FTP implementations. In record-structure the file is made up of sequential records. 3.1.2.3. 74 * PAGE STRUCTURE To transmit files that are discontinuous, FTP defines a page structure. Files 75 * of this type are sometimes known as "random access files" or even as "holey files". In these 76 * files there is sometimes other information associated with the file as a whole (e.g., a file 77 * descriptor), or with a section of the file (e.g., page access controls), or both. In FTP, the 78 * sections of the file are called pages. To provide for various page sizes and associated 79 * information, each page is sent with a page header. The page header has the following defined 80 * fields: Header Length The number of logical bytes in the page header including this byte. The 81 * minimum header length is 4. Page Index The logical page number of this section of the file. 82 * This is not the transmission sequence number of this page, but the index used to identify 83 * this page of the file. Data Length The number of logical bytes in the page data. The minimum 84 * data length is 0. Page Type The type of page this is. The following page types are defined: 0 85 * = Last Page This is used to indicate the end of a paged structured transmission. The header 86 * length must be 4, and the data length must be 0. 1 = Simple Page This is the normal type for 87 * simple paged files with no page level associated control information. The header length must 88 * be 4. 2 = Descriptor Page This type is used to transmit the descriptive information for the 89 * file as a whole. 3 = Access Controlled Page This type includes an additional header field for 90 * paged files with page level access control information. The header length must be 5. Optional 91 * Fields Further header fields may be used to supply per page control information, for example, 92 * per page access control. All fields are one logical byte in length. The logical byte size is 93 * specified by the TYPE command. See Appendix I for further details and a specific case at the 94 * page structure. A note of caution about parameters: a file must be stored and retrieved with 95 * the same parameters if the retrieved version is to be identical to the version originally 96 * transmitted. Conversely, FTP implementations must return a file identical to the original if 97 * the parameters used to store and retrieve a file are the same. 98 */ 99 /** 100 * Structure of transfer 101 */ 102 private TransferStructure structure = null; 103 104 /** 105 * @param structure 106 */ 107 public FtpDataStructureCodec(TransferStructure structure) { 108 super(); 109 this.structure = structure; 110 } 111 112 /** 113 * @return the structure 114 */ 115 public TransferStructure getStructure() { 116 return structure; 117 } 118 119 /** 120 * @param structure 121 * the structure to set 122 */ 123 public void setStructure(TransferStructure structure) { 124 this.structure = structure; 125 } 126 127 @Override 128 protected void encode(ChannelHandlerContext ctx, DataBlock msg, List<Object> out) throws Exception { 129 if (structure == TransferStructure.FILE) { 130 out.add(msg); 131 return; 132 } else if (structure == TransferStructure.RECORD) { 133 out.add(msg); 134 return; 135 } 136 // Type unimplemented 137 throw new InvalidArgumentException("Structure unimplemented in " + 138 this.getClass().getName() + " codec " + structure.name()); 139 } 140 141 @Override 142 protected void decode(ChannelHandlerContext ctx, DataBlock msg, List<Object> out) throws Exception { 143 if (structure == TransferStructure.FILE) { 144 out.add(msg); 145 return; 146 } else if (structure == TransferStructure.RECORD) { 147 out.add(msg); 148 return; 149 } 150 // Type unimplemented 151 throw new InvalidArgumentException("Structure unimplemented in " + 152 this.getClass().getName() + " codec " + structure.name()); 153 } 154 155 }