コード例 #1
0
ファイル: ObjectInspector.java プロジェクト: cpoliwoda/VRL
  /**
   * For each instance of the given class a new instance for replacement will be created if the
   * interface of the specified class has not changed. The purpose of this method is to create
   * instances from updated class, i.e., if the specified class has been recompiled.
   *
   * @param cls the class
   * @param creator instance creator
   * @return a pair containing the old instances (first) and the new instances (second)
   * @throws InterfaceChangedException if the interface of the specified class has changed
   */
  public synchronized Pair<ArrayList<Object>, ArrayList<Object>> replaceAllObjects(
      Class<?> cls, InstanceCreator creator) throws InterfaceChangedException {

    if (cls == null) {
      throw new IllegalArgumentException("Argument \"null\" not supported!");
    }

    ArrayList<Object> newInstances = new ArrayList<Object>();
    ArrayList<Object> oldInstances = new ArrayList<Object>();

    Collection<Object> instances = getObjectsByClassName(cls.getName());

    //        if (instances.isEmpty()) {
    //            throw new IllegalStateException(
    //                    "Cannot replace. No instances found!");
    //        }
    for (Object oldObj : instances) {
      Object newObj;

      newObj = creator.newInstance(cls);

      if (newObj == null) {
        break;
      }

      int objID = getObjectID(oldObj);

      ObjectDescription oDescOld = getObjectDescription(oldObj);
      ObjectDescription oDescNew = generateObjectDescription(newObj, objID, false);

      if (oDescOld.getSignature().equals(oDescNew.getSignature())) {
        oldInstances.add(getObject(objID));

        replaceObject(newObj, objID);
        newInstances.add(newObj);
      } else {
        throw new InterfaceChangedException(
            "Cannot replace object because the interface of the new"
                + " class and the old class are not equal!");
      }
    }

    return new Pair<ArrayList<Object>, ArrayList<Object>>(oldInstances, newInstances);
  }
コード例 #2
0
ファイル: ObjectInspector.java プロジェクト: cpoliwoda/VRL
  public ObjectDescription generateObjectDescription(Object o, Integer objID, boolean addObject) {

    ObjectDescription result = null;

    // Object annotations
    ObjectInfo objectInfo = null;

    Annotation[] objectAnnotations = o.getClass().getAnnotations();

    for (Annotation a : objectAnnotations) {
      if (a.annotationType().equals(ObjectInfo.class)) {
        objectInfo = (ObjectInfo) a;
        break;
      }
    }

    if (addObject) {
      ObjectEntry oEntry = new ObjectEntry(o);
      if (objID != null) {
        objects.addWithID(oEntry, objID);
      } else {
        objects.add(oEntry);
        objID = oEntry.getID();
      }
    }

    boolean hasCustomReferenceMethod = false;

    // we need special treatment for proxy objects
    if (o instanceof ProxyObject) {
      ProxyObject proxy = (ProxyObject) o;

      result = proxy.getObjectDescription();

      result.setName(o.getClass().getName());

      result.setID(objID);

      // update objID of methods
      for (MethodDescription mDesc : result.getMethods()) {
        mDesc.setObjectID(objID);
      }

    } else {
      result = new ObjectDescription();
      result.setInfo(objectInfo);

      result.setName(o.getClass().getName());

      result.setID(objID);

      Class<?> c = o.getClass();

      Method[] theMethods = null;

      if (objectInfo != null && objectInfo.showInheritedMethods()) {
        theMethods = c.getMethods();
      } else {
        ArrayList<Method> methods = new ArrayList<Method>();

        // methods declared by class c
        for (Method m : c.getDeclaredMethods()) {
          methods.add(m);
        }

        // methods declared in superclasses of c
        for (Method m : c.getMethods()) {
          MethodInfo info = m.getAnnotation(MethodInfo.class);
          // if m is marked as inheritGUI this method will
          // be visualized even if it is a method declared
          // in a superclass of c
          if (info != null && info.inheritGUI()) {
            if (!methods.contains(m)) {
              methods.add(m);
            }
          }
        }

        Method[] tmpArray = new Method[methods.size()];

        theMethods = methods.toArray(tmpArray);
      }

      for (int i = 0; i < theMethods.length; i++) {

        // filter groovy object specific methods
        String method = theMethods[i].getName();
        boolean isGroovyObject = o instanceof GroovyObject;
        boolean isGroovyMethod =
            method.equals("setProperty")
                || method.equals("getProperty")
                || method.equals("invokeMethod")
                || method.equals("getMetaClass")
                || method.equals("setMetaClass"); // ||
        //                            // the following methods are only present
        //                            // for Groovy >= 1.6
        //                            method.equals("super$1$wait") ||
        //                            method.equals("super$1$toString") ||
        //                            method.equals("super$1$notify") ||
        //                            method.equals("super$1$notifyAll") ||
        //                            method.equals("super$1$getClass") ||
        //                            method.equals("super$1$equals") ||
        //                            method.equals("super$1$clone") ||
        //                            method.equals("super$1$hashCode") ||
        //                            method.equals("super$1$finalize");

        // For Groovy >= 1.6 private methods have $ sign in their
        // name, e.g.,
        //   private doSomething()
        // will be changed to
        //   this$2$doSomething()
        // which is unfortunately accessible and thus will be
        // visualized by vrl.
        // To prevent groovys strange behavior
        // methods with $ sign are ignored and treated as private.
        boolean isPrivateGroovyMethod = method.contains("$");

        // TODO improve that code!
        if ((isGroovyObject && isGroovyMethod) || isPrivateGroovyMethod) {
          continue;
        }

        Class[] parameterTypes = theMethods[i].getParameterTypes();

        Annotation[][] allParameterAnnotations = theMethods[i].getParameterAnnotations();

        ArrayList<String> paramNames = new ArrayList<String>();

        ArrayList<ParamInfo> paramAnnotations = new ArrayList<ParamInfo>();
        ArrayList<ParamGroupInfo> paramGroupAnnotations = new ArrayList<ParamGroupInfo>();

        // retrieving annotation information for each parameter
        for (int j = 0; j < allParameterAnnotations.length; j++) {

          Annotation[] annotations = allParameterAnnotations[j];

          // add name element and set it to null
          // because we don't know if parameter j is annotated
          paramNames.add(null);
          paramAnnotations.add(null);
          paramGroupAnnotations.add(null);

          // check all annotations of parameter j
          // if we have a ParamInfo annotation retrieve data
          // and store it as element of paramName
          for (Annotation a : annotations) {
            if (a.annotationType().equals(ParamInfo.class)) {
              ParamInfo n = (ParamInfo) a;
              if (!n.name().equals("")) {
                paramNames.set(j, n.name());
              }
              paramAnnotations.set(j, n);
            } else {
              if (a.annotationType().equals(ParamGroupInfo.class)) {
                ParamGroupInfo n = (ParamGroupInfo) a;
                paramGroupAnnotations.set(j, n);
              }
            }
          } // end for a
        } // end for j

        // convert list to array
        String[] parameterNames = paramNames.toArray(new String[paramNames.size()]);

        ParamInfo[] parameterAnnotations =
            paramAnnotations.toArray(new ParamInfo[paramAnnotations.size()]);

        ParamGroupInfo[] parameterGroupAnnotations =
            paramGroupAnnotations.toArray(new ParamGroupInfo[paramGroupAnnotations.size()]);

        Class returnType = theMethods[i].getReturnType();

        String methodString = theMethods[i].getName();
        String methodTitle = "";
        String returnValueName = null;

        int modifiers = theMethods[i].getModifiers();

        String modifierString = Modifier.toString(modifiers);

        // Method Annotations
        Annotation[] annotations = theMethods[i].getAnnotations();
        MethodInfo methodInfo = null;

        OutputInfo outputInfo = null;

        boolean interactive = true;
        boolean hide = false;

        for (Annotation a : annotations) {
          if (a.annotationType().equals(MethodInfo.class)) {
            MethodInfo n = (MethodInfo) a;

            methodTitle = n.name();
            interactive = n.interactive();
            hide = n.hide();
            returnValueName = n.valueName();

            methodInfo = n;
          }

          if (a.annotationType().equals(OutputInfo.class)) {
            outputInfo = (OutputInfo) a;
          }
        }

        if (theMethods[i].getAnnotation(ReferenceMethodInfo.class) != null) {
          hasCustomReferenceMethod = true;
          MethodDescription customReferenceMethod =
              new MethodDescription(
                  objID,
                  0,
                  methodString,
                  methodTitle,
                  null,
                  parameterTypes,
                  parameterNames,
                  parameterAnnotations,
                  parameterGroupAnnotations,
                  returnType,
                  returnValueName,
                  interactive,
                  methodInfo,
                  outputInfo);

          if (customReferenceMethod.getParameterTypes() == null
              || customReferenceMethod.getParameterTypes().length != 1) {
            throw new IllegalArgumentException(
                " Cannot to use "
                    + "\""
                    + methodString
                    + "\" as reference method"
                    + " because the number of parameters does not"
                    + " match. Exactly one parameter must be"
                    + " provided.");
          }

          if (customReferenceMethod.getReturnType() == void.class
              || customReferenceMethod.getReturnType().isPrimitive()) {
            throw new IllegalArgumentException(
                " Cannot to use "
                    + "\""
                    + methodString
                    + "\" as reference method"
                    + " because it does not return an object."
                    + " Returning primitives or void is not"
                    + " allowed.");
          }

          customReferenceMethod.setMethodType(MethodType.CUSTOM_REFERENCE);

          result.addMethod(customReferenceMethod);
        } //
        // TODO: at the moment method id is always 0 and will only be
        //      set from corresponding method representations
        //
        //      is it necessary to change that?
        else if (modifierString.contains("public")
            && (methodInfo == null || !methodInfo.ignore())) {
          result.addMethod(
              new MethodDescription(
                  objID,
                  0,
                  methodString,
                  methodTitle,
                  null,
                  parameterTypes,
                  parameterNames,
                  parameterAnnotations,
                  parameterGroupAnnotations,
                  returnType,
                  returnValueName,
                  interactive,
                  methodInfo,
                  outputInfo));
        }
      } // end for i

      // Object name
      if (objectInfo != null && !objectInfo.name().equals("")) {
        result.setName(objectInfo.name());
      }
    } // end else if (o instanceof ProxyObject)

    if (!hasCustomReferenceMethod) {
      result.addMethod(MethodDescription.createReferenceMethod(objID, o.getClass()));
    }

    return result;
  }