View Javadoc

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 }