ソースを参照

checked functions, FunctionUtils, CHttpHandler

Ranides Atterwim 10 年 前
コミット
6a7ff06fde

+ 4 - 2
assira/src/main/java/net/ranides/assira/collection/query/CQueryBuilder.java

@@ -16,6 +16,7 @@ import java.util.function.Supplier;
 import java.util.stream.Stream;
 import net.ranides.assira.functional.CheckedFunction;
 import net.ranides.assira.functional.CheckedSupplier;
+import net.ranides.assira.functional.FunctionUtils;
 
 /**
  *
@@ -115,11 +116,12 @@ public class CQueryBuilder<T> {
     }
     
     public static <T> CQuery<T> fromStream(CheckedSupplier<Stream<T>> source) {
-        return new CQueryAbstract.CQIterable<>(() -> source.asSupplier().get().iterator());
+        
+        return new CQueryAbstract.CQIterable<>(() -> FunctionUtils.usupplier(source).get().iterator());
     }
     
     public static <T,P> CQuery<T> fromStream(P param, CheckedFunction<? super P, Stream<T>> source) {
-        return fromIterable(() -> source.asFunction().apply(param).iterator());
+        return fromIterable(() -> FunctionUtils.ufunction(source).apply(param).iterator());
     }
     
     public static <T> CQuery<T> fromCollection(Collection<T> source) {

+ 0 - 15
assira/src/main/java/net/ranides/assira/functional/CheckedConsumer.java

@@ -7,9 +7,6 @@
 
 package net.ranides.assira.functional;
 
-import java.util.function.Consumer;
-import net.ranides.assira.trace.UCException;
-
 /**
  *
  * @author Ranides Atterwim <ranides@gmail.com>
@@ -18,16 +15,4 @@ public interface CheckedConsumer<T> {
 
     void accept(T value) throws Exception;
 
-    default Consumer<T> asConsumer() {
-        return (T value) -> {
-            try {
-                accept(value);
-            } catch(RuntimeException cause) {
-                throw cause;
-            } catch (Exception cause) {
-                throw new UCException(cause);
-            }
-        };
-    }
-    
 }

+ 1 - 13
assira/src/main/java/net/ranides/assira/functional/CheckedFunction.java

@@ -17,17 +17,5 @@ import net.ranides.assira.trace.UCException;
 public interface CheckedFunction<T,R> {
 
     R apply(T t) throws Exception;
-    
-    default Function<T,R> asFunction() {
-        return (T value) -> {
-            try {
-                return apply(value);
-            } catch(RuntimeException cause) {
-                throw cause;
-            } catch (Exception cause) {
-                throw new UCException(cause);
-            }
-        };
-    }
-    
+
 }

+ 0 - 15
assira/src/main/java/net/ranides/assira/functional/CheckedSupplier.java

@@ -7,9 +7,6 @@
 
 package net.ranides.assira.functional;
 
-import java.util.function.Supplier;
-import net.ranides.assira.trace.UCException;
-
 /**
  *
  * @author Ranides Atterwim <ranides@gmail.com>
@@ -18,16 +15,4 @@ public interface CheckedSupplier<T> {
 
     T get() throws Exception;
     
-    default Supplier<T> asSupplier() {
-        return () -> {
-            try {
-                return get();
-            } catch(RuntimeException cause) {
-                throw cause;
-            } catch (Exception cause) {
-                throw new UCException(cause);
-            }
-        };
-    }
-    
 }

+ 87 - 0
assira/src/main/java/net/ranides/assira/functional/FunctionUtils.java

@@ -0,0 +1,87 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.functional;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import net.ranides.assira.trace.ExceptionUtils;
+import net.ranides.assira.trace.UCException;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class FunctionUtils {
+    
+    public static <T> Consumer<T> uconsumer(CheckedConsumer<T> cc) {
+        return (T value) -> {
+            try {
+                cc.accept(value);
+            } catch(RuntimeException cause) {
+                throw cause;
+            } catch (Exception cause) {
+                throw new UCException(cause);
+            }
+        };
+    }
+    
+    public static <T,R> Function<T,R> ufunction(CheckedFunction<T,R> cf) {
+        return (T value) -> {
+            try {
+                return cf.apply(value);
+            } catch(RuntimeException cause) {
+                throw cause;
+            } catch (Exception cause) {
+                throw new UCException(cause);
+            }
+        };
+    }
+    
+    public static <T> Supplier<T> usupplier(CheckedSupplier<T> cs) {
+        return () -> {
+            try {
+                return cs.get();
+            } catch(RuntimeException cause) {
+                throw cause;
+            } catch (Exception cause) {
+                throw new UCException(cause);
+            }
+        };
+    }
+    
+    public static <T> Consumer<T> rconsumer(CheckedConsumer<T> cc) {
+        return (T value) -> {
+            try {
+                cc.accept(value);
+            } catch(Exception cause) {
+                throw ExceptionUtils.rethrow(cause);
+            }
+        };
+    }
+    
+    public static <T,R> Function<T,R> rfunction(CheckedFunction<T,R> cf) {
+        return (T value) -> {
+            try {
+                return cf.apply(value);
+            } catch(Exception cause) {
+                throw ExceptionUtils.rethrow(cause);
+            }
+        };
+    }
+    
+    public static <T> Supplier<T> rsupplier(CheckedSupplier<T> cs) {
+        return () -> {
+            try {
+                return cs.get();
+            } catch(Exception cause) {
+                throw ExceptionUtils.rethrow(cause);
+            }
+        };
+    }
+    
+}

+ 83 - 0
assira/src/main/java/net/ranides/assira/io/IOStreams.java

@@ -174,6 +174,89 @@ public final class IOStreams {
         return thread;
     }
     
+    public static InputStream substream(InputStream istream, long begin, long end) throws IOException {
+        // @todo (assira #1) substream
+        return new SubInput(istream, begin, end);
+    }
+    
+    
+    
+    private static final class SubInput extends FilterInputStream {
+        
+        private final boolean close;
+        private final long max;
+        private long pos;
+        private long mark;
+
+        public SubInput(InputStream in, long begin, long end) throws IOException {
+            this(in, begin, end, true);
+        }
+        
+        public SubInput(InputStream in, long begin, long end, boolean close) throws IOException {
+            super(in);
+            in.skip(begin);
+            this.max = end-begin;
+            this.close = close;
+        }
+
+        @Override
+        public void reset() throws IOException {
+            super.reset();
+            pos = mark;
+        }
+
+        @Override
+        public void mark(int readlimit) {
+            super.mark(readlimit);
+            mark = pos;
+        }
+
+        @Override
+        public void close() throws IOException {
+            if(close) {
+                super.close();
+            }
+        }
+
+        @Override
+        public int available() throws IOException {
+            return Math.max(0, Math.min((int)(max - pos), super.available()));
+        }
+
+        @Override
+        public long skip(long n) throws IOException {
+            if (pos>=max) {
+                return 0;
+            }
+            long r = super.skip( Math.min(n, max-pos) );
+            pos += r;
+            return r;
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            if (pos>=max) {
+                return -1;
+            }
+            int br = super.read(b, off, (int)Math.min(len, max-pos));
+            if(-1 != br) {
+                pos += br;
+            }
+            return br;
+        }
+
+        @Override
+        public int read() throws IOException {
+            if (pos>=max) {
+                return -1;
+            }
+            int cr = super.read();
+            pos += 1;
+            return cr;
+        }
+        
+    }
+    
     private static final class InputObserver extends FilterInputStream {
         
         private final EventListener<? super IOEvent> listener;

+ 1 - 1
assira/src/main/java/net/ranides/assira/io/uri/URIFlags.java

@@ -25,7 +25,7 @@ public enum URIFlags {
     TEXT        (0x0000_0040),
     BINARY      (0x0000_0080),
     SIZE        (0x0000_0100),
-    
+    SEEK        (0x0000_0200),
     ;
     
     private static final Bitmask<URIFlags> MAP = new Bitmask<>(URIFlags.values(), a -> a.mask);

+ 0 - 3
assira/src/main/java/net/ranides/assira/io/uri/URIHandle.java

@@ -11,13 +11,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
-import java.io.Serializable;
 import java.io.Writer;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.nio.charset.Charset;
 import java.nio.file.Path;
-import java.nio.file.attribute.FileTime;
 import java.time.Instant;
 import java.util.Set;
 import net.ranides.assira.collection.query.CQuery;

+ 1 - 3
assira/src/main/java/net/ranides/assira/io/uri/URIHandler.java

@@ -15,11 +15,9 @@ import java.io.Writer;
 import java.net.URI;
 import java.nio.charset.Charset;
 import java.nio.file.Path;
-import java.nio.file.attribute.FileTime;
 import java.time.Instant;
 import java.util.Set;
 import net.ranides.assira.collection.query.CQuery;
-import net.ranides.assira.io.IOStreams;
 
 /**
  *
@@ -56,7 +54,7 @@ public interface URIHandler {
     
     InputStream istream(URIHandle ustream) throws IOException;
     
-    InputStream istream(URIHandle ustream, long offset, long size) throws IOException;
+    InputStream istream(URIHandle ustream, long begin, long end) throws IOException;
     
     OutputStream ostream(URIHandle ustream) throws IOException;
     

+ 2 - 1
assira/src/main/java/net/ranides/assira/io/uri/impl/CFileHandler.java

@@ -81,6 +81,7 @@ public class CFileHandler implements URIHandler {
         if(attr.isRegularFile()) {
             flags.add(URIFlags.FILE);
             flags.add(URIFlags.SIZE);
+            flags.add(URIFlags.SEEK);
         }
         if(Files.isReadable(ustream.path())) {
             flags.add(URIFlags.READABLE);
@@ -138,7 +139,7 @@ public class CFileHandler implements URIHandler {
     }
     
     @Override
-    public InputStream istream(URIHandle ustream, long offset, long size) throws IOException {
+    public InputStream istream(URIHandle ustream, long begin, long end) throws IOException {
         // @todo (assira #1) CFileHandler: istream(offset)
         throw new UnsupportedOperationException("Not supported yet.");
     }

+ 37 - 12
assira/src/main/java/net/ranides/assira/io/uri/impl/CHttpHandler.java

@@ -73,7 +73,7 @@ public class CHttpHandler  implements URIHandler {
 
     @Override
     public Charset charset(URIHandle ustream) throws IOException {
-        return getContentCharset(connect(ustream, "HEAD").getContentType());
+        return getContentCharset(head(ustream).getContentType());
     }
     
 
@@ -81,7 +81,7 @@ public class CHttpHandler  implements URIHandler {
     public Set<URIFlags> flags(URIHandle ustream) throws IOException {
         Set<URIFlags> re = URIFlags.collect(URIFlags.FILE);
         try {
-            HttpURLConnection c = connect(ustream, "HEAD");
+            HttpURLConnection c = head(ustream);
             re.add(URIFlags.READABLE);
             if(2 == (c.getResponseCode() / 100)) {
                 re.add(URIFlags.EXISTS);
@@ -94,6 +94,9 @@ public class CHttpHandler  implements URIHandler {
             if(c.getContentLengthLong() >= 0) {
                 re.add(URIFlags.SIZE);
             }
+            if(StringTraits.contains(c.getHeaderField("Accept-Ranges"), "bytes")) {
+                re.add(URIFlags.SEEK);
+            }
         } catch(IOException cause) {
             // do nothing
         }
@@ -103,14 +106,18 @@ public class CHttpHandler  implements URIHandler {
     @Override
     public Instant time(URIHandle ustream, URITime ut) throws IOException {
         if(ut == URITime.MODIFIED) {
-            return new Date(connect(ustream, "HEAD").getHeaderFieldDate("Last-Modified", 0)).toInstant();
+            HttpURLConnection c = head(ustream);
+            if(null == c.getHeaderField("Last-Modified")) {
+                return Instant.ofEpochMilli(c.getDate());
+            }
+            return new Date(c.getHeaderFieldDate("Last-Modified", 0)).toInstant();
         }
         throw new UnsupportedOperationException(HTTP_NS);
     }
 
     @Override
     public long size(URIHandle ustream) throws IOException {
-        return connect(ustream, "HEAD").getContentLengthLong();
+        return head(ustream).getContentLengthLong();
     }
 
     @Override
@@ -129,25 +136,39 @@ public class CHttpHandler  implements URIHandler {
     }
     
     @Override
-    public InputStream istream(URIHandle ustream, long offset, long size) throws IOException {
-        // @todo (assira #1) CFileHandler: istream(offset)
-        throw new UnsupportedOperationException("Not supported yet.");
+    public InputStream istream(URIHandle ustream, long begin, long end) throws IOException {
+        HttpURLConnection c = connect(ustream);
+        c.setRequestMethod("GET");
+        c.setRequestProperty("Range", "bytes=" + begin + "-" + (end));
+        if (c.getResponseCode() != HttpURLConnection.HTTP_PARTIAL) {
+            // @todo (assira #1) CFileHandler: istream(offset)
+            throw new UnsupportedOperationException("HTTP " + c.getResponseCode());
+        } else {
+            return c.getInputStream();
+        }
     }
 
     @Override
     public OutputStream ostream(URIHandle ustream) throws IOException {
-        return connect(ustream, "PUT").getOutputStream();
+        HttpURLConnection c = connect(ustream);
+        c.setRequestMethod("PUT");
+        c.connect();
+        return c.getOutputStream();
     }
 
     @Override
     public Reader reader(URIHandle ustream) throws IOException {
-        HttpURLConnection c = connect(ustream, "GET");
+        HttpURLConnection c = connect(ustream);
+        c.setRequestMethod("GET");
+        c.connect();
         return new InputStreamReader(c.getInputStream(), getContentCharset(c.getContentType()));
     }
 
     @Override
     public Writer writer(URIHandle ustream) throws IOException {
-        HttpURLConnection c = connect(ustream, "PUT");
+        HttpURLConnection c = connect(ustream);
+        c.setRequestMethod("PUT");
+        c.connect();
         return new OutputStreamWriter(c.getOutputStream(), getContentCharset(c.getContentType()));
     }
 
@@ -175,13 +196,17 @@ public class CHttpHandler  implements URIHandler {
         } 
     }
     
-    private HttpURLConnection connect(URIHandle ustream, String method) throws IOException {
+    private HttpURLConnection head(URIHandle ustream) throws IOException {
         HttpURLConnection c = (HttpURLConnection)((CHttpHandle)ustream).url.openConnection();
-        c.setRequestMethod(method);
+        c.setRequestMethod("HEAD");
         c.connect();
         return c;
     }
     
+    private HttpURLConnection connect(URIHandle ustream) throws IOException {
+        return (HttpURLConnection)((CHttpHandle)ustream).uri.toURL().openConnection();
+    }
+    
     private static Charset getContentCharset(String type) {
         if(null == type) {
             return Charsets.UTF8;

+ 8 - 4
assira/src/main/java/net/ranides/assira/text/StringTraits.java

@@ -41,12 +41,16 @@ public final class StringTraits {
         return c>='0' && c<='9';
     }
     
-    public static boolean starts(String value, String prefix) {
-		return null != value || value.startsWith(prefix);
+    public static boolean starts(String text, String prefix) {
+		return null != text && text.startsWith(prefix);
 	}
     
-    public static boolean ends(String value, String suffix) {
-		return null != value || value.endsWith(suffix);
+    public static boolean ends(String text, String suffix) {
+		return null != text && text.endsWith(suffix);
+	}
+    
+    public static boolean contains(String text, String fragment) {
+		return null != text && text.contains(fragment);
 	}
     
 }

+ 35 - 17
assira/src/test/java/net/ranides/assira/io/uri/impl/CHttpHandlerTest.java

@@ -6,12 +6,13 @@
  */
 package net.ranides.assira.io.uri.impl;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.net.URI;
 import java.net.URISyntaxException;
 import net.ranides.assira.io.uri.URIHandle;
 import net.ranides.assira.io.uri.URIResolver;
 import net.ranides.assira.io.uri.URITime;
+import net.ranides.assira.junit.NewAssert;
 import net.ranides.assira.text.IOStrings;
 import org.junit.Test;
 
@@ -27,27 +28,44 @@ public class CHttpHandlerTest {
     @Test
     public void testSomeMethod() throws IOException, URISyntaxException {
         URIResolver r = new URIResolver().register(CHttpHandler.THAT);
-        URIHandle h1 = r.resolve("http://maven.ranides.net/net/ranides/assira/");
-        URIHandle h2 = r.resolve("http://maven.ranides.net/net/ranides/assira/maven-metadata.xml");
         
+        URIHandle h1 = r.resolve("http://maven.ranides.net/net/ranides/assira/0.58/");
+        System.out.printf("uri     = %s%n", h1.uri());
         System.out.printf("charset = %s%n", h1.charset());
-        System.out.printf("charset = %s%n", h2.charset());
-        
-        System.out.printf("exists = %s%n", h1.exists());
-        System.out.printf("exists = %s%n", h2.exists());
-        
-        System.out.printf("flags = %s%n", h1.flags());
-        System.out.printf("flags = %s%n", h2.flags());
-        
-        System.out.printf("reader = %s%n", IOStrings.read(h1.reader()).length());
-        System.out.printf("reader = %s%n", IOStrings.read(h2.reader()).length());
+        System.out.printf("exists  = %s%n", h1.exists());
+        System.out.printf("flags   = %s%n", h1.flags());
+        System.out.printf("stream  = %s%n", IOStrings.read(h1.istream(10,40), h1.charset()));
+        System.out.printf("reader  = %s%n", IOStrings.read(h1.reader()).length());
+        System.out.printf("time    = %s%n", h1.time(URITime.MODIFIED));
+        System.out.printf("size    = %s%n", h1.size());
+        System.out.printf("%n");
         
-        System.out.printf("time = %s%n", h1.time(URITime.MODIFIED));
-        System.out.printf("time = %s%n", h2.time(URITime.MODIFIED));
+        URIHandle h2 = r.resolve("http://maven.ranides.net/net/ranides/assira/0.58/assira-0.58.pom");
+
+        System.out.printf("uri     = %s%n", h2.uri());        
+        System.out.printf("charset = %s%n", h2.charset());
+        System.out.printf("exists  = %s%n", h2.exists());
+        System.out.printf("flags   = %s%n", h2.flags());
+        System.out.printf("stream  = %s%n", IOStrings.read(h2.istream(10, 15), h2.charset()));
+        System.out.printf("reader  = %s%n", IOStrings.read(h2.reader()).length());
+        System.out.printf("time    = %s%n", h2.time(URITime.MODIFIED));
+        System.out.printf("size    = %s%n", h2.size());
+        System.out.printf("%n");
         
-        System.out.printf("size = %s%n", h1.size());
-        System.out.printf("size = %s%n", h2.size());
+        URIHandle h3 = r.resolve("http://maven.ranides.net/net/ranides/assira/0.58/assira-0.58.po");
         
+        System.out.printf("uri     = %s%n", h3.uri());
+        System.out.printf("charset = %s%n", h3.charset());
+        System.out.printf("exists  = %s%n", h3.exists());
+        System.out.printf("flags   = %s%n", h3.flags());
+        NewAssert.assertThrows(FileNotFoundException.class, ()->{
+            System.out.printf("reader  = %s%n", IOStrings.read(h3.reader()).length());
+        });
+        System.out.printf("time    = %s%n", h3.time(URITime.MODIFIED));
+        System.out.printf("size    = %s%n", h3.size());
+        System.out.printf("%n");
     }
     
+    
+    
 }