提交 27c15a8d 编写于 作者: M msheppar

8059054: Better URL processing

Reviewed-by: chegar, rriggs, ahgross, coffeys, igerasim
上级 46a6dd20
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,6 +27,10 @@ package java.net; ...@@ -27,6 +27,10 @@ package java.net;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; 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.Hashtable;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -135,6 +139,7 @@ import sun.security.util.SecurityConstants; ...@@ -135,6 +139,7 @@ import sun.security.util.SecurityConstants;
*/ */
public final class URL implements java.io.Serializable { public final class URL implements java.io.Serializable {
static final String BUILTIN_HANDLERS_PREFIX = "sun.net.www.protocol";
static final long serialVersionUID = -7627629688361524110L; static final long serialVersionUID = -7627629688361524110L;
/** /**
...@@ -219,6 +224,8 @@ public final class URL implements java.io.Serializable { ...@@ -219,6 +224,8 @@ public final class URL implements java.io.Serializable {
*/ */
private int hashCode = -1; private int hashCode = -1;
private transient UrlDeserializedState tempState;
/** /**
* Creates a {@code URL} object from the specified * Creates a {@code URL} object from the specified
* {@code protocol}, {@code host}, {@code port} * {@code protocol}, {@code host}, {@code port}
...@@ -1219,6 +1226,31 @@ public final class URL implements java.io.Serializable { ...@@ -1219,6 +1226,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 * WriteObject is called to save the state of the URL to an
* ObjectOutputStream. The handler is not saved since it is * ObjectOutputStream. The handler is not saved since it is
...@@ -1241,16 +1273,67 @@ public final class URL implements java.io.Serializable { ...@@ -1241,16 +1273,67 @@ public final class URL implements java.io.Serializable {
* stream handler. * stream handler.
*/ */
private synchronized void readObject(java.io.ObjectInputStream s) private synchronized void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException throws IOException, ClassNotFoundException {
{ GetField gf = s.readFields();
s.defaultReadObject(); // read the fields String protocol = (String)gf.get("protocol", null);
if ((handler = getURLStreamHandler(protocol)) == null) { if (getURLStreamHandler(protocol) == null) {
throw new IOException("unknown protocol: " + protocol); 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 // Construct authority part
if (authority == null && if (authority == null
((host != null && host.length() > 0) || port != -1)) { && ((host != null && host.length() > 0) || port != -1)) {
if (host == null) if (host == null)
host = ""; host = "";
authority = (port == -1) ? host : host + ":" + port; authority = (port == -1) ? host : host + ":" + port;
...@@ -1269,8 +1352,8 @@ public final class URL implements java.io.Serializable { ...@@ -1269,8 +1352,8 @@ public final class URL implements java.io.Serializable {
} }
// Construct path and query part // Construct path and query part
path = null; String path = null;
query = null; String query = null;
if (file != null) { if (file != null) {
// Fix: only do this if hierarchical? // Fix: only do this if hierarchical?
int q = file.lastIndexOf('?'); int q = file.lastIndexOf('?');
...@@ -1280,6 +1363,67 @@ public final class URL implements java.io.Serializable { ...@@ -1280,6 +1363,67 @@ public final class URL implements java.io.Serializable {
} else } else
path = file; 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 { ...@@ -1311,3 +1455,82 @@ class Parts {
return ref; 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();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册