158 * can be used to create a {@link URI} from a file path, which can be
159 * converted to URL using {@link URI#toURL()}.
160 * Applications should never try to {@linkplain #URL(String, String, String)
161 * construct} or {@linkplain #URL(String) parse} a {@code URL}
162 * from the direct string representation of a {@code File} or {@code Path}
163 * instance.
164 * <p>
165 * Some components of a URL or URI, such as <i>userinfo</i>, may
166 * be abused to construct misleading URLs or URIs. Applications
167 * that deal with URLs or URIs should take into account
168 * the recommendations advised in <a
169 * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
170 * Section 7, Security Considerations</a>.
171 *
172 * @author James Gosling
173 * @since 1.0
174 */
175 public final class URL implements java.io.Serializable {
176
177 static final String BUILTIN_HANDLERS_PREFIX = "sun.net.www.protocol";
178 static final long serialVersionUID = -7627629688361524110L;
179
180 /**
181 * The property which specifies the package prefix list to be scanned
182 * for protocol handlers. The value of this property (if any) should
183 * be a vertical bar delimited list of package names to search through
184 * for a protocol handler to load. The policy of this class is that
185 * all protocol handlers will be in a class called <protocolname>.Handler,
186 * and each package in the list is examined in turn for a matching
187 * handler. If none are found (or the property is not specified), the
188 * default package prefix, sun.net.www.protocol, is used. The search
189 * proceeds from the first package in the list to the last and stops
190 * when a match is found.
191 */
192 private static final String protocolPathProp = "java.protocol.handler.pkgs";
193
194 /**
195 * The protocol to use (ftp, http, nntp, ... etc.) .
196 * @serial
197 */
1472 }
1473 return handler;
1474 }
1475
1476 /**
1477 * @serialField protocol String
1478 *
1479 * @serialField host String
1480 *
1481 * @serialField port int
1482 *
1483 * @serialField authority String
1484 *
1485 * @serialField file String
1486 *
1487 * @serialField ref String
1488 *
1489 * @serialField hashCode int
1490 *
1491 */
1492 private static final ObjectStreamField[] serialPersistentFields = {
1493 new ObjectStreamField("protocol", String.class),
1494 new ObjectStreamField("host", String.class),
1495 new ObjectStreamField("port", int.class),
1496 new ObjectStreamField("authority", String.class),
1497 new ObjectStreamField("file", String.class),
1498 new ObjectStreamField("ref", String.class),
1499 new ObjectStreamField("hashCode", int.class), };
1500
1501 /**
1502 * WriteObject is called to save the state of the URL to an
1503 * ObjectOutputStream. The handler is not saved since it is
1504 * specific to this system.
1505 *
1506 * @serialData the default write object value. When read back in,
1507 * the reader must ensure that calling getURLStreamHandler with
1508 * the protocol variable returns a valid URLStreamHandler and
1509 * throw an IOException if it does not.
1510 */
1511 private synchronized void writeObject(java.io.ObjectOutputStream s)
1512 throws IOException
1513 {
1514 s.defaultWriteObject(); // write the fields
1515 }
1516
1517 /**
1518 * readObject is called to restore the state of the URL from the
1519 * stream. It reads the components of the URL and finds the local
1520 * stream handler.
1521 */
1522 private synchronized void readObject(java.io.ObjectInputStream s)
1523 throws IOException, ClassNotFoundException {
1524 GetField gf = s.readFields();
1525 String protocol = (String)gf.get("protocol", null);
1526 if (getURLStreamHandler(protocol) == null) {
1527 throw new IOException("unknown protocol: " + protocol);
1528 }
1529 String host = (String)gf.get("host", null);
1530 int port = gf.get("port", -1);
1531 String authority = (String)gf.get("authority", null);
1532 String file = (String)gf.get("file", null);
1533 String ref = (String)gf.get("ref", null);
1534 int hashCode = gf.get("hashCode", -1);
1535 if (authority == null
1536 && ((host != null && !host.isEmpty()) || port != -1)) {
1537 if (host == null)
1538 host = "";
1539 authority = (port == -1) ? host : host + ":" + port;
1540 }
1541 tempState = new UrlDeserializedState(protocol, host, port, authority,
1542 file, ref, hashCode);
1543 }
1544
1545 /**
1546 * Replaces the de-serialized object with an URL object.
1547 *
1548 * @return a newly created object from deserialized data
1549 *
1550 * @throws ObjectStreamException if a new object replacing this
1551 * object could not be created
1552 */
1553
1554 private Object readResolve() throws ObjectStreamException {
1555
1556 URLStreamHandler handler = null;
1557 // already been checked in readObject
1558 handler = getURLStreamHandler(tempState.getProtocol());
1559
1560 URL replacementURL = null;
1561 if (isBuiltinStreamHandler(handler.getClass().getName())) {
1562 replacementURL = fabricateNewURL();
1563 } else {
1564 replacementURL = setDeserializedFields(handler);
1565 }
1566 return replacementURL;
1567 }
1568
1569 private URL setDeserializedFields(URLStreamHandler handler) {
1570 URL replacementURL;
1571 String userInfo = null;
1572 String protocol = tempState.getProtocol();
1573 String host = tempState.getHost();
|
158 * can be used to create a {@link URI} from a file path, which can be
159 * converted to URL using {@link URI#toURL()}.
160 * Applications should never try to {@linkplain #URL(String, String, String)
161 * construct} or {@linkplain #URL(String) parse} a {@code URL}
162 * from the direct string representation of a {@code File} or {@code Path}
163 * instance.
164 * <p>
165 * Some components of a URL or URI, such as <i>userinfo</i>, may
166 * be abused to construct misleading URLs or URIs. Applications
167 * that deal with URLs or URIs should take into account
168 * the recommendations advised in <a
169 * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
170 * Section 7, Security Considerations</a>.
171 *
172 * @author James Gosling
173 * @since 1.0
174 */
175 public final class URL implements java.io.Serializable {
176
177 static final String BUILTIN_HANDLERS_PREFIX = "sun.net.www.protocol";
178 @java.io.Serial
179 static final long serialVersionUID = -7627629688361524110L;
180
181 /**
182 * The property which specifies the package prefix list to be scanned
183 * for protocol handlers. The value of this property (if any) should
184 * be a vertical bar delimited list of package names to search through
185 * for a protocol handler to load. The policy of this class is that
186 * all protocol handlers will be in a class called <protocolname>.Handler,
187 * and each package in the list is examined in turn for a matching
188 * handler. If none are found (or the property is not specified), the
189 * default package prefix, sun.net.www.protocol, is used. The search
190 * proceeds from the first package in the list to the last and stops
191 * when a match is found.
192 */
193 private static final String protocolPathProp = "java.protocol.handler.pkgs";
194
195 /**
196 * The protocol to use (ftp, http, nntp, ... etc.) .
197 * @serial
198 */
1473 }
1474 return handler;
1475 }
1476
1477 /**
1478 * @serialField protocol String
1479 *
1480 * @serialField host String
1481 *
1482 * @serialField port int
1483 *
1484 * @serialField authority String
1485 *
1486 * @serialField file String
1487 *
1488 * @serialField ref String
1489 *
1490 * @serialField hashCode int
1491 *
1492 */
1493 @java.io.Serial
1494 private static final ObjectStreamField[] serialPersistentFields = {
1495 new ObjectStreamField("protocol", String.class),
1496 new ObjectStreamField("host", String.class),
1497 new ObjectStreamField("port", int.class),
1498 new ObjectStreamField("authority", String.class),
1499 new ObjectStreamField("file", String.class),
1500 new ObjectStreamField("ref", String.class),
1501 new ObjectStreamField("hashCode", int.class), };
1502
1503 /**
1504 * WriteObject is called to save the state of the URL to an
1505 * ObjectOutputStream. The handler is not saved since it is
1506 * specific to this system.
1507 *
1508 * @serialData the default write object value. When read back in,
1509 * the reader must ensure that calling getURLStreamHandler with
1510 * the protocol variable returns a valid URLStreamHandler and
1511 * throw an IOException if it does not.
1512 */
1513 @java.io.Serial
1514 private synchronized void writeObject(java.io.ObjectOutputStream s)
1515 throws IOException
1516 {
1517 s.defaultWriteObject(); // write the fields
1518 }
1519
1520 /**
1521 * readObject is called to restore the state of the URL from the
1522 * stream. It reads the components of the URL and finds the local
1523 * stream handler.
1524 */
1525 @java.io.Serial
1526 private synchronized void readObject(java.io.ObjectInputStream s)
1527 throws IOException, ClassNotFoundException {
1528 GetField gf = s.readFields();
1529 String protocol = (String)gf.get("protocol", null);
1530 if (getURLStreamHandler(protocol) == null) {
1531 throw new IOException("unknown protocol: " + protocol);
1532 }
1533 String host = (String)gf.get("host", null);
1534 int port = gf.get("port", -1);
1535 String authority = (String)gf.get("authority", null);
1536 String file = (String)gf.get("file", null);
1537 String ref = (String)gf.get("ref", null);
1538 int hashCode = gf.get("hashCode", -1);
1539 if (authority == null
1540 && ((host != null && !host.isEmpty()) || port != -1)) {
1541 if (host == null)
1542 host = "";
1543 authority = (port == -1) ? host : host + ":" + port;
1544 }
1545 tempState = new UrlDeserializedState(protocol, host, port, authority,
1546 file, ref, hashCode);
1547 }
1548
1549 /**
1550 * Replaces the de-serialized object with an URL object.
1551 *
1552 * @return a newly created object from deserialized data
1553 *
1554 * @throws ObjectStreamException if a new object replacing this
1555 * object could not be created
1556 */
1557 @java.io.Serial
1558 private Object readResolve() throws ObjectStreamException {
1559
1560 URLStreamHandler handler = null;
1561 // already been checked in readObject
1562 handler = getURLStreamHandler(tempState.getProtocol());
1563
1564 URL replacementURL = null;
1565 if (isBuiltinStreamHandler(handler.getClass().getName())) {
1566 replacementURL = fabricateNewURL();
1567 } else {
1568 replacementURL = setDeserializedFields(handler);
1569 }
1570 return replacementURL;
1571 }
1572
1573 private URL setDeserializedFields(URLStreamHandler handler) {
1574 URL replacementURL;
1575 String userInfo = null;
1576 String protocol = tempState.getProtocol();
1577 String host = tempState.getHost();
|