src.com.ibm.as400.access.PxToolboxObjectParm Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400-jdk8 Show documentation
Show all versions of jt400-jdk8 Show documentation
The Open Source version of the IBM Toolbox for Java
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PxToolboxObjectParm.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.StringTokenizer;
import java.util.Vector;
/**
The PxToolboxObjectParm class represents a
serialized Toolbox object parameter in a proxy datastream. We can't
just serialize Toolbox objects, since they may contain proxy objects.
Otherwise, the contained proxy objects would be serialized along with
it, which is incorrect.
**/
class PxToolboxObjectParm
extends PxCompDS
implements PxParm
{
private static final String copyright = "Copyright (C) 1997-2000 International Business Machines Corporation and others.";
// Private data.
private static boolean DEBUG_ = false;
private Object value_;
public PxToolboxObjectParm ()
{
super (ProxyConstants.DS_TOOLBOX_OBJECT_PARM);
}
public PxToolboxObjectParm (Object value)
{
super (ProxyConstants.DS_TOOLBOX_OBJECT_PARM);
value_ = value;
if (DEBUG_)
System.out.println("Creating toolbox object parm: " + value + " (" + value.getClass() + ").");
// First we can just serialize this object.
addParm(new PxSerializedObjectParm(value));
// Next we will pass along a list of all contained objects
// (no matter how deep) which are proxified objects.
Vector fieldNames = new Vector();
Vector proxyImpls = new Vector();
analyze(value, "", fieldNames, proxyImpls);
// Send the number of contained proxy objects.
int proxyCount = proxyImpls.size();
addParm(new PxIntParm(proxyCount));
// Send each proxy object, name then value.
for (int i = 0; i < proxyCount; ++i) {
addParm(new PxStringParm((String)fieldNames.elementAt(i)));
addParm(new PxPxObjectParm(((ProxyImpl)proxyImpls.elementAt(i)).getPxId()));
}
}
private static void analyze(Object objectValue, String prefix, Vector fieldNames, Vector proxyImpls)
{
if (DEBUG_) {
System.out.println("Analyzing " + objectValue + " (" + objectValue.getClass() + ").");
System.out.println("Prefix=" + prefix + ".");
}
// getDeclaredFields() is not allowed in applets. If it throws // @A1A
// an exception, we will assume that there is nothing interesting // @A1A
// in the data. If there is, it will potentially be lost (i.e. // @A1A
// not everything that works for applications will work for applets. // @A1A
try { // @A1A
// First, analyze all of our declared fields, then all of
// our superclass's, etc.
for (Class clazz = objectValue.getClass();
! clazz.equals(Object.class);
clazz = clazz.getSuperclass())
{
Field[] declaredFields = clazz.getDeclaredFields();
if (declaredFields != null) {
for (int i = 0; i < declaredFields.length; ++i) {
String fieldName = declaredFields[i].getName();
if (DEBUG_)
System.out.println("Field name=" + fieldName + ".");
// If the field is transient, then do nothing.
if (! Modifier.isTransient(declaredFields[i].getModifiers())) {
// Note that this check depends on the assumption that
// contained proxy objects be declared at least package
// scope (otherwise we will catch an IllegalAccessException).
// I know this is not a great assumption, but
// it makes the implementation easier.
try {
Object fieldValue = declaredFields[i].get(objectValue);
if (fieldValue != null) {
if (DEBUG_)
System.out.println("Field value=" + fieldValue + " (" + fieldValue.getClass() + ").");
// Only be concerned with non-static Toolbox fields.
if (!Modifier.isStatic(declaredFields[i].getModifiers())
&& fieldValue.getClass().getName().startsWith("com.ibm.as400.access")) {
// If the field value is a proxy object, then add it to the list.
// Otherwise, analyze recursively.
if (fieldValue instanceof ProxyImpl) {
fieldNames.addElement(prefix + fieldName);
proxyImpls.addElement((ProxyImpl)fieldValue);
}
else if (fieldValue.getClass().getName().startsWith("com.ibm.as400.access"))
analyze(fieldValue, fieldValue + ".", fieldNames, proxyImpls);
}
}
}
catch (IllegalAccessException e) {
// Ignore.
if (DEBUG_)
System.out.println("Ignored IllegalAccessException:" + e.getMessage());
}
}
}
}
}
} // @A1A
catch (Exception e) { // @A1A
if (Trace.isTraceErrorOn()) // @A1A
Trace.log(Trace.ERROR, "Exception when analyzing Toolbox parm", e); // @A1A
} // @A1A
}
/**
Returns a new copy of this datastream.
@return A new copy of this datastream.
@exception CloneNotSupportedException If the object cannot be cloned.
**/
//
// Implementation note: This method is necessary in order to do
// a deep copy of the internal object. Otherwise,
// we run into problems with multiple threads.
public Object clone ()
throws CloneNotSupportedException
{
value_ = null;
return super.clone();
}
public Object getObjectValue ()
{
return value_;
}
public void readFrom(InputStream input, PxDSFactory factory)
throws IOException
{
super.readFrom(input, factory);
// Deserialize the object.
value_ = getParm(0).getObjectValue();
// Number of contained objects ("corrections").
int proxyCount = ((PxIntParm)getParm(1)).getIntValue();
int parmIndex = 1;
for (int i = 1; i <= proxyCount; ++i) {
String fieldName = ((PxStringParm)getParm(++parmIndex)).getStringValue();
Object impl = ((PxPxObjectParm)getParm(++parmIndex)).getObjectValue();
// Set the field.
Object fieldValue = value_;
Field field = null;
// Navigate down the containment hierarchy to
// get the right field.
StringTokenizer tokenizer = new StringTokenizer(fieldName, ".");
while (tokenizer.hasMoreTokens()) {
// Get the next field to navigate to.
String token = tokenizer.nextToken();
Class clazz = fieldValue.getClass();
try {
field = clazz.getDeclaredField(token);
if (field == null) {
// This should never happen!
if (Trace.isTraceErrorOn())
Trace.log(Trace.ERROR, "Error reading toolbox parm: field set to null");
}
}
catch(NoSuchFieldException e) {
// This should never happen!
if (Trace.isTraceErrorOn())
Trace.log(Trace.ERROR, "Error reading toolbox parm", e);
}
// Get the value of that field.
try {
if (tokenizer.hasMoreTokens())
if (field != null) fieldValue = field.get(fieldValue);
}
catch(IllegalAccessException e) {
// This should never happen!
if (Trace.isTraceErrorOn())
Trace.log(Trace.ERROR, "Error reading toolbox parm", e);
}
}
// At this point, field is set to the field that we need to set.
try {
if (field != null) field.set(fieldValue, impl);
}
catch(IllegalAccessException e) {
// This should never happen!
if (Trace.isTraceErrorOn())
Trace.log(Trace.ERROR, "Error reading toolbox parm", e);
}
}
}
public String toString ()
{
return super.toString () + " (" + value_ + ")";
}
}