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  
21  package org.waarp.http.protocol;
22  
23  import org.waarp.common.logging.WaarpLogger;
24  import org.waarp.common.logging.WaarpLoggerFactory;
25  
26  /**
27   * Http Resumable information
28   */
29  public class HttpResumableInfo {
30    private static final WaarpLogger logger =
31        WaarpLoggerFactory.getLogger(HttpResumableInfo.class);
32  
33    private int chunkNumber;
34    private int totalChunks;
35    private int chunkSize;
36    private long totalSize;
37    private String identifier;
38    private String filename;
39    private String relativePath;
40  
41  
42    public HttpResumableInfo(final int chunkNumber, final int chunkSize,
43                             final long totalSize, final String identifier,
44                             final String filename, final String relativePath) {
45      this.chunkNumber = chunkNumber;
46      this.chunkSize = chunkSize;
47      this.totalSize = totalSize;
48      this.identifier = identifier;
49      this.filename = filename;
50      this.relativePath = relativePath;
51      this.totalChunks =
52          (int) Math.ceil(((double) totalSize) / ((double) chunkSize));
53      logger.debug("{} {} {} {} {}", totalSize, chunkSize,
54                   (totalSize) / chunkSize,
55                   (int) Math.ceil(((double) totalSize) / ((double) chunkSize)),
56                   totalChunks);
57    }
58  
59    /**
60     * The original file name (since a bug in Firefox results in the file name
61     * not being transmitted in chunk multipart posts).
62     */
63    public final String getFilename() {
64      return filename;
65    }
66  
67    public final HttpResumableInfo setFilename(final String filename) {
68      this.filename = filename;
69      return this;
70    }
71  
72    /**
73     * The file's relative path when selecting a directory (defaults to file
74     * name in all browsers except Chrome).
75     */
76    public final String getRelativePath() {
77      return relativePath;
78    }
79  
80    public final HttpResumableInfo setRelativePath(final String relativePath) {
81      this.relativePath = relativePath;
82      return this;
83    }
84  
85    /**
86     * @param resumableInfo
87     *
88     * @return True if both HttpResumableInfo are compatible (size, chunk size,
89     *     total number of chunks, identifier and current chunk vs max chunk
90     *     number)
91     */
92    public final boolean isCompatible(final HttpResumableInfo resumableInfo) {
93      return resumableInfo.getChunkSize() == getChunkSize() &&
94             resumableInfo.getTotalSize() == getTotalSize() &&
95             resumableInfo.getIdentifier().equals(getIdentifier()) &&
96             resumableInfo.getTotalChunks() == getTotalChunks() &&
97             resumableInfo.getChunkNumber() <= getTotalChunks();
98    }
99  
100   /**
101    * The general chunk size. Using this value and resumableTotalSize you can
102    * calculate the total number of chunks. Please note that the size of the
103    * data received in the HTTP might be higher than resumableChunkSize for
104    * the last chunk for a file. Max being 2^31, preferably 2^20 (1 MB)
105    */
106   public final int getChunkSize() {
107     return chunkSize;
108   }
109 
110   public final HttpResumableInfo setChunkSize(final int chunkSize) {
111     this.chunkSize = chunkSize;
112     return this;
113   }
114 
115   /**
116    * The total file size. Max being theoretically 2^63, but in practice being
117    * resumableChunkSize x resumableTotalChunks, therefore 2^20 x 2^31 = 2^51
118    */
119   public final long getTotalSize() {
120     return totalSize;
121   }
122 
123   public final HttpResumableInfo setTotalSize(final long totalSize) {
124     this.totalSize = totalSize;
125     return this;
126   }
127 
128   /**
129    * A unique identifier for the file contained in the request.
130    */
131   public final String getIdentifier() {
132     return identifier;
133   }
134 
135   /**
136    * The total number of chunks. Max being 2^31
137    */
138   public final int getTotalChunks() {
139     return totalChunks;
140   }
141 
142   /**
143    * The index of the chunk in the current upload. First chunk is 1 (no
144    * base-0 counting here). Max being 2^31
145    */
146   public final int getChunkNumber() {
147     return chunkNumber;
148   }
149 
150   public final HttpResumableInfo setChunkNumber(final int chunkNumber) {
151     this.chunkNumber = chunkNumber;
152     return this;
153   }
154 
155   public final HttpResumableInfo setTotalChunks(final int totalChunks) {
156     this.totalChunks = totalChunks;
157     return this;
158   }
159 
160   public final HttpResumableInfo setIdentifier(final String identifier) {
161     this.identifier = identifier;
162     return this;
163   }
164 
165   @Override
166   public String toString() {
167     return "RI:{CN:" + chunkNumber + ", TC:" + totalChunks + ", CS:" +
168            chunkSize + ", TS:" + totalSize + ", ID:" + identifier + ", FN:" +
169            filename + ", RP:" + relativePath + "}";
170   }
171 }