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