2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.debugger.jpda.models;
44
import com.sun.jdi.ArrayReference;
45
import com.sun.jdi.CharValue;
46
import com.sun.jdi.ClassObjectReference;
47
import com.sun.jdi.ClassType;
48
import com.sun.jdi.Field;
49
import com.sun.jdi.ObjectCollectedException;
50
import com.sun.jdi.ObjectReference;
51
import com.sun.jdi.PrimitiveValue;
52
import com.sun.jdi.ReferenceType;
53
import com.sun.jdi.StringReference;
54
import com.sun.jdi.Value;
55
import com.sun.jdi.VoidValue;
56
import com.sun.jdi.VMDisconnectedException;
57
import java.beans.Customizer;
58
import java.beans.PropertyChangeEvent;
60
import java.beans.PropertyChangeListener;
61
import java.util.HashSet;
64
import org.netbeans.api.debugger.jpda.InvalidExpressionException;
65
import org.netbeans.api.debugger.jpda.JPDAClassType;
66
import org.netbeans.api.debugger.jpda.Variable;
67
import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
68
import org.netbeans.modules.debugger.jpda.expr.JDIVariable;
69
import org.openide.util.NbBundle;
75
class AbstractVariable implements JDIVariable, Customizer, Cloneable {
76
// Customized for add/removePropertyChangeListener
77
// Cloneable for fixed watches
80
private JPDADebuggerImpl debugger;
83
private Set<PropertyChangeListener> listeners = new HashSet<PropertyChangeListener>();
87
JPDADebuggerImpl debugger,
91
this.debugger = debugger;
95
this.id = Integer.toString(super.hashCode());
99
// public interface ........................................................
102
* Returns string representation of type of this variable.
104
* @return string representation of type of this variable.
106
public String getValue () {
107
Value v = getInnerValue ();
111
static String getValue (Value v) {
112
if (v == null) return "null";
113
if (v instanceof VoidValue) return "void";
114
if (v instanceof CharValue)
115
return "\'" + v.toString () + "\'";
116
if (v instanceof PrimitiveValue)
117
return v.toString ();
118
if (v instanceof StringReference)
120
((StringReference) v).value ()
122
if (v instanceof ClassObjectReference)
123
return "class " + ((ClassObjectReference) v).reflectedType ().name ();
124
if (v instanceof ArrayReference)
125
return "#" + ((ArrayReference) v).uniqueID () +
126
"(length=" + ((ArrayReference) v).length () + ")";
127
return "#" + ((ObjectReference) v).uniqueID ();
131
* Sets string representation of value of this variable.
133
* @param value string representation of value of this variable.
135
public void setValue (String expression) throws InvalidExpressionException {
136
String oldValue = getValue();
137
if (expression.equals(oldValue)) {
138
return ; // Do nothing, since the values are identical
141
Value oldV = getInnerValue();
142
if (oldV instanceof CharValue && expression.startsWith("'") && expression.endsWith("'") && expression.length() > 1) {
143
value = oldV.virtualMachine().mirrorOf(expression.charAt(1));
144
} else if ((oldV instanceof StringReference || oldV == null) &&
145
expression.startsWith("\"") && expression.endsWith("\"") && expression.length() > 1) {
146
value = debugger.getVirtualMachine().mirrorOf(expression.substring(1, expression.length() - 1));
147
} else if (oldV instanceof ObjectReference &&
148
((ObjectReference) oldV).referenceType() instanceof ClassType &&
149
((ClassType) ((ObjectReference) oldV).referenceType()).isEnum()) {
150
ClassType enumType = (ClassType) ((ObjectReference) oldV).referenceType();
151
Field enumValue = enumType.fieldByName(expression);
152
if (enumValue != null) {
153
value = enumType.getValue(enumValue);
155
throw new InvalidExpressionException(expression);
157
} else if ("null".equals(expression)) {
160
// evaluate expression to Value
161
Value evaluatedValue = debugger.evaluateIn (expression);
162
if (!(evaluatedValue instanceof PrimitiveValue)) {
163
throw new InvalidExpressionException(expression);
165
value = (PrimitiveValue) evaluatedValue;
167
// set new value to remote veriable
169
// set new value to this model
170
setInnerValue (value);
172
PropertyChangeEvent evt = new PropertyChangeEvent(this, "value", null, value);
174
synchronized (listeners) {
175
ls = listeners.toArray();
177
for (int i = 0; i < ls.length; i++) {
178
((PropertyChangeListener) ls[i]).propertyChange(evt);
180
//pchs.firePropertyChange("value", null, value);
181
//getModel ().fireTableValueChangedChanged (this, null);
185
* Override, but do not call directly!
187
protected void setValue (Value value) throws InvalidExpressionException {
188
throw new InternalError ();
191
public void setObject(Object bean) {
193
if (bean instanceof String) {
194
setValue((String) bean);
195
//} else if (bean instanceof Value) {
196
// setValue((Value) bean); -- do not call directly
198
throw new IllegalArgumentException(""+bean);
200
} catch (InvalidExpressionException ieex) {
201
IllegalArgumentException iaex = new IllegalArgumentException(ieex.getLocalizedMessage());
202
iaex.initCause(ieex);
208
* Declared type of this local.
210
* @return declared type of this local
212
public String getType () {
213
if (getInnerValue () == null) return "";
215
return this.getInnerValue().type().name ();
216
} catch (VMDisconnectedException vmdex) {
217
// The session is gone.
218
return NbBundle.getMessage(AbstractVariable.class, "MSG_Disconnected");
219
} catch (ObjectCollectedException ocex) {
220
// The object is gone.
221
return NbBundle.getMessage(AbstractVariable.class, "MSG_ObjCollected");
225
public JPDAClassType getClassType() {
226
Value value = getInnerValue();
227
if (value == null) return null;
228
com.sun.jdi.Type type = value.type();
229
if (type instanceof ReferenceType) {
230
return new JPDAClassTypeImpl(debugger, (ReferenceType) type);
236
public boolean equals (Object o) {
237
return (o instanceof AbstractVariable) &&
238
(id.equals (((AbstractVariable) o).id));
241
public int hashCode () {
242
return id.hashCode ();
246
// other methods............................................................
248
protected Value getInnerValue () {
252
protected void setInnerValue (Value v) {
256
public Value getJDIValue() {
260
protected final JPDADebuggerImpl getDebugger() {
264
protected final String getID () {
268
private int cloneNumber = 1;
270
public Variable clone() {
271
AbstractVariable clon = new AbstractVariable(debugger, value, id + "_clone"+(cloneNumber++));
275
public void addPropertyChangeListener(PropertyChangeListener l) {
279
public void removePropertyChangeListener(PropertyChangeListener l) {
283
public String toString () {
287
/* Uncomment when needed. Was used to create "readable" String and Char values.
288
private static String convertToStringInitializer (String s) {
289
StringBuffer sb = new StringBuffer ();
290
int i, k = s.length ();
291
for (i = 0; i < k; i++)
292
switch (s.charAt (i)) {
315
sb.append (s.charAt (i));
317
return sb.toString();
320
private static String convertToCharInitializer (String s) {
321
StringBuffer sb = new StringBuffer ();
322
int i, k = s.length ();
323
for (i = 0; i < k; i++)
324
switch (s.charAt (i)) {
347
sb.append (s.charAt (i));
349
return sb.toString();