Skip to content

Package: Range

Range

nameinstructionbranchcomplexitylinemethod
Range(long, long, long)
M: 0 C: 19
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
canEqual(Object)
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
equals(Object)
M: 14 C: 39
74%
M: 7 C: 7
50%
M: 7 C: 1
13%
M: 0 C: 1
100%
M: 0 C: 1
100%
fromHeader(String, long)
M: 93 C: 8
8%
M: 13 C: 1
7%
M: 7 C: 1
13%
M: 13 C: 3
19%
M: 0 C: 1
100%
full(long)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getEnd()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getLength()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getRegion(Resource)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getStart()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getTotal()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
hashCode()
M: 62 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
subStringOrMinusOne(String, int, int)
M: 13 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
subrange(long)
M: 0 C: 17
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * *********************************************************************************************************************
3: *
4: * blueMarine II: Semantic Media Centre
5: * http://tidalwave.it/projects/bluemarine2
6: *
7: * Copyright (C) 2015 - 2021 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/bluemarine2-src
23: * git clone https://github.com/tidalwave-it/bluemarine2-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.bluemarine2.rest.impl;
28:
29: import javax.annotation.Nonnegative;
30: import javax.annotation.Nonnull;
31: import javax.annotation.Nullable;
32: import java.util.ArrayList;
33: import java.util.List;
34: import org.springframework.core.io.Resource;
35: import org.springframework.core.io.support.ResourceRegion;
36: import lombok.EqualsAndHashCode;
37: import lombok.Getter;
38: import lombok.extern.slf4j.Slf4j;
39:
40: /***********************************************************************************************************************
41: *
42: * @author Fabrizio Giudici
43: *
44: **********************************************************************************************************************/
45:•@Slf4j @Getter @EqualsAndHashCode
46: public class Range
47: {
48: private final long start;
49: private final long end;
50: private final long length;
51: private final long total;
52:
53: /*******************************************************************************************************************
54: *
55: * Construct a byte range.
56: *
57: * @param start start of the byte range.
58: * @param end end of the byte range.
59: * @param total total length of the byte source.
60: *
61: ******************************************************************************************************************/
62: public Range (@Nonnegative final long start, @Nonnegative final long end, @Nonnegative final long total)
63: {
64: this.start = start;
65: this.end = end;
66: this.length = end - start + 1;
67: this.total = total;
68: }
69:
70: /*******************************************************************************************************************
71: *
72: *
73: ******************************************************************************************************************/
74: @Nonnull
75: public static Range full (@Nonnegative final long total)
76: {
77: return new Range(0, total - 1, total);
78: }
79:
80: /*******************************************************************************************************************
81: *
82: *
83: ******************************************************************************************************************/
84: @Nonnull
85: public Range subrange (@Nonnegative final long size)
86: {
87: return new Range(start, Math.min(end, start + size - 1), total);
88: }
89:
90: /*******************************************************************************************************************
91: *
92: * Parses a range from a HTTP header.
93: *
94: * @param rangeHeader the HTTP header
95: * @param total the length of the full datum
96: * @return the range
97: *
98: ******************************************************************************************************************/
99: @Nonnull
100: public static List<Range> fromHeader (@Nullable final String rangeHeader, @Nonnegative final long total)
101: {
102: final List<Range> ranges = new ArrayList<>();
103:
104:• if (rangeHeader != null)
105: {
106: // Range header should match format "bytes=n-n,n-n,n-n...".
107:• if (!rangeHeader.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$"))
108: {
109: throw new IllegalArgumentException("Invalid range: " + rangeHeader);
110: }
111:
112: // If any valid If-Range header, then process each part of byte range.
113:• for (final String part : rangeHeader.substring(6).split(","))
114: {
115: // Assuming a file with length of 100, the following examples returns bytes at:
116: // 50-80 (50 to 80), 40- (40 to length=100), -20 (length-20=80 to length=100).
117: long start = subStringOrMinusOne(part, 0, part.indexOf("-"));
118: long end = subStringOrMinusOne(part, part.indexOf("-") + 1, part.length());
119:
120:• if (start == -1)
121: {
122: start = total - end;
123: end = total - 1;
124: }
125:• else if ((end == -1) || (end > total - 1))
126: {
127: end = total - 1;
128: }
129:
130:• if (start > end)
131: {
132: throw new IllegalArgumentException("Invalid range: " + rangeHeader);
133: }
134:
135: ranges.add(new Range(start, end, total));
136: }
137: }
138:
139: return ranges;
140: }
141:
142: /*******************************************************************************************************************
143: *
144: * Returns a {@link ResourceRegion} mapping the portion of bytes matching this range.
145: *
146: * @param resource the resource
147: * @return the region
148: *
149: ******************************************************************************************************************/
150: @Nonnull
151: public ResourceRegion getRegion (@Nonnull final Resource resource)
152: {
153: return new ResourceRegion(resource, start, length);
154: }
155:
156: /*******************************************************************************************************************
157: *
158: * Returns a substring of the given string value from the given begin index to the given end index as a long. If the
159: * substring is empty, then -1 will be returned
160: *
161: * @param value the string value to return a substring as long for.
162: * @param beginIndex the begin index of the substring to be returned as long.
163: * @param endIndex the end index of the substring to be returned as long.
164: * @return a substring of the given string value as long or -1 if substring is empty.
165: *
166: ******************************************************************************************************************/
167: private static long subStringOrMinusOne (@Nonnull final String value,
168: @Nonnegative final int beginIndex,
169: @Nonnegative final int endIndex)
170: {
171: final String substring = value.substring(beginIndex, endIndex);
172:• return (substring.length() > 0) ? Long.parseLong(substring) : -1;
173: }
174: }
175: