1 /** 2 This file is part of GoldenGate Project (named also GoldenGate or GG). 3 4 Copyright 2009, Frederic Bregier, and individual contributors by the @author 5 tags. See the COPYRIGHT.txt in the distribution for a full listing of 6 individual contributors. 7 8 All GoldenGate Project is free software: you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as published 10 by the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 GoldenGate is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GoldenGate . If not, see <http://www.gnu.org/licenses/>. 20 */ 21 package goldengate.ftp.core.data.handler; 22 23 import goldengate.common.exception.InvalidArgumentException; 24 import goldengate.common.file.DataBlock; 25 import goldengate.ftp.core.command.FtpArgumentCode.TransferStructure; 26 27 import org.jboss.netty.channel.ChannelHandlerContext; 28 import org.jboss.netty.channel.MessageEvent; 29 import org.jboss.netty.channel.SimpleChannelHandler; 30 import org.jboss.netty.channel.ChannelHandler.Sharable; 31 32 /** 33 * Third CODEC :<br> 34 * - encode/decode : takes {@link DataBlock} and transforms it to a 35 * {@link DataBlock}<br> 36 * FILE and RECORD are implemented (DataNetworkHandler will do the real job). 37 * PAGE is not implemented.<br> 38 * Note that real actions are taken in the DataNetworkHandler according to the 39 * implementation of FtpFile. 40 * 41 * @author Frederic Bregier 42 * 43 */ 44 @Sharable 45 public class FtpDataStructureCodec extends SimpleChannelHandler { 46 /* 47 * 3.1.2. DATA STRUCTURES 48 * 49 * In addition to different representation types, FTP allows the structure 50 * of a file to be specified. Three file structures are defined in FTP: 51 * 52 * file-structure, where there is no internal structure and the file is 53 * considered to be a continuous sequence of data bytes, 54 * 55 * record-structure, where the file is made up of sequential records, 56 * 57 * and page-structure, where the file is made up of independent indexed 58 * pages. 59 * 60 * FileInterface-structure is the default to be assumed if the STRUcture 61 * command has not been used but both file and record structures must be 62 * accepted for "text" files (i.e., files with TYPE ASCII or EBCDIC) by all 63 * FTP implementations. The structure of a file will affect both the 64 * transfer mode of a file (see the Section on Transmission Modes) and the 65 * interpretation and storage of the file. 66 * 67 * The "natural" structure of a file will depend on which host stores the 68 * file. A source-code file will usually be stored on an IBM Mainframe in 69 * fixed length records but on a DEC TOPS-20 as a stream of characters 70 * partitioned into lines, for example by <CRLF>. If the transfer of files 71 * between such disparate sites is to be useful, there must be some way for 72 * one site to recognize the other's assumptions about the file. 73 * 74 * With some sites being naturally file-oriented and others naturally 75 * record-oriented there may be problems if a file with one structure is 76 * sent to a host oriented to the other. If a text file is sent with 77 * record-structure to a host which is file oriented, then that host should 78 * apply an internal transformation to the file based on the record 79 * structure. Obviously, this transformation should be useful, but it must 80 * also be invertible so that an identical file may be retrieved using 81 * record structure. 82 * 83 * In the case of a file being sent with file-structure to a record-oriented 84 * host, there exists the question of what criteria the host should use to 85 * divide the file into records which can be processed locally. If this 86 * division is necessary, the FTP implementation should use the end-of-line 87 * sequence, 88 * 89 * <CRLF> for ASCII, or <NL> for EBCDIC text files, as the delimiter. If an 90 * FTP implementation adopts this technique, it must be prepared to reverse 91 * the transformation if the file is retrieved with file-structure. 92 * 93 * 3.1.2.1. FILE STRUCTURE 94 * 95 * FileInterface structure is the default to be assumed if the STRUcture 96 * command has not been used. 97 * 98 * In file-structure there is no internal structure and the file is 99 * considered to be a continuous sequence of data bytes. 100 * 101 * 3.1.2.2. RECORD STRUCTURE 102 * 103 * Record structures must be accepted for "text" files (i.e., files with 104 * TYPE ASCII or EBCDIC) by all FTP implementations. 105 * 106 * In record-structure the file is made up of sequential records. 107 * 108 * 3.1.2.3. PAGE STRUCTURE 109 * 110 * To transmit files that are discontinuous, FTP defines a page structure. 111 * Files of this type are sometimes known as "random access files" or even 112 * as "holey files". In these files there is sometimes other information 113 * associated with the file as a whole (e.g., a file descriptor), or with a 114 * section of the file (e.g., page access controls), or both. In FTP, the 115 * sections of the file are called pages. 116 * 117 * To provide for various page sizes and associated information, each page 118 * is sent with a page header. The page header has the following defined 119 * fields: 120 * 121 * Header Length 122 * 123 * The number of logical bytes in the page header including this byte. The 124 * minimum header length is 4. 125 * 126 * Page Index 127 * 128 * The logical page number of this section of the file. This is not the 129 * transmission sequence number of this page, but the index used to identify 130 * this page of the file. 131 * 132 * Data Length 133 * 134 * The number of logical bytes in the page data. The minimum data length is 135 * 0. 136 * 137 * Page Type 138 * 139 * The type of page this is. The following page types are defined: 140 * 141 * 0 = Last Page 142 * 143 * This is used to indicate the end of a paged structured transmission. The 144 * header length must be 4, and the data length must be 0. 145 * 146 * 1 = Simple Page 147 * 148 * This is the normal type for simple paged files with no page level 149 * associated control information. The header length must be 4. 150 * 151 * 2 = Descriptor Page 152 * 153 * This type is used to transmit the descriptive information for the file as 154 * a whole. 155 * 156 * 3 = Access Controlled Page 157 * 158 * This type includes an additional header field for paged files with page 159 * level access control information. The header length must be 5. 160 * 161 * Optional Fields 162 * 163 * Further header fields may be used to supply per page control information, 164 * for example, per page access control. 165 * 166 * All fields are one logical byte in length. The logical byte size is 167 * specified by the TYPE command. See Appendix I for further details and a 168 * specific case at the page structure. 169 * 170 * A note of caution about parameters: a file must be stored and retrieved 171 * with the same parameters if the retrieved version is to 172 * 173 * be identical to the version originally transmitted. Conversely, FTP 174 * implementations must return a file identical to the original if the 175 * parameters used to store and retrieve a file are the same. 176 */ 177 /** 178 * Structure of transfer 179 */ 180 private TransferStructure structure = null; 181 182 /** 183 * @param structure 184 */ 185 public FtpDataStructureCodec(TransferStructure structure) { 186 super(); 187 this.structure = structure; 188 } 189 190 /** 191 * @return the structure 192 */ 193 public TransferStructure getStructure() { 194 return structure; 195 } 196 197 /** 198 * @param structure 199 * the structure to set 200 */ 201 public void setStructure(TransferStructure structure) { 202 this.structure = structure; 203 } 204 205 /* 206 * (non-Javadoc) 207 * 208 * @see 209 * org.jboss.netty.channel.SimpleChannelHandler#writeRequested(org.jboss 210 * .netty.channel.ChannelHandlerContext, 211 * org.jboss.netty.channel.MessageEvent) 212 */ 213 @Override 214 public void writeRequested(ChannelHandlerContext arg0, MessageEvent arg1) 215 throws Exception { 216 Object o = arg1.getMessage(); 217 if (!(o instanceof DataBlock)) { 218 // Type unimplemented 219 throw new InvalidArgumentException("Wrong object received in " + 220 this.getClass().getName() + " codec " + 221 o.getClass().getName()); 222 } 223 if (structure == TransferStructure.FILE) { 224 super.writeRequested(arg0, arg1); 225 return; 226 } else if (structure == TransferStructure.RECORD) { 227 super.writeRequested(arg0, arg1); 228 return; 229 } 230 // Type unimplemented 231 throw new InvalidArgumentException("Structure unimplemented in " + 232 this.getClass().getName() + " codec " + structure.name()); 233 } 234 235 /* 236 * (non-Javadoc) 237 * 238 * @see 239 * org.jboss.netty.channel.SimpleChannelHandler#messageReceived(org.jboss 240 * .netty.channel.ChannelHandlerContext, 241 * org.jboss.netty.channel.MessageEvent) 242 */ 243 @Override 244 public void messageReceived(ChannelHandlerContext arg0, MessageEvent arg1) 245 throws Exception { 246 Object o = arg1.getMessage(); 247 if (!(o instanceof DataBlock)) { 248 // Type unimplemented 249 throw new InvalidArgumentException("Wrong object received in " + 250 this.getClass().getName() + " codec " + 251 o.getClass().getName()); 252 } 253 if (structure == TransferStructure.FILE) { 254 super.messageReceived(arg0, arg1); 255 return; 256 } else if (structure == TransferStructure.RECORD) { 257 super.messageReceived(arg0, arg1); 258 return; 259 } 260 // Type unimplemented 261 throw new InvalidArgumentException("Structure unimplemented in " + 262 this.getClass().getName() + " codec " + structure.name()); 263 } 264 265 }