/** * * Copyright 2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.geronimo.interop.rmi.iiop; import java.io.*; import java.util.*; import java.lang.reflect.*; /** ** An implementation of java.io.ObjectInputStream.GetField ** Provide access to the persistent fields read from the input stream. **/ public class GetField extends java.io.ObjectInputStream.GetField { /** class descriptor describing serializable fields */ private final ObjectStreamClass desc; /** primitive field values */ private final byte[] primVals; /** object field values */ private final Object[] objVals; /** object field value handles */ private final int[] objHandles; private int primDataSize = 0; private int numObjFields = 0; private ObjectStreamField[] _fields = null; private static Method setOffsetMethod; static { try { Class osFieldClass = java.io.ObjectStreamField.class; Class[] params = new Class[1]; params[0] = int.class; setOffsetMethod = osFieldClass.getDeclaredMethod("setOffset", params); setOffsetMethod.setAccessible(true); } catch (Throwable t) { t.printStackTrace(); } } /** * Creates GetFieldImpl object for reading fields defined in given * class descriptor. */ GetField(ObjectStreamClass desc) { this.desc = desc; computeOffsets(); primVals = new byte[primDataSize]; objVals = new Object[numObjFields]; objHandles = new int[objVals.length]; } /** * Get the ObjectStreamClass that describes the fields in the stream. * * @return the descriptor class that describes the serializable fields */ public ObjectStreamClass getObjectStreamClass() { return desc; } /** * Return true if the named field is defaulted and has no value in this * stream. * * @param name the name of the field * @return true, if and only if the named field is defaulted * @throws IOException if there are I/O errors while reading from * the underlying <code>InputStream</code> * @throws IllegalArgumentException if <code>name</code> does not * correspond to a serializable field */ public boolean defaulted(String name) throws IOException { int fieldOffset = getFieldOffset(name, null); boolean result; if(fieldOffset < 0) { result = false; } else { result = true; } return result; } /** * Get the value of the named boolean field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>boolean</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public boolean get(String name, boolean val) throws IOException { int off = getFieldOffset(name, Boolean.TYPE); return (off >= 0) ? Bits.getBoolean(primVals, off) : val; } /** * Get the value of the named byte field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>byte</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public byte get(String name, byte val) throws IOException { int off = getFieldOffset(name, Byte.TYPE); return (off >= 0) ? primVals[off] : val; } /** * Get the value of the named char field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>char</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public char get(String name, char val) throws IOException { int off = getFieldOffset(name, Character.TYPE); return (off >= 0) ? Bits.getChar(primVals, off) : val; } /** * Get the value of the named short field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>short</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public short get(String name, short val) throws IOException { int off = getFieldOffset(name, Short.TYPE); return (off >= 0) ? Bits.getShort(primVals, off) : val; } /** * Get the value of the named int field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>int</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public int get(String name, int val) throws IOException { int off = getFieldOffset(name, Integer.TYPE); return (off >= 0) ? Bits.getInt(primVals, off) : val; } /** * Get the value of the named long field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>long</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public long get(String name, long val) throws IOException { int off = getFieldOffset(name, Long.TYPE); return (off >= 0) ? Bits.getLong(primVals, off) : val; } /** * Get the value of the named float field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>float</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public float get(String name, float val) throws IOException { int off = getFieldOffset(name, Float.TYPE); return (off >= 0) ? Bits.getFloat(primVals, off) : val; } /** * Get the value of the named double field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>double</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public double get(String name, double val) throws IOException { int off = getFieldOffset(name, Double.TYPE); return (off >= 0) ? Bits.getDouble(primVals, off) : val; } /** * Get the value of the named Object field from the persistent field. * * @param name the name of the field * @param val the default value to use if <code>name</code> does not * have a value * @return the value of the named <code>Object</code> field * @throws IOException if there are I/O errors while reading from the * underlying <code>InputStream</code> * @throws IllegalArgumentException if type of <code>name</code> is * not serializable or if the field type is incorrect */ public Object get(String name, Object val) throws IOException { int off = getFieldOffset(name, Object.class); if (off >= 0) { return objVals[off]; } else { return val; } } /** * Reads primitive and object field values from stream. */ void readFields(ObjectInputStream oi) throws IOException { org.apache.geronimo.interop.rmi.iiop.ObjectInputStream in = (org.apache.geronimo.interop.rmi.iiop.ObjectInputStream)oi; in._cdrInput.read_align(4, 4); //Read in primitive values first for(int i = 0; i < primVals.length; i++) { primVals[i] = in.readByte(); } //Read in the object fields java.io.ObjectStreamField[] fields = desc.getFields(); int numPrimFields = fields.length - objVals.length; for (int i = 0; i < objVals.length; i++) { objVals[i] = in.readObject(ValueType.getInstance(fields[numPrimFields + i].getType())); } } private int getFieldOffset(String name, Class type) { ObjectStreamField field = getField(name, type); if (field == null) { throw new IllegalArgumentException("no such field: " + name + " of type: " + type.getName()); } return field.getOffset(); } private ObjectStreamField getField(String name, Class type) { if(type == null) { //Return match by name for(int i = 0; i < _fields.length; i++) { if(_fields[i].getName().equals(name)) { return _fields[i]; } } return (ObjectStreamField)null; } else if(type == java.lang.Object.class) { //Return match for name, and any non-primitive type for(int i = 0; i < _fields.length; i++) { if(_fields[i].getName().equals(name) && !_fields[i].getType().isPrimitive()) { return _fields[i]; } } return (ObjectStreamField)null; } else { for(int i = 0; i < _fields.length; i++) { if(_fields[i].getName().equals(name) && _fields[i].getType().equals(type)) { return _fields[i]; } } return (ObjectStreamField)null; } } private void computeOffsets() { try { computeFieldOffsets(); } catch(Exception e) { throw new RuntimeException(org.apache.geronimo.interop.util.ExceptionUtil.causedBy(e)); } } private void computeFieldOffsets() throws Exception { primDataSize = 0; numObjFields = 0; int firstObjIndex = -1; java.io.ObjectStreamField[] fields = desc.getFields(); _fields = new ObjectStreamField[fields.length]; Object[] args = new Object[1]; for (int i = 0; i < fields.length; i++) { java.io.ObjectStreamField f = fields[i]; _fields[i] = new ObjectStreamField(fields[i].getName(), fields[i].getType()); ObjectStreamField _f = _fields[i]; switch (f.getTypeCode()) { case 'Z': case 'B': args[0] = new Integer(primDataSize++); setOffsetMethod.invoke(_f, args); break; case 'C': case 'S': args[0] = new Integer(primDataSize); setOffsetMethod.invoke(_f, args); primDataSize += 2; break; case 'I': case 'F': args[0] = new Integer(primDataSize); setOffsetMethod.invoke(_f, args); primDataSize += 4; break; case 'J': case 'D': args[0] = new Integer(primDataSize); setOffsetMethod.invoke(_f, args); primDataSize += 8; break; case '[': case 'L': args[0] = new Integer(numObjFields++); setOffsetMethod.invoke(_f, args); if (firstObjIndex == -1) { firstObjIndex = i; } break; default: break; } } if (firstObjIndex != -1 && firstObjIndex + numObjFields != fields.length) { //throw new InvalidClassException(name, "illegal field order"); } } }