jdk/src/java.base/share/classes/java/net/URL.java
changeset 35280 c607d894f91e
parent 34882 ce2a8ec851c1
child 35381 2545709d9a45
equal deleted inserted replaced
35279:5afd2941dfb7 35280:c607d894f91e
     1 /*
     1 /*
     2  * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    29 import java.io.InputStream;
    29 import java.io.InputStream;
    30 import java.net.spi.URLStreamHandlerProvider;
    30 import java.net.spi.URLStreamHandlerProvider;
    31 import java.security.AccessController;
    31 import java.security.AccessController;
    32 import java.security.PrivilegedAction;
    32 import java.security.PrivilegedAction;
    33 import java.util.Hashtable;
    33 import java.util.Hashtable;
       
    34 import java.io.InvalidObjectException;
       
    35 import java.io.ObjectStreamException;
       
    36 import java.io.ObjectStreamField;
       
    37 import java.io.ObjectInputStream.GetField;
    34 import java.util.Iterator;
    38 import java.util.Iterator;
    35 import java.util.NoSuchElementException;
    39 import java.util.NoSuchElementException;
    36 import java.util.ServiceConfigurationError;
    40 import java.util.ServiceConfigurationError;
    37 import java.util.ServiceLoader;
    41 import java.util.ServiceLoader;
    38 
    42 
   140  * @author  James Gosling
   144  * @author  James Gosling
   141  * @since 1.0
   145  * @since 1.0
   142  */
   146  */
   143 public final class URL implements java.io.Serializable {
   147 public final class URL implements java.io.Serializable {
   144 
   148 
       
   149     static final String BUILTIN_HANDLERS_PREFIX = "sun.net.www.protocol";
   145     static final long serialVersionUID = -7627629688361524110L;
   150     static final long serialVersionUID = -7627629688361524110L;
   146 
   151 
   147     /**
   152     /**
   148      * The property which specifies the package prefix list to be scanned
   153      * The property which specifies the package prefix list to be scanned
   149      * for protocol handlers.  The value of this property (if any) should
   154      * for protocol handlers.  The value of this property (if any) should
   223 
   228 
   224     /* Our hash code.
   229     /* Our hash code.
   225      * @serial
   230      * @serial
   226      */
   231      */
   227     private int hashCode = -1;
   232     private int hashCode = -1;
       
   233 
       
   234     private transient UrlDeserializedState tempState;
   228 
   235 
   229     /**
   236     /**
   230      * Creates a {@code URL} object from the specified
   237      * Creates a {@code URL} object from the specified
   231      * {@code protocol}, {@code host}, {@code port}
   238      * {@code protocol}, {@code host}, {@code port}
   232      * number, and {@code file}.<p>
   239      * number, and {@code file}.<p>
  1352 
  1359 
  1353         return handler;
  1360         return handler;
  1354     }
  1361     }
  1355 
  1362 
  1356     /**
  1363     /**
       
  1364      * @serialField    protocol String
       
  1365      *
       
  1366      * @serialField    host String
       
  1367      *
       
  1368      * @serialField    port int
       
  1369      *
       
  1370      * @serialField    authority String
       
  1371      *
       
  1372      * @serialField    file String
       
  1373      *
       
  1374      * @serialField    ref String
       
  1375      *
       
  1376      * @serialField    hashCode int
       
  1377      *
       
  1378      */
       
  1379     private static final ObjectStreamField[] serialPersistentFields = {
       
  1380         new ObjectStreamField("protocol", String.class),
       
  1381         new ObjectStreamField("host", String.class),
       
  1382         new ObjectStreamField("port", int.class),
       
  1383         new ObjectStreamField("authority", String.class),
       
  1384         new ObjectStreamField("file", String.class),
       
  1385         new ObjectStreamField("ref", String.class),
       
  1386         new ObjectStreamField("hashCode", int.class), };
       
  1387 
       
  1388     /**
  1357      * WriteObject is called to save the state of the URL to an
  1389      * WriteObject is called to save the state of the URL to an
  1358      * ObjectOutputStream. The handler is not saved since it is
  1390      * ObjectOutputStream. The handler is not saved since it is
  1359      * specific to this system.
  1391      * specific to this system.
  1360      *
  1392      *
  1361      * @serialData the default write object value. When read back in,
  1393      * @serialData the default write object value. When read back in,
  1373      * readObject is called to restore the state of the URL from the
  1405      * readObject is called to restore the state of the URL from the
  1374      * stream.  It reads the components of the URL and finds the local
  1406      * stream.  It reads the components of the URL and finds the local
  1375      * stream handler.
  1407      * stream handler.
  1376      */
  1408      */
  1377     private synchronized void readObject(java.io.ObjectInputStream s)
  1409     private synchronized void readObject(java.io.ObjectInputStream s)
  1378          throws IOException, ClassNotFoundException
  1410             throws IOException, ClassNotFoundException {
  1379     {
  1411         GetField gf = s.readFields();
  1380         s.defaultReadObject();  // read the fields
  1412         String protocol = (String)gf.get("protocol", null);
  1381         if ((handler = getURLStreamHandler(protocol)) == null) {
  1413         if (getURLStreamHandler(protocol) == null) {
  1382             throw new IOException("unknown protocol: " + protocol);
  1414             throw new IOException("unknown protocol: " + protocol);
  1383         }
  1415         }
       
  1416         String host = (String)gf.get("host", null);
       
  1417         int port = gf.get("port", -1);
       
  1418         String authority = (String)gf.get("authority", null);
       
  1419         String file = (String)gf.get("file", null);
       
  1420         String ref = (String)gf.get("ref", null);
       
  1421         int hashCode = gf.get("hashCode", -1);
       
  1422         if (authority == null
       
  1423                 && ((host != null && host.length() > 0) || port != -1)) {
       
  1424             if (host == null)
       
  1425                 host = "";
       
  1426             authority = (port == -1) ? host : host + ":" + port;
       
  1427         }
       
  1428         tempState = new UrlDeserializedState(protocol, host, port, authority,
       
  1429                file, ref, hashCode);
       
  1430     }
       
  1431 
       
  1432     /**
       
  1433      * Replaces the de-serialized object with an URL object.
       
  1434      *
       
  1435      * @return a newly created object from deserialized data
       
  1436      *
       
  1437      * @throws ObjectStreamException if a new object replacing this
       
  1438      * object could not be created
       
  1439      */
       
  1440 
       
  1441    private Object readResolve() throws ObjectStreamException {
       
  1442 
       
  1443         URLStreamHandler handler = null;
       
  1444         // already been checked in readObject
       
  1445         handler = getURLStreamHandler(tempState.getProtocol());
       
  1446 
       
  1447         URL replacementURL = null;
       
  1448         if (isBuiltinStreamHandler(handler.getClass().getName())) {
       
  1449             replacementURL = fabricateNewURL();
       
  1450         } else {
       
  1451             replacementURL = setDeserializedFields(handler);
       
  1452         }
       
  1453         return replacementURL;
       
  1454     }
       
  1455 
       
  1456     private URL setDeserializedFields(URLStreamHandler handler) {
       
  1457         URL replacementURL;
       
  1458         String userInfo = null;
       
  1459         String protocol = tempState.getProtocol();
       
  1460         String host = tempState.getHost();
       
  1461         int port = tempState.getPort();
       
  1462         String authority = tempState.getAuthority();
       
  1463         String file = tempState.getFile();
       
  1464         String ref = tempState.getRef();
       
  1465         int hashCode = tempState.getHashCode();
       
  1466 
  1384 
  1467 
  1385         // Construct authority part
  1468         // Construct authority part
  1386         if (authority == null &&
  1469         if (authority == null
  1387             ((host != null && host.length() > 0) || port != -1)) {
  1470             && ((host != null && host.length() > 0) || port != -1)) {
  1388             if (host == null)
  1471             if (host == null)
  1389                 host = "";
  1472                 host = "";
  1390             authority = (port == -1) ? host : host + ":" + port;
  1473             authority = (port == -1) ? host : host + ":" + port;
  1391 
  1474 
  1392             // Handle hosts with userInfo in them
  1475             // Handle hosts with userInfo in them
  1401             if (ind != -1)
  1484             if (ind != -1)
  1402                 userInfo = authority.substring(0, ind);
  1485                 userInfo = authority.substring(0, ind);
  1403         }
  1486         }
  1404 
  1487 
  1405         // Construct path and query part
  1488         // Construct path and query part
  1406         path = null;
  1489         String path = null;
  1407         query = null;
  1490         String query = null;
  1408         if (file != null) {
  1491         if (file != null) {
  1409             // Fix: only do this if hierarchical?
  1492             // Fix: only do this if hierarchical?
  1410             int q = file.lastIndexOf('?');
  1493             int q = file.lastIndexOf('?');
  1411             if (q != -1) {
  1494             if (q != -1) {
  1412                 query = file.substring(q+1);
  1495                 query = file.substring(q+1);
  1413                 path = file.substring(0, q);
  1496                 path = file.substring(0, q);
  1414             } else
  1497             } else
  1415                 path = file;
  1498                 path = file;
  1416         }
  1499         }
       
  1500 
       
  1501         if (port == -1) {
       
  1502             port = 0;
       
  1503         }
       
  1504         // Set the object fields.
       
  1505         this.protocol = protocol;
       
  1506         this.host = host;
       
  1507         this.port = port;
       
  1508         this.file = file;
       
  1509         this.authority = authority;
       
  1510         this.ref = ref;
       
  1511         this.hashCode = hashCode;
       
  1512         this.handler = handler;
       
  1513         this.query = query;
       
  1514         this.path = path;
       
  1515         this.userInfo = userInfo;
       
  1516         replacementURL = this;
       
  1517         return replacementURL;
       
  1518     }
       
  1519 
       
  1520     private URL fabricateNewURL()
       
  1521                 throws InvalidObjectException {
       
  1522         // create URL string from deserialized object
       
  1523         URL replacementURL = null;
       
  1524         String urlString = tempState.reconstituteUrlString();
       
  1525 
       
  1526         try {
       
  1527             replacementURL = new URL(urlString);
       
  1528         } catch (MalformedURLException mEx) {
       
  1529             resetState();
       
  1530             InvalidObjectException invoEx = new InvalidObjectException(
       
  1531                     "Malformed URL:  " + urlString);
       
  1532             invoEx.initCause(mEx);
       
  1533             throw invoEx;
       
  1534         }
       
  1535         replacementURL.setSerializedHashCode(tempState.getHashCode());
       
  1536         resetState();
       
  1537         return replacementURL;
       
  1538     }
       
  1539 
       
  1540     private boolean isBuiltinStreamHandler(String handlerClassName) {
       
  1541         return (handlerClassName.startsWith(BUILTIN_HANDLERS_PREFIX));
       
  1542     }
       
  1543 
       
  1544     private void resetState() {
       
  1545         this.protocol = null;
       
  1546         this.host = null;
       
  1547         this.port = -1;
       
  1548         this.file = null;
       
  1549         this.authority = null;
       
  1550         this.ref = null;
       
  1551         this.hashCode = -1;
       
  1552         this.handler = null;
       
  1553         this.query = null;
       
  1554         this.path = null;
       
  1555         this.userInfo = null;
       
  1556         this.tempState = null;
       
  1557     }
       
  1558 
       
  1559     private void setSerializedHashCode(int hc) {
       
  1560         this.hashCode = hc;
  1417     }
  1561     }
  1418 }
  1562 }
  1419 
  1563 
  1420 class Parts {
  1564 class Parts {
  1421     String path, query, ref;
  1565     String path, query, ref;
  1443 
  1587 
  1444     String getRef() {
  1588     String getRef() {
  1445         return ref;
  1589         return ref;
  1446     }
  1590     }
  1447 }
  1591 }
       
  1592 
       
  1593 final class UrlDeserializedState {
       
  1594     private final String protocol;
       
  1595     private final String host;
       
  1596     private final int port;
       
  1597     private final String authority;
       
  1598     private final String file;
       
  1599     private final String ref;
       
  1600     private final int hashCode;
       
  1601 
       
  1602     public UrlDeserializedState(String protocol,
       
  1603                                 String host, int port,
       
  1604                                 String authority, String file,
       
  1605                                 String ref, int hashCode) {
       
  1606         this.protocol = protocol;
       
  1607         this.host = host;
       
  1608         this.port = port;
       
  1609         this.authority = authority;
       
  1610         this.file = file;
       
  1611         this.ref = ref;
       
  1612         this.hashCode = hashCode;
       
  1613     }
       
  1614 
       
  1615     String getProtocol() {
       
  1616         return protocol;
       
  1617     }
       
  1618 
       
  1619     String getHost() {
       
  1620         return host;
       
  1621     }
       
  1622 
       
  1623     String getAuthority () {
       
  1624         return authority;
       
  1625     }
       
  1626 
       
  1627     int getPort() {
       
  1628         return port;
       
  1629     }
       
  1630 
       
  1631     String getFile () {
       
  1632         return file;
       
  1633     }
       
  1634 
       
  1635     String getRef () {
       
  1636         return ref;
       
  1637     }
       
  1638 
       
  1639     int getHashCode () {
       
  1640         return hashCode;
       
  1641     }
       
  1642 
       
  1643     String reconstituteUrlString() {
       
  1644 
       
  1645         // pre-compute length of StringBuffer
       
  1646         int len = protocol.length() + 1;
       
  1647         if (authority != null && authority.length() > 0)
       
  1648             len += 2 + authority.length();
       
  1649         if (file != null) {
       
  1650             len += file.length();
       
  1651         }
       
  1652         if (ref != null)
       
  1653             len += 1 + ref.length();
       
  1654         StringBuilder result = new StringBuilder(len);
       
  1655         result.append(protocol);
       
  1656         result.append(":");
       
  1657         if (authority != null && authority.length() > 0) {
       
  1658             result.append("//");
       
  1659             result.append(authority);
       
  1660         }
       
  1661         if (file != null) {
       
  1662             result.append(file);
       
  1663         }
       
  1664         if (ref != null) {
       
  1665             result.append("#");
       
  1666             result.append(ref);
       
  1667         }
       
  1668         return result.toString();
       
  1669     }
       
  1670 }