View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.common.content.util;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.StringTokenizer;
24  
25  class Range {
26  
27      public long start;
28  
29      public long end;
30  
31      public long length;
32  
33      public static final String RANGE_UNIT = "bytes";
34  
35      public boolean validate() {
36          if (end >= length) {
37              //set 'end' to content size
38              end = length - 1;
39          }
40          return start >= 0 && end >= 0 && start <= end && length > 0;
41      }
42  
43      public static List<Range> parseRanges(final String rangeHeader, long fileLength) throws IllegalArgumentException {
44          if (rangeHeader == null) {
45              return null;
46          }
47  
48          // We operate on byte level only
49          if (!rangeHeader.startsWith(RANGE_UNIT)) {
50              throw new IllegalArgumentException();
51          }
52  
53          String rangeValue = rangeHeader.substring(RANGE_UNIT.length() + 1);
54  
55          final ArrayList<Range> result = new ArrayList<>();
56          final StringTokenizer commaTokenizer = new StringTokenizer(rangeValue, ",");
57  
58          // Parsing the range list
59          long lastByte = 0;
60          while (commaTokenizer.hasMoreTokens()) {
61              final String rangeDefinition = commaTokenizer.nextToken().trim();
62  
63              final Range currentRange = new Range();
64              currentRange.length = fileLength;
65  
66              final int dashPos = rangeDefinition.indexOf('-');
67  
68              if (dashPos == -1) {
69                  throw new IllegalArgumentException();
70              }
71  
72              if (dashPos == 0) {
73  
74                  try {
75                      //offset is negative
76                      final long offset = Long.parseLong(rangeDefinition);
77                      currentRange.start = fileLength + offset;
78                      currentRange.end = fileLength - 1;
79                  } catch (final NumberFormatException e) {
80                      throw new IllegalArgumentException(e);
81                  }
82  
83              } else {
84  
85                  try {
86                      currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos));
87                      if (dashPos < rangeDefinition.length() - 1) {
88                          currentRange.end = Long.parseLong(rangeDefinition.substring(dashPos + 1));
89                      } else {
90                          currentRange.end = fileLength - 1;
91                      }
92                  } catch (final NumberFormatException e) {
93                      throw new IllegalArgumentException(e);
94                  }
95  
96              }
97  
98              if (!currentRange.validate() || lastByte > currentRange.start) {
99                  throw new IllegalArgumentException();
100             }
101             lastByte = currentRange.end;
102             result.add(currentRange);
103         }
104         return result;
105     }
106 }