diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 7162315e53..d22777dcd1 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -56,6 +56,10 @@ public final class Integer extends Number { return (double) value; } + public static int parseInt(String s) { + return parseInt(s, 10); + } + public static int parseInt(String s, int radix) { return (int) Long.parseLong(s, radix); } diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index 2e50a5aa0d..0238d08d16 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -87,6 +87,10 @@ public final class Long extends Number { return c; } + public static long parseLong(String s) { + return parseLong(s, 10); + } + public static long parseLong(String s, int radix) { long number = 0; diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 65034444bc..2d25a7a060 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -1,19 +1,126 @@ package java.net; +import java.io.IOException; +import java.io.InputStream; + public final class URL { -// private final String protocol; -// private final String host; -// private final int port; -// private final String file; + private final URLStreamHandler handler; + private String protocol; + private String host; + private int port; + private String file; + private String ref; public URL(String s) throws MalformedURLException { -// int colon = s.indexOf(':'); -// int slash = s.indexOf('/'); -// if (colon > 0 && (slash < 0 || colon < slash)) { -// protocol = s.substring(0, colon); -// // todo -// } else { -// throw new MalformedURLException(s); -// } + int colon = s.indexOf(':'); + int slash = s.indexOf('/'); + if (colon > 0 && (slash < 0 || colon < slash)) { + handler = findHandler(s.substring(0, colon)); + handler.parseURL(this, s, colon + 1, s.length()); + } else { + throw new MalformedURLException(s); + } + } + + public String getProtocol() { + return protocol; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getFile() { + return file; + } + + public String getRef() { + return ref; + } + + public URLConnection openConnection() throws IOException { + return handler.openConnection(this); + } + + public Object getContent() throws IOException { + return openConnection().getContent(); + } + + private static URLStreamHandler findHandler(String protocol) + throws MalformedURLException + { + if ("resource".equals(protocol)) { + return new ResourceHandler(); + } else { + throw new MalformedURLException("unknown protocol: " + protocol); + } + } + + protected void set(String protocol, String host, int port, String file, + String ref) + { + this.protocol = protocol; + this.host = host; + this.port = port; + this.file = file; + this.ref = ref; + } + + private static class ResourceHandler extends URLStreamHandler { + protected URLConnection openConnection(URL url) { + return new ResourceConnection(url); + } + } + + private static class ResourceConnection extends URLConnection { + public ResourceConnection(URL url) { + super(url); + } + + public InputStream getInputStream() throws IOException { + return new ResourceInputStream(url.getFile()); + } + } + + private static class ResourceInputStream extends InputStream { + private long peer; + + public ResourceInputStream(String path) throws IOException { + peer = open(path); + } + + private static native long open(String path) throws IOException; + + private static native int read(long peer) throws IOException; + + private static native int read(long peer, byte[] b, int offset, int length) + throws IOException; + + public static native void close(long peer) throws IOException; + + public int read() throws IOException { + return read(peer); + } + + public int read(byte[] b, int offset, int length) throws IOException { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset + length > b.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + return read(peer, b, offset, length); + } + + public void close() throws IOException { + close(peer); + peer = 0; + } } } diff --git a/classpath/java/net/URLConnection.java b/classpath/java/net/URLConnection.java new file mode 100644 index 0000000000..52d0db3df8 --- /dev/null +++ b/classpath/java/net/URLConnection.java @@ -0,0 +1,25 @@ +package java.net; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public abstract class URLConnection { + protected final URL url; + + protected URLConnection(URL url) { + this.url = url; + } + + public Object getContent() throws IOException { + return getInputStream(); + } + + public InputStream getInputStream() throws IOException { + throw new UnknownServiceException(); + } + + public OutputStream getOutputStream() throws IOException { + throw new UnknownServiceException(); + } +} diff --git a/classpath/java/net/URLStreamHandler.java b/classpath/java/net/URLStreamHandler.java new file mode 100644 index 0000000000..8e508d8078 --- /dev/null +++ b/classpath/java/net/URLStreamHandler.java @@ -0,0 +1,69 @@ +package java.net; + +import java.io.IOException; + +public abstract class URLStreamHandler { + protected void parseURL(URL url, String s, int start, int end) { + String protocol = s.substring(0, start - 1); + s = s.substring(start, end); + + String host = null; + int port = -1; + if (s.startsWith("//")) { + s = s.substring(2); + int colon = s.indexOf(':'); + int slash = s.indexOf('/'); + if (slash < 0) { + if (colon < 0) { + host = s; + } else { + host = s.substring(0, colon); + port = Integer.parseInt(s.substring(colon + 1)); + } + s = ""; + } else { + if (colon < 0 || colon > slash) { + host = s.substring(0, slash); + } else { + host = s.substring(0, colon); + port = Integer.parseInt(s.substring(colon + 1), slash); + } + s = s.substring(slash + 1); + } + } + + String file = null; + if (s.length() > 0) { + file = s; + } + + url.set(protocol, host, port, file, null); + } + + private static boolean equals(String a, String b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + protected boolean equals(URL a, URL b) { + return equals(a.getHost(), b.getHost()) + && (a.getPort() == b.getPort()) + && equals(a.getFile(), b.getFile()); + } + + protected String toExternalForm(URL url) { + StringBuilder sb = new StringBuilder(); + sb.append(url.getProtocol()).append("://"); + if (url.getHost() != null) { + sb.append(url.getHost()); + if (url.getPort() >= 0) { + sb.append(":").append(url.getPort()); + } + } + if (url.getFile() != null) { + sb.append("/").append(url.getFile()); + } + return sb.toString(); + } + + protected abstract URLConnection openConnection(URL url) throws IOException; +} diff --git a/classpath/java/net/UnknownServiceException.java b/classpath/java/net/UnknownServiceException.java new file mode 100644 index 0000000000..58ca4acd3c --- /dev/null +++ b/classpath/java/net/UnknownServiceException.java @@ -0,0 +1,13 @@ +package java.net; + +import java.io.IOException; + +public class UnknownServiceException extends IOException { + public UnknownServiceException(String message) { + super(message); + } + + public UnknownServiceException() { + this(null); + } +}