/** * Generates a new error message based on the excpetion message. * * @param message the rror message */ public void generateErrorMessage(String message, MethodDescription mDesc) { ObjectDescription oDesc = getObjectDescription(getObject(mDesc.getObjectID())); String methodName = oDesc.getName() + "." + mDesc.getMethodName() + "()"; System.err.println("Method \"" + methodName + "\" can't be invoked:" + message); }
/** * Adds an object to this inspector. * * @param o the object that is to be added * @param objID object id of the object that shall be replaced */ public synchronized void replaceObject(Object newObj, int objID) throws InterfaceChangedException { if (newObj == null) { throw new IllegalArgumentException("Argument \"null\" not supported!"); } // objects.getById(objID).setObject(newObj); Collection<Object> instances = getObjectsByClassName(newObj.getClass().getName()); if (instances.size() <= objID) { addObject(newObj); } else { Object oldObj = getObject(objID); ObjectDescription oDescOld = getObjectDescription(oldObj); ObjectDescription oDescNew = generateObjectDescription(newObj, objID, false); if (oDescOld.getSignature().equals(oDescNew.getSignature())) { removeObject(objID); addObject(newObj, objID); objectDescriptions.add(oDescNew); } else { throw new InterfaceChangedException( "Cannot replace object because the interface of the new" + " class and the old class are not equal!"); } } }
/** * Returns the object description of an object. * * @param o the object of the description that is to be returned * @return description of the object or <code>null</code> if the requested description cannot be * found */ public ObjectDescription getObjectDescription(Object o) { Integer ID = getObjectID(o); if (ID == null) { return null; } for (ObjectDescription oD : this.getObjectDescriptions()) { if (oD.getID() == ID) { return oD; } } return null; }
/** * 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); }
/** * Returns the description of a method. * * @param o object of the method * @param methodName name of the method * @param params method parameters * @return description of the method or <code>null</code> if the requested method could not be * found */ public MethodDescription getMethodDescription(Object o, String methodName, Class... params) { ObjectDescription oDesc = getObjectDescription(o); MethodDescription result = null; ArrayList<Class> paramTypes = new ArrayList<Class>(); for (Class<?> p : params) { // Class c = p.getClass(); paramTypes.add(p); } for (MethodDescription mDesc : oDesc.getMethods()) { if (mDesc.getMethodName().equals(methodName)) { // System.out.println("M: " + mDesc.getMethodName()); boolean isEqual = true; for (int i = 0; i < mDesc.getParameterTypes().length; i++) { // System.out.println(">> P: " + // mDesc.getParameterTypes()[i].getName()); // System.out.println(">> PE: " + paramTypes.get(i).getName()); if (!paramTypes.get(i).equals(mDesc.getParameterTypes()[i])) { isEqual = false; break; } } if (isEqual) { result = mDesc; result.setParameters(params); break; } } } // if (result == null) { // System.err.println(">> MethodDescription not found!" // + " Wrong name or wrong parameters?"); // } return result; }
/** * Removes object with specific ID from the inspector. * * @param ID the ID of the object that is to be removed */ public void removeObject(int ID) { // remove object entry ObjectEntry removedElement1 = null; for (ObjectEntry oEntry : objects) { if (oEntry.getID() == ID) { removedElement1 = oEntry; break; } } objects.remove(removedElement1); // remove object description ObjectDescription removedElement2 = null; for (ObjectDescription oDesc : objectDescriptions) { if (oDesc.getID() == ID) { removedElement2 = oDesc; break; } } objectDescriptions.remove(removedElement2); }
/** * Returns the description of a method. * * @param o object of the method * @param methodName name of the method * @param params method parameters * @return description of the method */ public MethodDescription getMethodDescriptionFromGUI( Object o, String methodName, Object... params) { ObjectDescription oDesc = getObjectDescription(o); MethodDescription result = null; // ArrayList<Class> paramTypes = new ArrayList<Class>(); // // for (Object p : params) { // Class c = p.getClass(); // paramTypes.add(c); // } for (MethodDescription mDesc : oDesc.getMethods()) { if (mDesc.getMethodName().equals(methodName)) { boolean isEqual = true; for (int i = 0; i < mDesc.getParameterTypes().length; i++) { if (!params[i].equals(mDesc.getParameterTypes()[i])) { isEqual = false; break; } } if (isEqual) { result = mDesc; result.setParameters(params); break; } } } if (result == null) { System.out.println(">> MethodDescription not found!" + " Wrong name or wrong parameters?"); } return result; }
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; }