47 |
import java.util.Hashtable; |
import java.util.Hashtable; |
48 |
import java.util.Vector; |
import java.util.Vector; |
49 |
|
|
|
|
|
50 |
import gnu.java.io.ObjectIdentityWrapper; |
import gnu.java.io.ObjectIdentityWrapper; |
51 |
import gnu.java.lang.reflect.TypeSignature; |
import gnu.java.lang.reflect.TypeSignature; |
52 |
import java.lang.reflect.Field; |
import java.lang.reflect.Field; |
98 |
this.blockDataInput = new DataInputStream (this); |
this.blockDataInput = new DataInputStream (this); |
99 |
this.realInputStream = new DataInputStream (in); |
this.realInputStream = new DataInputStream (in); |
100 |
this.nextOID = baseWireHandle; |
this.nextOID = baseWireHandle; |
101 |
this.objectLookupTable = new Hashtable (); |
this.objectLookupTable = new Hashtable(); |
102 |
this.validators = new Vector (); |
this.validators = new Vector(); |
103 |
|
this.classLookupTable = new Hashtable(); |
104 |
setBlockDataMode (true); |
setBlockDataMode (true); |
105 |
readStreamHeader (); |
readStreamHeader(); |
106 |
} |
} |
107 |
|
|
108 |
|
|
203 |
Class cl = resolveProxyClass(intfs); |
Class cl = resolveProxyClass(intfs); |
204 |
setBlockDataMode(oldmode); |
setBlockDataMode(oldmode); |
205 |
|
|
206 |
ObjectStreamClass osc = ObjectStreamClass.lookup(cl); |
ObjectStreamClass osc = lookupClass (cl); |
207 |
assignNewHandle (osc); |
assignNewHandle (osc); |
208 |
|
|
209 |
if (!is_consumed) |
if (!is_consumed) |
332 |
int handle = assignNewHandle (obj); |
int handle = assignNewHandle (obj); |
333 |
this.currentObject = obj; |
this.currentObject = obj; |
334 |
ObjectStreamClass[] hierarchy = |
ObjectStreamClass[] hierarchy = |
335 |
ObjectStreamClass.getObjectStreamClasses (clazz); |
inputGetObjectStreamClasses (clazz); |
336 |
|
|
337 |
for (int i=0; i < hierarchy.length; i++) |
for (int i=0; i < hierarchy.length; i++) |
338 |
{ |
{ |
455 |
new ObjectStreamField (field_name, class_name); |
new ObjectStreamField (field_name, class_name); |
456 |
} |
} |
457 |
|
|
458 |
|
Class clazz = resolveClass (osc); |
459 |
boolean oldmode = setBlockDataMode (true); |
boolean oldmode = setBlockDataMode (true); |
460 |
osc.setClass (resolveClass (osc)); |
osc.setClass (clazz, lookupClass (clazz.getSuperclass())); |
461 |
|
classLookupTable.put (clazz, osc); |
462 |
setBlockDataMode (oldmode); |
setBlockDataMode (oldmode); |
463 |
|
|
464 |
return osc; |
return osc; |
552 |
protected Class resolveClass (ObjectStreamClass osc) |
protected Class resolveClass (ObjectStreamClass osc) |
553 |
throws ClassNotFoundException, IOException |
throws ClassNotFoundException, IOException |
554 |
{ |
{ |
555 |
|
return Class.forName (osc.getName(), true, currentLoader()); |
556 |
|
} |
557 |
|
|
558 |
|
private ClassLoader currentLoader () |
559 |
|
{ |
560 |
SecurityManager sm = System.getSecurityManager (); |
SecurityManager sm = System.getSecurityManager (); |
561 |
if (sm == null) |
if (sm == null) |
562 |
sm = new SecurityManager () {}; |
sm = new SecurityManager () {}; |
563 |
|
|
564 |
|
return currentClassLoader (sm); |
565 |
|
} |
566 |
|
|
567 |
ClassLoader cl = currentClassLoader (sm); |
/** |
568 |
|
* Lookup a class stored in the local hashtable. If it is not |
569 |
|
* use the global lookup function in ObjectStreamClass to build |
570 |
|
* the ObjectStreamClass. This method is requested according to |
571 |
|
* the behaviour detected in the JDK by Kaffe's team. |
572 |
|
* |
573 |
|
* @param clazz Class to lookup in the hash table or for which |
574 |
|
* we must build a descriptor. |
575 |
|
* @return A valid instance of ObjectStreamClass corresponding |
576 |
|
* to the specified class. |
577 |
|
*/ |
578 |
|
private ObjectStreamClass lookupClass (Class clazz) |
579 |
|
{ |
580 |
|
ObjectStreamClass oclazz; |
581 |
|
|
582 |
|
oclazz = (ObjectStreamClass) classLookupTable.get(clazz); |
583 |
|
if (oclazz == null) |
584 |
|
return ObjectStreamClass.lookup (clazz); |
585 |
|
else |
586 |
|
return oclazz; |
587 |
|
} |
588 |
|
|
589 |
if (cl == null) |
/** |
590 |
return Class.forName (osc.getName ()); |
* Reconstruct class hierarchy the same way |
591 |
|
* {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does |
592 |
|
* but using lookupClass instead of ObjectStreamClass.lookup. This |
593 |
|
* dup is necessary localize the lookup table. Hopefully some future rewritings will |
594 |
|
* be able to prevent this. |
595 |
|
* |
596 |
|
* @param clazz This is the class for which we want the hierarchy. |
597 |
|
* |
598 |
|
* @return An array of valid {@link java.io.ObjectStreamClass} instances which |
599 |
|
* represent the class hierarchy for clazz. |
600 |
|
*/ |
601 |
|
private ObjectStreamClass[] inputGetObjectStreamClasses (Class clazz) |
602 |
|
{ |
603 |
|
ObjectStreamClass osc = lookupClass (clazz); |
604 |
|
|
605 |
|
ObjectStreamClass[] ret_val; |
606 |
|
|
607 |
|
if (osc == null) |
608 |
|
return new ObjectStreamClass[0]; |
609 |
else |
else |
610 |
return cl.loadClass (osc.getName ()); |
{ |
611 |
|
Vector oscs = new Vector (); |
612 |
|
|
613 |
|
while (osc != null) |
614 |
|
{ |
615 |
|
oscs.addElement (osc); |
616 |
|
osc = osc.getSuper (); |
617 |
|
} |
618 |
|
|
619 |
|
int count = oscs.size (); |
620 |
|
ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ]; |
621 |
|
|
622 |
|
for (int i = count - 1; i >= 0; i--) |
623 |
|
sorted_oscs[ count - i - 1 ] = (ObjectStreamClass)oscs.elementAt (i); |
624 |
|
|
625 |
|
return sorted_oscs; |
626 |
|
} |
627 |
} |
} |
628 |
|
|
629 |
/** |
/** |
1212 |
throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride"); |
throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride"); |
1213 |
} |
} |
1214 |
|
|
1215 |
// assigns the next availible handle to OBJ |
/** |
1216 |
|
* Assigns the next available handle to <code>obj</code>. |
1217 |
|
* |
1218 |
|
* @param obj The object for which we want a new handle. |
1219 |
|
* @return A valid handle for the specified object. |
1220 |
|
*/ |
1221 |
private int assignNewHandle (Object obj) |
private int assignNewHandle (Object obj) |
1222 |
{ |
{ |
1223 |
this.objectLookupTable.put (new Integer (this.nextOID), |
this.objectLookupTable.put (new Integer (this.nextOID), |
1369 |
{ |
{ |
1370 |
ObjectStreamField[] stream_fields = stream_osc.fields; |
ObjectStreamField[] stream_fields = stream_osc.fields; |
1371 |
ObjectStreamField[] real_fields = |
ObjectStreamField[] real_fields = |
1372 |
ObjectStreamClass.lookup (stream_osc.forClass ()).fields; |
lookupClass (stream_osc.forClass ()).fields; |
1373 |
|
|
1374 |
boolean default_initialize, set_value; |
boolean default_initialize, set_value; |
1375 |
String field_name = null; |
String field_name = null; |
1562 |
} |
} |
1563 |
} |
} |
1564 |
|
|
1565 |
// this native method is used to get access to the protected method |
/** |
1566 |
// of the same name in SecurityManger |
* This native method is used to get access to the protected method |
1567 |
|
* of the same name in SecurityManger. |
1568 |
|
* |
1569 |
|
* @param sm SecurityManager instance which should be called. |
1570 |
|
* @return The current class loader in the calling stack. |
1571 |
|
*/ |
1572 |
private static native ClassLoader currentClassLoader (SecurityManager sm); |
private static native ClassLoader currentClassLoader (SecurityManager sm); |
1573 |
|
|
1574 |
private static Field getField (Class klass, String name) |
private static Field getField (Class klass, String name) |
1575 |
throws java.lang.NoSuchFieldException |
throws java.lang.NoSuchFieldException |
1576 |
{ |
{ |
1577 |
final Field f = klass.getDeclaredField(name); |
final Field f = klass.getDeclaredField(name); |
1578 |
|
|
1579 |
AccessController.doPrivileged(new PrivilegedAction() |
AccessController.doPrivileged(new PrivilegedAction() |
1580 |
{ |
{ |
1581 |
public Object run() |
public Object run() |
1640 |
|
|
1641 |
private native void callConstructor (Class clazz, Object obj); |
private native void callConstructor (Class clazz, Object obj); |
1642 |
|
|
1643 |
|
/** |
1644 |
|
* This method writes a "boolean" value <code>val</code> in the specified field |
1645 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1646 |
|
* |
1647 |
|
* @param obj Instance to setup. |
1648 |
|
* @param klass Class type of the specified instance. |
1649 |
|
* @param field_name Name of the field in the specified class type. |
1650 |
|
* @param val The boolean value to write into the field. |
1651 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1652 |
|
* @throws IOException if there is no field of that name in the specified class. |
1653 |
|
*/ |
1654 |
private void setBooleanField (Object obj, Class klass, String field_name, |
private void setBooleanField (Object obj, Class klass, String field_name, |
1655 |
boolean val) |
boolean val) throws IOException, InvalidClassException |
1656 |
{ |
{ |
1657 |
try |
try |
1658 |
{ |
{ |
1659 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1660 |
f.setBoolean (obj, val); |
f.setBoolean (obj, val); |
1661 |
} |
} |
1662 |
|
catch (IllegalArgumentException _) |
1663 |
|
{ |
1664 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1665 |
|
} |
1666 |
catch (Exception _) |
catch (Exception _) |
1667 |
{ |
{ |
1668 |
} |
} |
1669 |
} |
} |
1670 |
|
|
1671 |
|
/** |
1672 |
|
* This method writes a "byte" value <code>val</code> in the specified field |
1673 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1674 |
|
* |
1675 |
|
* @param obj Instance to setup. |
1676 |
|
* @param klass Class type of the specified instance. |
1677 |
|
* @param field_name Name of the field in the specified class type. |
1678 |
|
* @param val The byte value to write into the field. |
1679 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1680 |
|
* @throws IOException if there is no field of that name in the specified class. |
1681 |
|
*/ |
1682 |
private void setByteField (Object obj, Class klass, String field_name, |
private void setByteField (Object obj, Class klass, String field_name, |
1683 |
byte val) |
byte val) throws IOException, InvalidClassException |
1684 |
{ |
{ |
1685 |
try |
try |
1686 |
{ |
{ |
1687 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1688 |
f.setByte (obj, val); |
f.setByte (obj, val); |
1689 |
} |
} |
1690 |
|
catch (IllegalArgumentException _) |
1691 |
|
{ |
1692 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1693 |
|
} |
1694 |
catch (Exception _) |
catch (Exception _) |
1695 |
{ |
{ |
1696 |
} |
} |
1697 |
} |
} |
1698 |
|
|
1699 |
|
/** |
1700 |
|
* This method writes a "character" value <code>val</code> in the specified field |
1701 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1702 |
|
* |
1703 |
|
* @param obj Instance to setup. |
1704 |
|
* @param klass Class type of the specified instance. |
1705 |
|
* @param field_name Name of the field in the specified class type. |
1706 |
|
* @param val The character value to write into the field. |
1707 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1708 |
|
* @throws IOException if there is no field of that name in the specified class. |
1709 |
|
*/ |
1710 |
private void setCharField (Object obj, Class klass, String field_name, |
private void setCharField (Object obj, Class klass, String field_name, |
1711 |
char val) |
char val) throws IOException, InvalidClassException |
1712 |
{ |
{ |
1713 |
try |
try |
1714 |
{ |
{ |
1715 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1716 |
f.setChar (obj, val); |
f.setChar (obj, val); |
1717 |
} |
} |
1718 |
|
catch (IllegalArgumentException _) |
1719 |
|
{ |
1720 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1721 |
|
} |
1722 |
catch (Exception _) |
catch (Exception _) |
1723 |
{ |
{ |
1724 |
} |
} |
1725 |
} |
} |
1726 |
|
|
1727 |
|
/** |
1728 |
|
* This method writes a "double" value <code>val</code> in the specified field |
1729 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1730 |
|
* |
1731 |
|
* @param obj Instance to setup. |
1732 |
|
* @param klass Class type of the specified instance. |
1733 |
|
* @param field_name Name of the field in the specified class type. |
1734 |
|
* @param val The double value to write into the field. |
1735 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1736 |
|
* @throws IOException if there is no field of that name in the specified class. |
1737 |
|
*/ |
1738 |
private void setDoubleField (Object obj, Class klass, String field_name, |
private void setDoubleField (Object obj, Class klass, String field_name, |
1739 |
double val) |
double val) throws IOException, InvalidClassException |
1740 |
{ |
{ |
1741 |
try |
try |
1742 |
{ |
{ |
1743 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1744 |
f.setDouble (obj, val); |
f.setDouble (obj, val); |
1745 |
} |
} |
1746 |
|
catch (IllegalArgumentException _) |
1747 |
|
{ |
1748 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1749 |
|
} |
1750 |
catch (Exception _) |
catch (Exception _) |
1751 |
{ |
{ |
1752 |
} |
} |
1753 |
} |
} |
1754 |
|
|
1755 |
|
/** |
1756 |
|
* This method writes a "float" value <code>val</code> in the specified field |
1757 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1758 |
|
* |
1759 |
|
* @param obj Instance to setup. |
1760 |
|
* @param klass Class type of the specified instance. |
1761 |
|
* @param field_name Name of the field in the specified class type. |
1762 |
|
* @param val The float value to write into the field. |
1763 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1764 |
|
* @throws IOException if there is no field of that name in the specified class. |
1765 |
|
*/ |
1766 |
private void setFloatField (Object obj, Class klass, String field_name, |
private void setFloatField (Object obj, Class klass, String field_name, |
1767 |
float val) |
float val) throws IOException, InvalidClassException |
1768 |
{ |
{ |
1769 |
try |
try |
1770 |
{ |
{ |
1771 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1772 |
f.setFloat (obj, val); |
f.setFloat (obj, val); |
1773 |
} |
} |
1774 |
|
catch (IllegalArgumentException _) |
1775 |
|
{ |
1776 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1777 |
|
} |
1778 |
catch (Exception _) |
catch (Exception _) |
1779 |
{ |
{ |
1780 |
} |
} |
1781 |
} |
} |
1782 |
|
|
1783 |
|
/** |
1784 |
|
* This method writes an "integer" value <code>val</code> in the specified field |
1785 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1786 |
|
* |
1787 |
|
* @param obj Instance to setup. |
1788 |
|
* @param klass Class type of the specified instance. |
1789 |
|
* @param field_name Name of the field in the specified class type. |
1790 |
|
* @param val The integer value to write into the field. |
1791 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1792 |
|
* @throws IOException if there is no field of that name in the specified class. |
1793 |
|
*/ |
1794 |
private void setIntField (Object obj, Class klass, String field_name, |
private void setIntField (Object obj, Class klass, String field_name, |
1795 |
int val) |
int val) throws IOException, InvalidClassException |
1796 |
{ |
{ |
1797 |
try |
try |
1798 |
{ |
{ |
1799 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1800 |
f.setInt (obj, val); |
f.setInt (obj, val); |
1801 |
} |
} |
1802 |
|
catch (IllegalArgumentException _) |
1803 |
|
{ |
1804 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1805 |
|
} |
1806 |
catch (Exception _) |
catch (Exception _) |
1807 |
{ |
{ |
1808 |
} |
} |
1809 |
} |
} |
1810 |
|
|
1811 |
|
/** |
1812 |
|
* This method writes the long value <code>val</code> in the specified field |
1813 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1814 |
|
* |
1815 |
|
* @param obj Instance to setup. |
1816 |
|
* @param klass Class type of the specified instance. |
1817 |
|
* @param field_name Name of the field in the specified class type. |
1818 |
|
* @param val The long value to write into the field. |
1819 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1820 |
|
* @throws IOException if there is no field of that name in the specified class. |
1821 |
|
*/ |
1822 |
private void setLongField (Object obj, Class klass, String field_name, |
private void setLongField (Object obj, Class klass, String field_name, |
1823 |
long val) |
long val) throws IOException, InvalidClassException |
1824 |
{ |
{ |
1825 |
try |
try |
1826 |
{ |
{ |
1827 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1828 |
f.setLong (obj, val); |
f.setLong (obj, val); |
1829 |
} |
} |
1830 |
|
catch (IllegalArgumentException _) |
1831 |
|
{ |
1832 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1833 |
|
} |
1834 |
catch (Exception _) |
catch (Exception _) |
1835 |
{ |
{ |
1836 |
} |
} |
1837 |
} |
} |
1838 |
|
|
1839 |
|
/** |
1840 |
|
* This method writes a "short" value <code>val</code> in the specified field |
1841 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1842 |
|
* |
1843 |
|
* @param obj Instance to setup. |
1844 |
|
* @param klass Class type of the specified instance. |
1845 |
|
* @param field_name Name of the field in the specified class type. |
1846 |
|
* @param val The short value to write into the field. |
1847 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1848 |
|
* @throws IOException if there is no field of that name in the specified class. |
1849 |
|
*/ |
1850 |
private void setShortField (Object obj, Class klass, String field_name, |
private void setShortField (Object obj, Class klass, String field_name, |
1851 |
short val) |
short val) throws IOException, InvalidClassException |
1852 |
{ |
{ |
1853 |
try |
try |
1854 |
{ |
{ |
1855 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1856 |
f.setShort (obj, val); |
f.setShort (obj, val); |
1857 |
} |
} |
1858 |
|
catch (IllegalArgumentException _) |
1859 |
|
{ |
1860 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1861 |
|
} |
1862 |
catch (Exception _) |
catch (Exception _) |
1863 |
{ |
{ |
1864 |
} |
} |
1865 |
} |
} |
1866 |
|
|
1867 |
|
/** |
1868 |
|
* This method writes an "object" value <code>val</code> in the specified field |
1869 |
|
* of the instance <code>obj</code> of the type <code>klass</code>. |
1870 |
|
* |
1871 |
|
* @param obj Instance to setup. |
1872 |
|
* @param klass Class type of the specified instance. |
1873 |
|
* @param field_name Name of the field in the specified class type. |
1874 |
|
* @param val The "object" value to write into the field. |
1875 |
|
* @throws InvalidClassException if the specified field has not the required type. |
1876 |
|
* @throws IOException if there is no field of that name in the specified class. |
1877 |
|
*/ |
1878 |
private void setObjectField (Object obj, Class klass, String field_name, |
private void setObjectField (Object obj, Class klass, String field_name, |
1879 |
String type_code, Object val) |
String type_code, Object val) throws IOException, InvalidClassException |
1880 |
{ |
{ |
1881 |
try |
try |
1882 |
{ |
{ |
1883 |
Field f = getField (klass, field_name); |
Field f = getField (klass, field_name); |
1884 |
// FIXME: We should check the type_code here |
ObjectStreamField of = new ObjectStreamField(field_name, f.getType()); |
1885 |
f.set (obj, val); |
|
1886 |
|
if (of.getTypeString() == null || |
1887 |
|
!of.getTypeString().equals(type_code)) |
1888 |
|
throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); |
1889 |
|
f.set (obj, val); |
1890 |
} |
} |
1891 |
catch (Exception _) |
catch (InvalidClassException e) |
1892 |
{ |
{ |
1893 |
} |
throw e; |
1894 |
|
} |
1895 |
|
catch (Exception _) |
1896 |
|
{} |
1897 |
} |
} |
1898 |
|
|
1899 |
private static final int BUFFER_SIZE = 1024; |
private static final int BUFFER_SIZE = 1024; |
1915 |
private boolean isDeserializing; |
private boolean isDeserializing; |
1916 |
private boolean fieldsAlreadyRead; |
private boolean fieldsAlreadyRead; |
1917 |
private Vector validators; |
private Vector validators; |
1918 |
|
private Hashtable classLookupTable; |
1919 |
|
|
1920 |
private static boolean dump; |
private static boolean dump; |
1921 |
|
|