FieldSig.java :  » Scripting » jacl » tcl » lang » Java Open Source

Java Open Source » Scripting » jacl 
jacl » tcl » lang » FieldSig.java
/*
 * FieldSig.java --
 *
 *  This class implements the internal representation of a Java
 *  field signature.
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 *
 * RCS: @(#) $Id: FieldSig.java,v 1.9 2006/04/13 07:36:50 mdejong Exp $
 *
 */

package tcl.lang;

import tcl.lang.reflect.*;
import java.lang.reflect.*;
import java.util.*;

/**
 * This class implements the internal representation of a Java field
 * signature.
 */

class FieldSig implements InternalRep {

// The class that the field signature is used against. If the
// java::field command is given a class name, then the targetCls is
// that class; if If the java::field command is given a Java object,
// then the targetCls is the class of that object.  targetCls is used
// to test the validity of a cached FieldSig internal rep.

Class targetCls;

// The class specified by the signature. If the signature only gives
// the name of a field and omits the declaring class, then sigCls is
// the same as targetCls.

Class sigCls;

// The handle to the field as given by the field signature.

Field field;

// The PkgInvoker used to access the field. 

PkgInvoker pkgInvoker;


/*
 *----------------------------------------------------------------------
 *
 * FieldSig --
 *
 *  Creates a new FieldSig instance.
 *
 * Side effects:
 *  Member fields are initialized.
 *
 *----------------------------------------------------------------------
 */

FieldSig(
    Class tc,      // Initial value for targetCls.
    Class sc,      // Initial value for sigCls.
    PkgInvoker p,    // Initial value for pkgInvoker.
    Field f)      // Initial value for field.
{
    targetCls = tc;
    sigCls = sc;
    pkgInvoker = p;
    field = f;
}

/*
 *----------------------------------------------------------------------
 *
 * duplicate --
 *
 *  Make a copy of an object's internal representation.
 *
 * Results:
 *  Returns a newly allocated instance of the appropriate type.
 *
 * Side effects:
 *  None.
 *
 *----------------------------------------------------------------------
 */

public InternalRep duplicate()
{
    return new FieldSig(targetCls, sigCls, pkgInvoker, field);
}

/**
  * Implement this no-op for the InternalRep interface.
  */

public void dispose() {}

/*
 *----------------------------------------------------------------------
 *
 * get --
 *
 *  Returns the FieldSig internal rep given by the field signature.
 *
 * Results:
 *  The FieldSig given by the signature.
 *
 * Side effects:
 *  When successful, the internalRep of the signature object is
 *  converted to FieldSig.
 *
 *----------------------------------------------------------------------
 */

static FieldSig
get(
    Interp interp,    // Current interpreter
    TclObject signature,  // The TclObject that holds a field signature.
    Class targetCls)    // The target class of the field signature.
throws
    TclException    // Standard Tcl exception.
{
    InternalRep rep = signature.getInternalRep();

    if ((rep instanceof FieldSig) && (((FieldSig)rep).targetCls == targetCls)){
  // The cached internal rep is a valid field signature for
  // the given targetCls.

  return (FieldSig)rep;
    }

    String fieldName;
    TclObject sigClsObj;
    Class sigCls;
    Field field;

    int len = TclList.getLength(interp, signature);
    if ((len < 1) || (len > 2)) {
  throw new TclException(interp, "bad field signature \"" +
    signature + "\"");
    }

    if (len == 1) {
  fieldName = signature.toString();
  sigClsObj = null;
    } else {
  fieldName = TclList.index(interp, signature, 0).toString();
  sigClsObj = TclList.index(interp, signature, 1);
    }

    if (sigClsObj != null) {
  sigCls = ClassRep.get(interp, sigClsObj);
  if (!sigCls.isAssignableFrom(targetCls)) {
      throw new TclException(interp, "\"" +
        JavaInfoCmd.getNameFromClass(sigCls) +
        "\" is not a superclass of \"" +
        JavaInfoCmd.getNameFromClass(targetCls) +
        "\"");
  }
  if (!PkgInvoker.isAccessible(sigCls)) {
      JavaInvoke.notAccessibleError(interp, sigCls);
  }
    } else {
  sigCls = targetCls;
    }

    try {
  field = getAccessibleField(sigCls, fieldName);
    } catch (NoSuchFieldException e) {
  throw new TclException(interp, "no accessible field \"" + signature +
    "\" found in class " +
    JavaInfoCmd.getNameFromClass(sigCls));
    }

    FieldSig sig = new FieldSig(targetCls, sigCls, PkgInvoker.getPkgInvoker(
      targetCls), field);
    signature.setInternalRep(sig);

    return sig;
}

/*
 *----------------------------------------------------------------------
 *
 * getAccessibleFields --
 *
 *  Returns all fields that can be read/written for a given class.
 *
 * Results:
 *  An array of all the accessible fields in the class.
 *
 * Side effects:
 *  None.
 *
 *----------------------------------------------------------------------
 */

static Field[]
getAccessibleFields(
    Class cls)        // The class to query.
{
    if (PkgInvoker.usesDefaultInvoker(cls)) {
  return cls.getFields();
    } else {
  Field[] fields = cls.getDeclaredFields();
  ArrayList alist = null;
  boolean skipped_any = false;

  for (int i=0; i < fields.length; i++) {
      Field f = fields[i];
      if (PkgInvoker.isAccessible(f)) {
          if (alist == null) {
              alist = new ArrayList(fields.length);
          }
          alist.add(f);
      } else {
          skipped_any = true;
      }
  }

  if (skipped_any) {
      fields = new Field[alist.size()];
      for (int i=0; i < fields.length; i++) {
                fields[i] = (Field) alist.get(i);
            }
  }
  return fields;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * getAccessibleField --
 *
 *  Returns an accessible field given by the fieldName and
 *  the given class.
 *
 * Results:
 *  An accessible field in the class, raises a NoSuchFieldException
 *  if an accessible field cannot be found.
 *
 * Side effects:
 *  None.
 *
 *----------------------------------------------------------------------
 */

static Field
getAccessibleField(
    Class cls,        // The class to query.
    String fieldName)      // The field name.
    throws NoSuchFieldException
{
    if (PkgInvoker.usesDefaultInvoker(cls)) {
  return cls.getField(fieldName);
    } else {
  Field f = cls.getDeclaredField(fieldName);
  if (!PkgInvoker.isAccessible(f)) {
      throw new NoSuchFieldException();
  }
  return f;
    }
}
} // end FieldSig

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.