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 |
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 } |