1 package org.eclipse.aether.connector.basic;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedInputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.nio.Buffer;
28 import java.nio.ByteBuffer;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithm;
38 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
39
40 import static java.util.Objects.requireNonNull;
41
42
43
44
45 final class ChecksumCalculator
46 {
47
48 static class Checksum
49 {
50 final ChecksumAlgorithmFactory checksumAlgorithmFactory;
51
52 ChecksumAlgorithm algorithm;
53
54 Exception error;
55
56 Checksum( ChecksumAlgorithmFactory checksumAlgorithmFactory )
57 {
58 this.checksumAlgorithmFactory = requireNonNull( checksumAlgorithmFactory );
59 this.algorithm = checksumAlgorithmFactory.getAlgorithm();
60 }
61
62 public void reset()
63 {
64 this.algorithm = checksumAlgorithmFactory.getAlgorithm();
65 this.error = null;
66 }
67
68 public void update( ByteBuffer buffer )
69 {
70 this.algorithm.update( buffer );
71 }
72
73 public void error( Exception error )
74 {
75 this.error = error;
76 }
77
78 public Object get()
79 {
80 if ( error != null )
81 {
82 return error;
83 }
84 return algorithm.checksum();
85 }
86
87 }
88
89 private final List<Checksum> checksums;
90
91 private final File targetFile;
92
93 public static ChecksumCalculator newInstance( File targetFile,
94 Collection<ChecksumAlgorithmFactory> checksumAlgorithmFactories )
95 {
96 if ( checksumAlgorithmFactories == null || checksumAlgorithmFactories.isEmpty() )
97 {
98 return null;
99 }
100 return new ChecksumCalculator( targetFile, checksumAlgorithmFactories );
101 }
102
103 private ChecksumCalculator( File targetFile,
104 Collection<ChecksumAlgorithmFactory> checksumAlgorithmFactories )
105 {
106 this.checksums = new ArrayList<>();
107 Set<String> algos = new HashSet<>();
108 for ( ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories )
109 {
110 if ( algos.add( checksumAlgorithmFactory.getName() ) )
111 {
112 this.checksums.add( new Checksum( checksumAlgorithmFactory ) );
113 }
114 }
115 this.targetFile = targetFile;
116 }
117
118 public void init( long dataOffset )
119 {
120 for ( Checksum checksum : checksums )
121 {
122 checksum.reset();
123 }
124 if ( dataOffset <= 0L )
125 {
126 return;
127 }
128
129 try ( InputStream in = new BufferedInputStream( new FileInputStream( targetFile ) ) )
130 {
131 long total = 0;
132 final byte[] buffer = new byte[ 1024 * 32 ];
133 for ( ; total < dataOffset; )
134 {
135 int read = in.read( buffer );
136 if ( read < 0 )
137 {
138 throw new IOException( targetFile + " contains only " + total
139 + " bytes, cannot resume download from offset " + dataOffset );
140 }
141 total += read;
142 if ( total > dataOffset )
143 {
144 read -= total - dataOffset;
145 }
146 update( ByteBuffer.wrap( buffer, 0, read ) );
147 }
148 }
149 catch ( IOException e )
150 {
151 for ( Checksum checksum : checksums )
152 {
153 checksum.error( e );
154 }
155 }
156 }
157
158 public void update( ByteBuffer data )
159 {
160 for ( Checksum checksum : checksums )
161 {
162 ( (Buffer) data ).mark();
163 checksum.update( data );
164 ( (Buffer) data ).reset();
165 }
166 }
167
168 public Map<String, Object> get()
169 {
170 Map<String, Object> results = new HashMap<>();
171 for ( Checksum checksum : checksums )
172 {
173 results.put( checksum.checksumAlgorithmFactory.getName(), checksum.get() );
174 }
175 return results;
176 }
177
178 }