提交 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.
*
* 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}
......@@ -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
* ObjectOutputStream. The handler is not saved since it is
......@@ -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();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册