22
33import java .io .Closeable ;
44import java .io .File ;
5+ import java .io .InputStream ;
56import java .io .IOException ;
67import java .io .RandomAccessFile ;
8+ import java .net .URL ;
9+ import java .net .URLConnection ;
710import java .nio .ByteBuffer ;
11+ import java .nio .channels .Channels ;
812import java .nio .channels .FileChannel ;
913import java .nio .channels .FileChannel .MapMode ;
14+ import java .nio .channels .ReadableByteChannel ;
1015
1116import com .maxmind .db .Reader .FileMode ;
1217
1318final class ThreadBuffer extends ThreadLocal <ByteBuffer > implements Closeable {
19+ /**
20+ * Construct a ThreadBuffer from the provided URL.
21+ * @param source the URL that I will read in and use as the source of my
22+ * bytes.
23+ * @return a newly constructed instance based on the contents of your URL.
24+ * @throws IOException if unable to read from your source, or if your
25+ * source does not return all of its contents (short read).
26+ */
27+ public static ThreadBuffer newInstance (URL source ) throws IOException {
28+ final URLConnection conn = source .openConnection ();
29+ conn .connect ();
30+
31+ final InputStream stream = conn .getInputStream ();
32+ final int length = conn .getContentLength ();
33+ final ByteBuffer buffer = ByteBuffer .allocate (length );
34+ final ReadableByteChannel channel = Channels .newChannel (stream );
35+ int bytesRead = 0 ;
36+ while (true ) {
37+ final int br = channel .read (buffer );
38+ if (-1 == br ) {
39+ throw new IOException (String .format (
40+ "Short read from %s, wanted %d got %d" , source , length , bytesRead ));
41+ }
42+ bytesRead += br ;
43+ if (length == bytesRead ) {
44+ break ;
45+ }
46+ }
47+ return new ThreadBuffer (buffer );
48+ }
49+
1450 // DO NOT PASS THESE OUTSIDE THIS CLASS. Doing so will remove thread
1551 // safety.
1652 private final ByteBuffer buffer ;
@@ -49,4 +85,4 @@ public void close() throws IOException {
4985 this .raf .close ();
5086 }
5187 }
52- }
88+ }
0 commit comments