blob: 0f79e5145634e0dc4a0f7e44f7e8dc5070fe33d1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.modules.debugger.jpda.visual;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassType;
import com.sun.jdi.Field;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.PrimitiveType;
import com.sun.jdi.PrimitiveValue;
import com.sun.jdi.StringReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Type;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
import java.awt.Rectangle;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import org.netbeans.api.debugger.jpda.CallStackFrame;
import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
import org.netbeans.modules.debugger.jpda.expr.InvocationExceptionTranslated;
import org.netbeans.modules.debugger.jpda.jdi.ClassNotPreparedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ClassTypeWrapper;
import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.MethodWrapper;
import org.netbeans.modules.debugger.jpda.jdi.MirrorWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ObjectCollectedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ObjectReferenceWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ReferenceTypeWrapper;
import org.netbeans.modules.debugger.jpda.jdi.StringReferenceWrapper;
import org.netbeans.modules.debugger.jpda.jdi.TypeComponentWrapper;
import org.netbeans.modules.debugger.jpda.jdi.TypeWrapper;
import org.netbeans.modules.debugger.jpda.jdi.UnsupportedOperationExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.VMDisconnectedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ValueWrapper;
import org.netbeans.modules.debugger.jpda.jdi.VirtualMachineWrapper;
import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
import org.netbeans.modules.debugger.jpda.visual.spi.ComponentInfo;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.nodes.Node;
import org.openide.nodes.Node.Property;
import org.openide.nodes.Node.PropertySet;
import org.openide.nodes.PropertySupport.ReadOnly;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
/**
*
* @author Jaroslav Bachorik
*/
public abstract class JavaComponentInfo implements ComponentInfo {
private static final JavaComponentInfo[] NO_SUBCOMPONENTS = new JavaComponentInfo[]{};
private static final int MAX_TEXT_LENGTH = 80;
private static RequestProcessor RP = new RequestProcessor(JavaComponentInfo.class);
//private AWTComponentInfo parent;
private Rectangle bounds;
private Rectangle windowBounds;
private String name;
private String type;
private JavaComponentInfo[] subComponents;
private List<PropertySet> propertySets = new ArrayList<PropertySet>();
private PropertyChangeSupport pchs = new PropertyChangeSupport(this);
private JPDAThreadImpl thread;
private ObjectReference component;
private FieldInfo fieldInfo;
private String componentText;
private RemoteServices.ServiceType sType;
long uid;
public JavaComponentInfo(JPDAThreadImpl t, ObjectReference component, RemoteServices.ServiceType sType) throws RetrievalException {
this.thread = t;
this.component = component;
try {
this.type = ReferenceTypeWrapper.name(ObjectReferenceWrapper.referenceType(component));
} catch (InternalExceptionWrapper ex) {
throw new RetrievalException(ex.getLocalizedMessage(), ex);
} catch (VMDisconnectedExceptionWrapper ex) {
throw RetrievalException.disconnected();
} catch (ObjectCollectedExceptionWrapper ex) {
throw new RetrievalException(ex.getLocalizedMessage(), ex);
}
this.sType = sType;
this.uid = component.uniqueID();
}
protected final void init() throws RetrievalException {
retrieve();
addProperties();
if (!RemoteAWTScreenshot.FAST_FIELDS_SEARCH) {
findComponentFields();
}
}
protected abstract void retrieve() throws RetrievalException;
public final JPDAThreadImpl getThread() {
return thread;
}
public final ObjectReference getComponent() {
return component;
}
/** Provide the stack information about where this component was added into the hierarchy */
public Stack getAddCallStack() {
return VisualDebuggerListener.getStackOf(thread.getDebugger(), component);
}
public final String getName() {
return name;
}
public final String getTypeName() {
int d = type.lastIndexOf('.');
String typeName;
if (d > 0) {
typeName = type.substring(d + 1);
} else {
typeName = type;
}
return typeName;
}
public final void setComponentText(String componentText) {
if (componentText.length() > MAX_TEXT_LENGTH) {
this.componentText = componentText.substring(0, MAX_TEXT_LENGTH) + "...";
} else {
this.componentText = componentText;
}
}
@Override
public String getDisplayName() {
String typeName = getTypeName();
String text = (componentText != null) ? " \"" + componentText + "\"" : "";
return getFieldName() + "[" + typeName + "]" + text;
}
@Override
public String getHtmlDisplayName() {
if (isCustomType() || componentText != null) {
String typeName = getTypeName();
if (isCustomType()) {
typeName = "<b>" + typeName + "</b>";
}
String text;
if (componentText != null) {
text = escapeHTML(componentText);
text = " <font color=\"#A0A0A0\">\"" + text + "\"</font>";
} else {
text = "";
}
return getFieldName() + "[" + typeName + "]" + text;
} else {
return null;
}
}
protected String getFieldName() {
return (fieldInfo != null) ? fieldInfo.getName() + " " : "";
}
public final String getType() {
return type;
}
public final FieldInfo getField() {
return fieldInfo;
}
public final boolean isCustomType() {
return isCustomType(type);
}
public static boolean isCustomType(String type) {
return !(type.startsWith("java.awt.") ||
type.startsWith("javax.swing.") ||
type.startsWith("javafx.") ||
type.startsWith("com.sun.")); // NOI18N
}
@Override
public final Rectangle getBounds() {
return bounds;
}
@Override
public final Rectangle getWindowBounds() {
if (windowBounds == null) {
return bounds;
} else {
return windowBounds;
}
}
public final void addPropertySet(PropertySet ps) {
propertySets.add(ps);
}
@Override
public final PropertySet[] getPropertySets() {
return propertySets.toArray(new PropertySet[]{});
}
protected final void setSubComponents(JavaComponentInfo[] subComponents) {
this.subComponents = subComponents;
}
@Override
public final JavaComponentInfo[] getSubComponents() {
if (subComponents == null) {
return NO_SUBCOMPONENTS;
} else {
return subComponents;
}
}
@Override
public final void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) {
pchs.addPropertyChangeListener(propertyChangeListener);
}
@Override
public final void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) {
pchs.removePropertyChangeListener(propertyChangeListener);
}
protected final void firePropertyChange(String name, Object o, Object n) {
pchs.firePropertyChange(name, o, n);
}
public final void setFieldInfo(FieldInfo fieldInfo) {
this.fieldInfo = fieldInfo;
}
public final void setBounds(Rectangle r) {
this.bounds = r;
}
public final void setWindowBounds(Rectangle rectangle) {
this.windowBounds = rectangle;
}
public final void setName(String value) {
this.name = value;
}
public final void setComponent(ObjectReference component) {
this.component = component;
}
public final void setType(String name) {
this.type = name;
}
private void addProperties() {
addPropertySet(new PropertySet("main", NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropMain"),
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropMainDescr")) {
@Override
public Property<?>[] getProperties() {
return new Property[] {
new ReadOnly("name", String.class,
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropName"),
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropNameDescr")) {
@Override
public Object getValue() throws IllegalAccessException, InvocationTargetException {
return JavaComponentInfo.this.getName();
}
},
new ReadOnly("type", String.class,
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropType"),
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropTypeDescr")) {
@Override
public Object getValue() throws IllegalAccessException, InvocationTargetException {
return JavaComponentInfo.this.getType();
}
},
new ReadOnly("bounds", String.class,
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropBounds"),
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropBoundsDescr")) {
@Override
public Object getValue() throws IllegalAccessException, InvocationTargetException {
Rectangle r = JavaComponentInfo.this.getWindowBounds();
return "[x=" + r.x + ",y=" + r.y + ",width=" + r.width + ",height=" + r.height + "]";
}
},
};
}
});
final LazyProperties lazyProperties = new LazyProperties();
addPropertySet(
new PropertySet("Properties",
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentProps"),
NbBundle.getMessage(JavaComponentInfo.class, "MSG_ComponentPropsDescr")) {
@Override
public Property<?>[] getProperties() {
//System.err.println("JavaComponentInfo.Properties PropertySet.getProperties()");
// To fix https://netbeans.org/bugzilla/show_bug.cgi?id=243065
// https://netbeans.org/bugzilla/show_bug.cgi?id=241154
// Do not compute properties above, compute them on demand in a separate thread now.
// When done, fire Node.PROP_PROPERTY_SETS, null, null.
Property<?>[] props = lazyProperties.getProperties();
//System.err.println("\nprops = "+props.length+"\n");
return props;
}
});
try {
Method getTextMethod = ClassTypeWrapper.concreteMethodByName(
(ClassType) ObjectReferenceWrapper.referenceType(component), "getText", "()Ljava/lang/String;");
//Method getTextMethod = methodsByName.get("getText"); // NOI18N
if (getTextMethod != null) {
try {
Value theText = ObjectReferenceWrapper.invokeMethod(component, getThread().getThreadReference(), getTextMethod, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
if (theText instanceof StringReference) {
setComponentText(StringReferenceWrapper.value((StringReference) theText));
}
} catch (VMDisconnectedExceptionWrapper vmdex) {
return;
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
} catch (ClassNotPreparedExceptionWrapper | InternalExceptionWrapper |
ObjectCollectedExceptionWrapper | VMDisconnectedExceptionWrapper cnpe) {
}
}
private class LazyProperties implements Runnable {
private volatile Reference<Property<?>[]> propertiesRef;
Property<?>[] getProperties() {
Property<?>[] properties;
if (propertiesRef == null) {
propertiesRef = new SoftReference<>(null);
properties = null;
} else {
properties = propertiesRef.get();
}
if (properties == null) {
properties = new Property[] {};
propertiesRef = new SoftReference<>(properties);
RP.post(this);
}
return properties;
}
@Override
public void run() {
// TODO: Try to find out the BeanInfo of the class
//System.err.println("Computing the component properties...");
List<Method> allMethods;
Map<String, Method> methodsByName;
try {
allMethods = ReferenceTypeWrapper.allMethods(ObjectReferenceWrapper.referenceType(component));
//System.err.println("Have "+allMethods.size()+" methods.");
methodsByName = new HashMap<String, Method>(allMethods.size());
for (Method m : allMethods) {
String mName = TypeComponentWrapper.name(m);
if ((mName.startsWith("get") || mName.startsWith("set")) && mName.length() > 3 ||
mName.startsWith("is") && mName.length() > 2) {
if ((mName.startsWith("get") || mName.startsWith("is")) && m.argumentTypeNames().size() == 0 ||
mName.startsWith("set") && MethodWrapper.argumentTypeNames(m).size() == 1 && "void".equals(MethodWrapper.returnTypeName(m))) {
methodsByName.put(mName, m);
}
}
}
} catch (ClassNotPreparedExceptionWrapper cnpex) {
// no class - no properties
return ;
} catch (InternalExceptionWrapper iex) {
// no go
return ;
} catch (ObjectCollectedExceptionWrapper ocex) {
// gone
return ;
} catch (VMDisconnectedExceptionWrapper vmdex) {
// gone
return ;
}
Map<String, Property> sortedProperties = new TreeMap<String, Property>();
//final List<Property> properties = new ArrayList<Property>();
for (String mName : methodsByName.keySet()) {
//System.err.println(" Have method '"+name+"'...");
if (mName.startsWith("set")) {
continue;
}
String property;
String setName;
if (mName.startsWith("is")) {
property = Character.toLowerCase(mName.charAt(2)) + mName.substring(3);
setName = "set" + mName.substring(2);
} else { // startsWith("get"):
property = Character.toLowerCase(mName.charAt(3)) + mName.substring(4);
setName = "set" + mName.substring(3);
}
Property p = new ComponentProperty(property, methodsByName.get(mName), methodsByName.get(setName),
JavaComponentInfo.this, component, getThread(), getThread().getDebugger(), sType);
sortedProperties.put(property, p);
//System.err.println(" => property '"+property+"', p = "+p);
}
Property<?>[] properties = sortedProperties.values().toArray(new Property[] {});
propertiesRef = new SoftReference<>(properties);
//System.err.println("Properties Computed: "+properties.length);
firePropertyChange(Node.PROP_PROPERTY_SETS, null, null);
}
}
protected static boolean isInstanceOfClass(ClassType c1, ClassType c2) {
if (c1.equals(c2)) {
return true;
}
c1 = c1.superclass();
if (c1 == null) {
return false;
}
return isInstanceOfClass(c1, c2);
}
private void findComponentFields() {
List<JavaComponentInfo> customParents = new ArrayList<JavaComponentInfo>();
fillCustomParents(customParents, this);
findFieldsInParents(customParents, this);
}
private static void fillCustomParents(List<JavaComponentInfo> customParents, JavaComponentInfo ci) {
ComponentInfo[] subs = ci.getSubComponents();
if (subs.length > 0 && ci.isCustomType()) {
customParents.add(ci);
}
for (ComponentInfo sci : subs) {
fillCustomParents(customParents, (JavaComponentInfo)sci);
}
}
private static void findFieldsInParents(List<JavaComponentInfo> customParents, JavaComponentInfo ci) {
ComponentInfo[] subComponents = ci.getSubComponents();
ObjectReference component = ci.getComponent();
for (JavaComponentInfo cp : customParents) {
try {
ObjectReference c = cp.getComponent();
Map<Field, Value> fieldValues = ObjectReferenceWrapper.getValues(c, ReferenceTypeWrapper.fields(ObjectReferenceWrapper.referenceType(c)));
for (Map.Entry<Field, Value> e : fieldValues.entrySet()) {
if (component.equals(e.getValue())) {
ci.setFieldInfo(new JavaComponentInfo.FieldInfo(e.getKey(), cp));
}
}
} catch (InternalExceptionWrapper ex) {
} catch (VMDisconnectedExceptionWrapper ex) {
return ;
} catch (ObjectCollectedExceptionWrapper ex) {
} catch (ClassNotPreparedExceptionWrapper ex) {
}
}
for (ComponentInfo sci : subComponents) {
findFieldsInParents(customParents, (JavaComponentInfo)sci);
}
}
private static class ComponentProperty extends Node.Property {
private String propertyName;
private Method getter;
private Method setter;
private JavaComponentInfo ci;
private ObjectReference component;
private JPDAThreadImpl t;
private ThreadReference tawt;
private JPDADebuggerImpl debugger;
private String value;
private final Object valueLock = new Object();
private final String valueCalculating = "calculating";
private final RemoteServices.ServiceType sType;
private boolean valueIsEditable;
private Type valueType;
ComponentProperty(String propertyName, Method getter, Method setter,
JavaComponentInfo ci, ObjectReference component,
JPDAThreadImpl t, JPDADebuggerImpl debugger, RemoteServices.ServiceType sType) {
super(String.class);
this.propertyName = propertyName;
this.getter = getter;
this.setter = setter;
this.ci = ci;
this.component = component;
this.t = t;
this.tawt = t.getThreadReference();
this.debugger = debugger;
this.sType = sType;
}
@Override
public String getName() {
return propertyName;
}
@Override
public String getDisplayName() {
return propertyName;
}
@Override
public boolean canRead() {
return getter != null;
}
@Override
public Object getValue() throws IllegalAccessException, InvocationTargetException {
synchronized (valueLock) {
if (value == null) {
value = valueCalculating;
debugger.getRequestProcessor().post(new Runnable() {
@Override
public void run() {
try {
RemoteServices.runOnStoppedThread(t, new Runnable() {
@Override
public void run() {
boolean[] isEditablePtr = new boolean[] { false };
Type[] typePtr = new Type[] { null };
String v = getValueLazy(isEditablePtr, typePtr);
synchronized (valueLock) {
value = v;
valueIsEditable = isEditablePtr[0];
valueType = typePtr[0];
}
ci.firePropertyChange(propertyName, null, v);
}
}, sType);
} catch (PropertyVetoException ex) {
value = ex.getLocalizedMessage();
}
}
});
}
return value;
}
}
private String getValueLazy(boolean[] isEditablePtr, Type[] typePtr) {
Lock l = t.accessLock.writeLock();
l.lock();
try {
Value v = ObjectReferenceWrapper.invokeMethod(component, tawt, getter, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
if (v != null) {
typePtr[0] = ValueWrapper.type(v);
}
if (v instanceof StringReference) {
isEditablePtr[0] = true;
return StringReferenceWrapper.value((StringReference) v);
}
if (v instanceof ObjectReference) {
isEditablePtr[0] = false;
Type t = ValueWrapper.type(v);
if (t instanceof ClassType) {
Method toStringMethod = ClassTypeWrapper.concreteMethodByName((ClassType) t, "toString", "()Ljava/lang/String;");
v = ObjectReferenceWrapper.invokeMethod((ObjectReference) v, tawt, toStringMethod, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
if (v instanceof StringReference) {
return StringReferenceWrapper.value((StringReference) v);
}
}
} else if (v instanceof PrimitiveValue) {
isEditablePtr[0] = true;
}
return (v == null) ? "null" : MirrorWrapper.toString(v);
} catch (InvalidTypeException ex) {
Exceptions.printStackTrace(ex);
return ex.getMessage();
} catch (ClassNotPreparedExceptionWrapper ex) {
Exceptions.printStackTrace(ex);
return ex.getMessage();
} catch (ClassNotLoadedException ex) {
return ex.getMessage();
} catch (IncompatibleThreadStateException ex) {
Exceptions.printStackTrace(ex);
return ex.getMessage();
} catch (InternalExceptionWrapper ex) {
return ex.getMessage();
} catch (ObjectCollectedExceptionWrapper ocex) {
return ocex.getLocalizedMessage();
} catch (VMDisconnectedExceptionWrapper vmdex) {
return vmdex.getLocalizedMessage();
} catch (final InvocationException ex) {
final InvocationExceptionTranslated iextr = new InvocationExceptionTranslated(ex, debugger);
iextr.setPreferredThread(t);
/*
RequestProcessor.getDefault().post(new Runnable() {
@Override
public void run() {
iextr.getMessage();
iextr.getLocalizedMessage();
iextr.getCause();
iextr.getStackTrace();
Exceptions.printStackTrace(iextr);
Exceptions.printStackTrace(ex);
}
}, 100);
*/
//Exceptions.printStackTrace(iextr);
//Exceptions.printStackTrace(ex);
return iextr.getMessage();
} finally {
l.unlock();
}
}
private String setValueLazy(String val, String oldValue, Type type) {
Value v;
VirtualMachine vm = type.virtualMachine();
try {
if (type instanceof PrimitiveType) {
String ts = TypeWrapper.name(type);
try {
if (Boolean.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Boolean.parseBoolean(val));
} else if (Byte.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Byte.parseByte(val));
} else if (Character.TYPE.getName().equals(ts)) {
if (val.length() == 0) {
throw new NumberFormatException("Zero length input.");
}
v = VirtualMachineWrapper.mirrorOf(vm, val.charAt(0));
} else if (Short.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Short.parseShort(val));
} else if (Integer.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Integer.parseInt(val));
} else if (Long.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Long.parseLong(val));
} else if (Float.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Float.parseFloat(val));
} else if (Double.TYPE.getName().equals(ts)) {
v = VirtualMachineWrapper.mirrorOf(vm, Double.parseDouble(val));
} else {
throw new IllegalArgumentException("Unknown type '"+ts+"'");
}
val = MirrorWrapper.toString(v);
} catch (NumberFormatException nfex) {
NotifyDescriptor msg = new NotifyDescriptor.Message(nfex.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE);
DialogDisplayer.getDefault().notify(msg);
return oldValue;
}
} else {
if ("java.lang.String".equals(TypeWrapper.name(type))) {
v = VirtualMachineWrapper.mirrorOf(vm, val);
} else {
throw new IllegalArgumentException("Unknown type '"+type.name()+"'");
}
}
} catch (InternalExceptionWrapper iex) {
return oldValue;
} catch (ObjectCollectedExceptionWrapper ocex) {
NotifyDescriptor msg = new NotifyDescriptor.Message(ocex.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE);
DialogDisplayer.getDefault().notify(msg);
return oldValue;
} catch (UnsupportedOperationExceptionWrapper uex) {
NotifyDescriptor msg = new NotifyDescriptor.Message(uex.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE);
DialogDisplayer.getDefault().notify(msg);
return oldValue;
} catch (VMDisconnectedExceptionWrapper vmd) {
return oldValue;
}
Lock l = t.accessLock.writeLock();
l.lock();
try {
ObjectReferenceWrapper.invokeMethod(component, tawt, setter, Collections.singletonList(v), ObjectReference.INVOKE_SINGLE_THREADED);
return val;
} catch (InvalidTypeException ex) {
Exceptions.printStackTrace(ex);
return oldValue;
} catch (ClassNotLoadedException ex) {
Exceptions.printStackTrace(ex);
return oldValue;
} catch (IncompatibleThreadStateException ex) {
Exceptions.printStackTrace(ex);
return oldValue;
} catch (InternalExceptionWrapper iex) {
return oldValue;
} catch (ObjectCollectedExceptionWrapper ocex) {
NotifyDescriptor msg = new NotifyDescriptor.Message(ocex.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE);
DialogDisplayer.getDefault().notify(msg);
return oldValue;
} catch (VMDisconnectedExceptionWrapper vmd) {
return oldValue;
} catch (final InvocationException ex) {
final InvocationExceptionTranslated iextr = new InvocationExceptionTranslated(ex, debugger);
iextr.setPreferredThread(t);
RequestProcessor.getDefault().post(new Runnable() {
@Override
public void run() {
iextr.getMessage();
iextr.getLocalizedMessage();
iextr.getCause();
iextr.getStackTrace();
Exceptions.printStackTrace(iextr);
//Exceptions.printStackTrace(ex);
}
}, 100);
//Exceptions.printStackTrace(iextr);
//Exceptions.printStackTrace(ex);
return oldValue;
} finally {
l.unlock();
}
}
@Override
public boolean canWrite() {
synchronized (valueLock) {
return setter != null && valueIsEditable;
}
}
@Override
public void setValue(final Object val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (!(val instanceof String)) {
throw new IllegalArgumentException("val = "+val);
}
final String oldValue;
final Type type;
synchronized (valueLock) {
oldValue = value;
type = valueType;
value = valueCalculating;
}
debugger.getRequestProcessor().post(new Runnable() {
@Override
public void run() {
try {
RemoteServices.runOnStoppedThread(t, new Runnable() {
@Override
public void run() {
String v;
Throwable t = null;
try {
v = setValueLazy((String) val, oldValue, type);
} catch (Throwable th) {
if (th instanceof ThreadDeath) {
throw (ThreadDeath) th;
}
t = th;
v = oldValue;
}
synchronized (valueLock) {
value = v;
}
ci.firePropertyChange(propertyName, null, v);
if (t != null) {
Exceptions.printStackTrace(t);
}
}
}, sType);
} catch (PropertyVetoException ex) {
NotifyDescriptor msg = new NotifyDescriptor.Message(ex.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE);
DialogDisplayer.getDefault().notify(msg);
}
}
});
}
}
public static class FieldInfo {
private String name;
private Field f;
private JavaComponentInfo parent;
FieldInfo(Field f, JavaComponentInfo parent) {
this.name = f.name();
this.f = f;
this.parent = parent;
}
public String getName() {
return name;
}
public Field getField() {
return f;
}
public JavaComponentInfo getParent() {
return parent;
}
}
public static class Stack {
private Frame[] frames;
public Stack(Frame[] frames) {
this.frames = frames;
}
public Stack(CallStackFrame[] stackFrames) {
int n = stackFrames.length;
frames = new Frame[n];
for (int i = 0; i < n; i++) {
CallStackFrame sf = stackFrames[i];
try {
frames[i] = new Frame(sf.getClassName(), sf.getMethodName(), sf.getSourceName(null), sf.getLineNumber(null));
} catch (AbsentInformationException ex) {
frames[i] = new Frame(sf.getClassName(), sf.getMethodName(), null, sf.getLineNumber(null));
}
}
}
public Frame[] getFrames() {
return frames;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Stack with "+frames.length+" elements.");
for (Frame f : frames) {
sb.append("\n ");
sb.append(f.toString());
}
return sb.toString();
}
public static class Frame {
private String className;
private String methodName;
private String fileName;
private int lineNumber;
public Frame(String className, String methodName, String fileName, int lineNumber) {
this.className = className;
this.methodName = methodName;
this.fileName = fileName;
this.lineNumber = lineNumber;
}
/** Parse a stack trace frame line */
static Frame parseLine(String line) {
if (line.startsWith("at ")) {
line = line.substring(3);
}
int p = line.indexOf('(');
if (p < 0) {
return new Frame(line, "", "", 1);
}
int d = line.lastIndexOf('.', p);
int start = line.lastIndexOf(' ', p);
if (start < 0) start = 0;
String cn;
String mn;
if (d >= 0) {
cn = line.substring(start, d);
mn = line.substring(d + 1, p);
} else {
cn = line.substring(start, p);
mn = "";
}
p++;
int col = line.indexOf(':', p);
String fn;
int ln;
if (col > 0) {
fn = line.substring(p, col);
String lns = line.substring(col + 1);
if (lns.endsWith(")")) lns = lns.substring(0, lns.length() - 1);
try {
ln = Integer.parseInt(lns);
} catch (NumberFormatException nfex) {
ln = 1;
}
} else {
fn = line.substring(p);
if (fn.endsWith(")")) fn = fn.substring(0, fn.length() - 1);
ln = 1;
}
return new Frame(cn, mn, fn, ln);
}
public String getClassName() {
return className;
}
public String getMethodName() {
return methodName;
}
public String getFileName() {
return fileName;
}
public int getLineNumber() {
return lineNumber;
}
@Override
public String toString() {
return "Frame "+className+"."+methodName+"("+fileName+":"+lineNumber+")";
}
}
}
private static String escapeHTML(String message) {
if (message == null) {
return null;
}
int len = message.length();
StringBuilder result = new StringBuilder(len + 20);
char aChar;
for (int i = 0; i < len; i++) {
aChar = message.charAt(i);
switch (aChar) {
case '<':
result.append("&lt;");
break;
case '>':
result.append("&gt;");
break;
case '&':
result.append("&amp;");
break;
case '"':
result.append("&quot;");
break;
default:
result.append(aChar);
}
}
return result.toString();
}
}