diff options
author | msheppar <none@none> | 2015-08-14 17:24:37 +0100 |
---|---|---|
committer | msheppar <none@none> | 2015-08-14 17:24:37 +0100 |
commit | 718dd3db2048688f22f19cbd208068a680e02b08 (patch) | |
tree | b5257cb8398243c4dc820fd2b5eb49c0f008654d /src/share/classes/java/net/URL.java | |
parent | 7bfdaf2880882fa4de8b27da622088fefa147391 (diff) | |
download | jdk8u_jdk-718dd3db2048688f22f19cbd208068a680e02b08.tar.gz |
8059054: Better URL processing
Reviewed-by: chegar, rriggs, ahgross, coffeys, igerasim
Diffstat (limited to 'src/share/classes/java/net/URL.java')
-rw-r--r-- | src/share/classes/java/net/URL.java | 241 |
1 files changed, 232 insertions, 9 deletions
diff --git a/src/share/classes/java/net/URL.java b/src/share/classes/java/net/URL.java index 1ff5d63a35..a6cbcbc4f9 100644 --- a/src/share/classes/java/net/URL.java +++ b/src/share/classes/java/net/URL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,10 @@ package java.net; import java.io.IOException; import java.io.InputStream; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.ObjectStreamField; +import java.io.ObjectInputStream.GetField; import java.util.Hashtable; import java.util.StringTokenizer; import sun.security.util.SecurityConstants; @@ -135,6 +139,7 @@ import sun.security.util.SecurityConstants; */ public final class URL implements java.io.Serializable { + static final String BUILTIN_HANDLERS_PREFIX = "sun.net.www.protocol"; static final long serialVersionUID = -7627629688361524110L; /** @@ -219,6 +224,8 @@ public final class URL implements java.io.Serializable { */ private int hashCode = -1; + private transient UrlDeserializedState tempState; + /** * Creates a {@code URL} object from the specified * {@code protocol}, {@code host}, {@code port} @@ -1220,6 +1227,31 @@ public final class URL implements java.io.Serializable { } /** + * @serialField protocol String + * + * @serialField host String + * + * @serialField port int + * + * @serialField authority String + * + * @serialField file String + * + * @serialField ref String + * + * @serialField hashCode int + * + */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("protocol", String.class), + new ObjectStreamField("host", String.class), + new ObjectStreamField("port", int.class), + new ObjectStreamField("authority", String.class), + new ObjectStreamField("file", String.class), + new ObjectStreamField("ref", String.class), + new ObjectStreamField("hashCode", int.class), }; + + /** * WriteObject is called to save the state of the URL to an * ObjectOutputStream. The handler is not saved since it is * specific to this system. @@ -1241,16 +1273,67 @@ public final class URL implements java.io.Serializable { * stream handler. */ private synchronized void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException - { - s.defaultReadObject(); // read the fields - if ((handler = getURLStreamHandler(protocol)) == null) { + throws IOException, ClassNotFoundException { + GetField gf = s.readFields(); + String protocol = (String)gf.get("protocol", null); + if (getURLStreamHandler(protocol) == null) { throw new IOException("unknown protocol: " + protocol); } + String host = (String)gf.get("host", null); + int port = gf.get("port", -1); + String authority = (String)gf.get("authority", null); + String file = (String)gf.get("file", null); + String ref = (String)gf.get("ref", null); + int hashCode = gf.get("hashCode", -1); + if (authority == null + && ((host != null && host.length() > 0) || port != -1)) { + if (host == null) + host = ""; + authority = (port == -1) ? host : host + ":" + port; + } + tempState = new UrlDeserializedState(protocol, host, port, authority, + file, ref, hashCode); + } + + /** + * Replaces the de-serialized object with an URL object. + * + * @return a newly created object from the deserialzed state. + * + * @throws ObjectStreamException if a new object replacing this + * object could not be created + */ + + private Object readResolve() throws ObjectStreamException { + + URLStreamHandler handler = null; + // already been checked in readObject + handler = getURLStreamHandler(tempState.getProtocol()); + + URL replacementURL = null; + if (isBuiltinStreamHandler(handler.getClass().getName())) { + replacementURL = fabricateNewURL(); + } else { + replacementURL = setDeserializedFields(handler); + } + return replacementURL; + } + + private URL setDeserializedFields(URLStreamHandler handler) { + URL replacementURL; + String userInfo = null; + String protocol = tempState.getProtocol(); + String host = tempState.getHost(); + int port = tempState.getPort(); + String authority = tempState.getAuthority(); + String file = tempState.getFile(); + String ref = tempState.getRef(); + int hashCode = tempState.getHashCode(); + // Construct authority part - if (authority == null && - ((host != null && host.length() > 0) || port != -1)) { + if (authority == null + && ((host != null && host.length() > 0) || port != -1)) { if (host == null) host = ""; authority = (port == -1) ? host : host + ":" + port; @@ -1269,8 +1352,8 @@ public final class URL implements java.io.Serializable { } // Construct path and query part - path = null; - query = null; + String path = null; + String query = null; if (file != null) { // Fix: only do this if hierarchical? int q = file.lastIndexOf('?'); @@ -1280,6 +1363,67 @@ public final class URL implements java.io.Serializable { } else path = file; } + + if (port == -1) { + port = 0; + } + // Set the object fields. + this.protocol = protocol; + this.host = host; + this.port = port; + this.file = file; + this.authority = authority; + this.ref = ref; + this.hashCode = hashCode; + this.handler = handler; + this.query = query; + this.path = path; + this.userInfo = userInfo; + replacementURL = this; + return replacementURL; + } + + private URL fabricateNewURL() + throws InvalidObjectException { + // create URL string from deserialized object + URL replacementURL = null; + String urlString = tempState.reconstituteUrlString(); + + try { + replacementURL = new URL(urlString); + } catch (MalformedURLException mEx) { + resetState(); + InvalidObjectException invoEx = new InvalidObjectException( + "Malformed URL: " + urlString); + invoEx.initCause(mEx); + throw invoEx; + } + replacementURL.setSerializedHashCode(tempState.getHashCode()); + resetState(); + return replacementURL; + } + + private boolean isBuiltinStreamHandler(String handlerClassName) { + return (handlerClassName.startsWith(BUILTIN_HANDLERS_PREFIX)); + } + + private void resetState() { + this.protocol = null; + this.host = null; + this.port = -1; + this.file = null; + this.authority = null; + this.ref = null; + this.hashCode = -1; + this.handler = null; + this.query = null; + this.path = null; + this.userInfo = null; + this.tempState = null; + } + + private void setSerializedHashCode(int hc) { + this.hashCode = hc; } } @@ -1311,3 +1455,82 @@ class Parts { return ref; } } + +final class UrlDeserializedState { + private final String protocol; + private final String host; + private final int port; + private final String authority; + private final String file; + private final String ref; + private final int hashCode; + + public UrlDeserializedState(String protocol, + String host, int port, + String authority, String file, + String ref, int hashCode) { + this.protocol = protocol; + this.host = host; + this.port = port; + this.authority = authority; + this.file = file; + this.ref = ref; + this.hashCode = hashCode; + } + + String getProtocol() { + return protocol; + } + + String getHost() { + return host; + } + + String getAuthority () { + return authority; + } + + int getPort() { + return port; + } + + String getFile () { + return file; + } + + String getRef () { + return ref; + } + + int getHashCode () { + return hashCode; + } + + String reconstituteUrlString() { + + // pre-compute length of StringBuilder + int len = protocol.length() + 1; + if (authority != null && authority.length() > 0) + len += 2 + authority.length(); + if (file != null) { + len += file.length(); + } + if (ref != null) + len += 1 + ref.length(); + StringBuilder result = new StringBuilder(len); + result.append(protocol); + result.append(":"); + if (authority != null && authority.length() > 0) { + result.append("//"); + result.append(authority); + } + if (file != null) { + result.append(file); + } + if (ref != null) { + result.append("#"); + result.append(ref); + } + return result.toString(); + } +} |