0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.debugger.jpda;
0043:
0044: import com.sun.jdi.AbsentInformationException;
0045: import com.sun.jdi.Bootstrap;
0046: import com.sun.jdi.IncompatibleThreadStateException;
0047: import com.sun.jdi.InvalidStackFrameException;
0048: import com.sun.jdi.LocalVariable;
0049: import com.sun.jdi.Method;
0050: import com.sun.jdi.ObjectCollectedException;
0051: import com.sun.jdi.ObjectReference;
0052: import com.sun.jdi.ReferenceType;
0053: import com.sun.jdi.StackFrame;
0054: import com.sun.jdi.ThreadGroupReference;
0055: import com.sun.jdi.ThreadReference;
0056: import com.sun.jdi.TypeComponent;
0057: import com.sun.jdi.VMDisconnectedException;
0058: import com.sun.jdi.Value;
0059: import com.sun.jdi.VirtualMachine;
0060: import com.sun.jdi.request.EventRequest;
0061: import com.sun.jdi.request.EventRequestManager;
0062: import com.sun.jdi.request.InvalidRequestStateException;
0063:
0064: import java.beans.PropertyChangeEvent;
0065: import java.beans.PropertyChangeListener;
0066: import java.beans.PropertyChangeSupport;
0067: import java.beans.PropertyVetoException;
0068: import java.util.ArrayList;
0069: import java.util.Arrays;
0070: import java.util.Collection;
0071: import java.util.Collections;
0072: import java.util.HashSet;
0073: import java.util.Iterator;
0074: import java.util.List;
0075: import java.util.Set;
0076: import java.lang.reflect.InvocationTargetException;
0077: import java.util.HashMap;
0078: import java.util.Map;
0079: import java.util.logging.Level;
0080: import java.util.logging.Logger;
0081:
0082: import org.netbeans.api.debugger.DebuggerEngine;
0083: import org.netbeans.api.debugger.DebuggerInfo;
0084: import org.netbeans.api.debugger.DebuggerManager;
0085: import org.netbeans.api.debugger.LazyActionsManagerListener;
0086: import org.netbeans.api.debugger.Properties;
0087:
0088: import org.netbeans.api.debugger.jpda.InvalidExpressionException;
0089: import org.netbeans.api.debugger.jpda.JPDAClassType;
0090: import org.netbeans.api.debugger.jpda.JPDAThreadGroup;
0091: import org.netbeans.modules.debugger.jpda.actions.CompoundSmartSteppingListener;
0092: import org.netbeans.modules.debugger.jpda.expr.EvaluationException;
0093: import org.netbeans.modules.debugger.jpda.models.ObjectTranslation;
0094: import org.netbeans.modules.debugger.jpda.util.JPDAUtils;
0095: import org.netbeans.spi.debugger.ContextProvider;
0096: import org.netbeans.api.debugger.Session;
0097: import org.netbeans.api.debugger.jpda.AbstractDICookie;
0098: import org.netbeans.api.debugger.jpda.AttachingDICookie;
0099: import org.netbeans.api.debugger.jpda.CallStackFrame;
0100: import org.netbeans.api.debugger.jpda.DebuggerStartException;
0101: import org.netbeans.api.debugger.jpda.JPDABreakpoint;
0102: import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
0103: import org.netbeans.api.debugger.jpda.JPDADebugger;
0104: import org.netbeans.api.debugger.jpda.JPDAThread;
0105: import org.netbeans.api.debugger.jpda.SmartSteppingFilter;
0106: import org.netbeans.api.debugger.jpda.Variable;
0107: import org.netbeans.api.debugger.jpda.JPDAStep;
0108: import org.netbeans.api.debugger.jpda.ListeningDICookie;
0109:
0110: import org.netbeans.modules.debugger.jpda.breakpoints.BreakpointsEngineListener;
0111: import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
0112: import org.netbeans.modules.debugger.jpda.models.LocalsTreeModel;
0113: import org.netbeans.modules.debugger.jpda.models.ThreadsTreeModel;
0114: import org.netbeans.modules.debugger.jpda.models.CallStackFrameImpl;
0115: import org.netbeans.modules.debugger.jpda.models.JPDAClassTypeImpl;
0116: import org.netbeans.modules.debugger.jpda.util.Operator;
0117: import org.netbeans.modules.debugger.jpda.expr.Expression;
0118: import org.netbeans.modules.debugger.jpda.expr.EvaluationContext;
0119: import org.netbeans.modules.debugger.jpda.expr.EvaluationException2;
0120: import org.netbeans.modules.debugger.jpda.expr.Expression2;
0121: import org.netbeans.modules.debugger.jpda.expr.ParseException;
0122: import org.netbeans.spi.debugger.DebuggerEngineProvider;
0123: import org.netbeans.spi.debugger.DelegatingSessionProvider;
0124:
0125: import org.netbeans.spi.viewmodel.TreeModel;
0126: import org.openide.ErrorManager;
0127:
0128: /**
0129: * Representation of a debugging session.
0130: *
0131: * @author Jan Jancura
0132: */
0133: public class JPDADebuggerImpl extends JPDADebugger {
0134:
0135: private static final Logger logger = Logger
0136: .getLogger("org.netbeans.modules.debugger.jpda");
0137:
0138: private static final boolean SINGLE_THREAD_STEPPING = Boolean
0139: .getBoolean("netbeans.debugger.singleThreadStepping");
0140:
0141: // variables ...............................................................
0142:
0143: //private DebuggerEngine debuggerEngine;
0144: private VirtualMachine virtualMachine = null;
0145: private Exception exception;
0146: private int state = 0;
0147: private Operator operator;
0148: private PropertyChangeSupport pcs;
0149: public PropertyChangeSupport varChangeSupport = new PropertyChangeSupport(
0150: this );
0151: private JPDAThreadImpl currentThread;
0152: private CallStackFrame currentCallStackFrame;
0153: private int suspend = (SINGLE_THREAD_STEPPING) ? SUSPEND_EVENT_THREAD
0154: : SUSPEND_ALL;
0155: public final Object LOCK = new Object();
0156: private final Object LOCK2 = new Object();
0157: private boolean starting;
0158: private AbstractDICookie attachingCookie;
0159: private JavaEngineProvider javaEngineProvider;
0160: private Set<String> languages;
0161: private String lastStratumn;
0162: private ContextProvider lookupProvider;
0163: private ObjectTranslation threadsTranslation;
0164: private ObjectTranslation localsTranslation;
0165: private ExpressionPool expressionPool;
0166:
0167: private StackFrame altCSF = null; //PATCH 48174
0168:
0169: private boolean doContinue = true; // Whether resume() will actually resume
0170: private Boolean singleThreadStepResumeDecision = null;
0171: private Boolean stepInterruptByBptResumeDecision = null;
0172:
0173: // init ....................................................................
0174:
0175: public JPDADebuggerImpl(ContextProvider lookupProvider) {
0176: this .lookupProvider = lookupProvider;
0177: pcs = new PropertyChangeSupport(this );
0178: List l = lookupProvider.lookup(null,
0179: DebuggerEngineProvider.class);
0180: int i, k = l.size();
0181: for (i = 0; i < k; i++)
0182: if (l.get(i) instanceof JavaEngineProvider)
0183: javaEngineProvider = (JavaEngineProvider) l.get(i);
0184: if (javaEngineProvider == null)
0185: throw new IllegalArgumentException(
0186: "JavaEngineProvider have to be used to start JPDADebugger!");
0187: languages = new HashSet<String>();
0188: languages.add("Java");
0189: threadsTranslation = ObjectTranslation
0190: .createThreadTranslation(this );
0191: localsTranslation = ObjectTranslation
0192: .createLocalsTranslation(this );
0193: this .expressionPool = new ExpressionPool();
0194: }
0195:
0196: // JPDADebugger methods ....................................................
0197:
0198: /**
0199: * Returns current state of JPDA debugger.
0200: *
0201: * @return current state of JPDA debugger
0202: * @see #STATE_STARTING
0203: * @see #STATE_RUNNING
0204: * @see #STATE_STOPPED
0205: * @see #STATE_DISCONNECTED
0206: */
0207: public int getState() {
0208: return state;
0209: }
0210:
0211: /**
0212: * Gets value of suspend property.
0213: *
0214: * @return value of suspend property
0215: */
0216: public int getSuspend() {
0217: return suspend;
0218: }
0219:
0220: /**
0221: * Sets value of suspend property.
0222: *
0223: * @param s a new value of suspend property
0224: */
0225: public void setSuspend(int s) {
0226: if (s == suspend)
0227: return;
0228: int old = suspend;
0229: suspend = s;
0230: firePropertyChange(PROP_SUSPEND, new Integer(old), new Integer(
0231: s));
0232: }
0233:
0234: /**
0235: * Returns current thread or null.
0236: *
0237: * @return current thread or null
0238: */
0239: public JPDAThread getCurrentThread() {
0240: return currentThread;
0241: }
0242:
0243: /**
0244: * Returns current stack frame or null.
0245: *
0246: * @return current stack frame or null
0247: */
0248: public synchronized CallStackFrame getCurrentCallStackFrame() {
0249: if (currentCallStackFrame != null) {
0250: try {
0251: if (!currentCallStackFrame.getThread().isSuspended()) {
0252: currentCallStackFrame = null;
0253: }
0254: } catch (InvalidStackFrameException isfex) {
0255: currentCallStackFrame = null;
0256: }
0257: }
0258: if (currentCallStackFrame == null && currentThread != null) {
0259: try {
0260: currentCallStackFrame = currentThread
0261: .getCallStack(0, 1)[0];
0262: } catch (Exception ex) {
0263: }
0264: }
0265: return currentCallStackFrame;
0266: }
0267:
0268: /**
0269: * Evaluates given expression in the current context.
0270: *
0271: * @param expression a expression to be evaluated
0272: *
0273: * @return current value of given expression
0274: */
0275: public Variable evaluate(String expression)
0276: throws InvalidExpressionException {
0277: Value v = evaluateIn(expression);
0278: return getLocalsTreeModel().getVariable(v);
0279: }
0280:
0281: /**
0282: * Waits till the Virtual Machine is started and returns
0283: * {@link DebuggerStartException} if any.
0284: *
0285: * @throws DebuggerStartException is some problems occurres during debugger
0286: * start
0287: *
0288: * @see AbstractDICookie#getVirtualMachine()
0289: */
0290: public void waitRunning() throws DebuggerStartException {
0291: synchronized (LOCK2) {
0292: if (getState() == STATE_DISCONNECTED) {
0293: if (exception != null)
0294: throw new DebuggerStartException(exception);
0295: else
0296: return;
0297: }
0298: if (!starting && state != STATE_STARTING
0299: || exception != null) {
0300: return; // We're already running
0301: }
0302: try {
0303: LOCK2.wait();
0304: } catch (InterruptedException e) {
0305: throw new DebuggerStartException(e);
0306: }
0307:
0308: if (exception != null)
0309: throw new DebuggerStartException(exception);
0310: else
0311: return;
0312: }
0313: }
0314:
0315: /**
0316: * Returns <code>true</code> if this debugger supports Pop action.
0317: *
0318: * @return <code>true</code> if this debugger supports Pop action
0319: */
0320: public boolean canPopFrames() {
0321: VirtualMachine vm = getVirtualMachine();
0322: if (vm == null)
0323: return false;
0324: return vm.canPopFrames();
0325: }
0326:
0327: /**
0328: * Returns <code>true</code> if this debugger supports fix & continue
0329: * (HotSwap).
0330: *
0331: * @return <code>true</code> if this debugger supports fix & continue
0332: */
0333: public boolean canFixClasses() {
0334: VirtualMachine vm = getVirtualMachine();
0335: if (vm == null)
0336: return false;
0337: return vm.canRedefineClasses();
0338: }
0339:
0340: /**
0341: * Implements fix & continue (HotSwap). Map should contain class names
0342: * as a keys, and byte[] arrays as a values.
0343: *
0344: * @param classes a map from class names to be fixed to byte[]
0345: */
0346: public void fixClasses(Map<String, byte[]> classes) {
0347: synchronized (LOCK) {
0348:
0349: // 1) redefine classes
0350: Map<ReferenceType, byte[]> map = new HashMap<ReferenceType, byte[]>();
0351: Iterator<String> i = classes.keySet().iterator();
0352: VirtualMachine vm = getVirtualMachine();
0353: if (vm == null) {
0354: return; // The session has finished
0355: }
0356: while (i.hasNext()) {
0357: String className = i.next();
0358: List<ReferenceType> classRefs = vm
0359: .classesByName(className);
0360: int j, jj = classRefs.size();
0361: for (j = 0; j < jj; j++)
0362: map.put(classRefs.get(j), classes.get(className));
0363: }
0364: vm.redefineClasses(map);
0365:
0366: // update breakpoints
0367: fixBreakpoints();
0368:
0369: // 2) pop obsoleted frames
0370: JPDAThread t = getCurrentThread();
0371: if (t != null && t.isSuspended()) {
0372: CallStackFrame frame = getCurrentCallStackFrame();
0373:
0374: //PATCH #52209
0375: if (t.getStackDepth() < 2 && frame.isObsolete())
0376: return;
0377: try {
0378: if (!frame.equals(t.getCallStack(0, 1)[0]))
0379: return;
0380: } catch (AbsentInformationException ex) {
0381: return;
0382: }
0383:
0384: //PATCH #52209
0385: if (frame.isObsolete()
0386: && ((CallStackFrameImpl) frame).canPop()) {
0387: frame.popFrame();
0388: setState(STATE_RUNNING);
0389: updateCurrentCallStackFrame(t);
0390: setState(STATE_STOPPED);
0391: }
0392: }
0393:
0394: }
0395: }
0396:
0397: public void fixBreakpoints() {
0398: Session s = getSession();
0399: DebuggerEngine de = s.getEngineForLanguage("Java");
0400: BreakpointsEngineListener bel = null;
0401: List lazyListeners = de.lookup(null,
0402: LazyActionsManagerListener.class);
0403: for (int li = 0; li < lazyListeners.size(); li++) {
0404: Object service = lazyListeners.get(li);
0405: if (service instanceof BreakpointsEngineListener) {
0406: bel = (BreakpointsEngineListener) service;
0407: break;
0408: }
0409: }
0410: // Just reset the time stamp so that new line numbers are taken.
0411: EditorContextBridge.getContext().disposeTimeStamp(this );
0412: EditorContextBridge.getContext().createTimeStamp(this );
0413: bel.fixBreakpointImpls();
0414: }
0415:
0416: public Session getSession() {
0417: return lookupProvider.lookupFirst(null, Session.class);
0418: }
0419:
0420: private Boolean canBeModified;
0421: private Object canBeModifiedLock = new Object();
0422:
0423: public boolean canBeModified() {
0424: VirtualMachine vm = getVirtualMachine();
0425: if (vm == null)
0426: return false;
0427: synchronized (canBeModifiedLock) {
0428: if (canBeModified == null) {
0429: try {
0430: java.lang.reflect.Method canBeModifiedMethod = com.sun.jdi.VirtualMachine.class
0431: .getMethod("canBeModified", new Class[] {});
0432: Object modifiable = canBeModifiedMethod.invoke(vm,
0433: new Object[] {});
0434: canBeModified = (Boolean) modifiable;
0435: } catch (NoSuchMethodException nsmex) {
0436: // On JDK 1.4 we do not know... we suppose that can
0437: canBeModified = Boolean.TRUE;
0438: } catch (IllegalAccessException iaex) {
0439: canBeModified = Boolean.TRUE;
0440: } catch (InvocationTargetException itex) {
0441: canBeModified = Boolean.TRUE;
0442: }
0443: }
0444: return canBeModified.booleanValue();
0445: }
0446: // return vm.canBeModified(); -- After we'll build on JDK 1.5
0447: }
0448:
0449: private SmartSteppingFilter smartSteppingFilter;
0450:
0451: /**
0452: * Returns instance of SmartSteppingFilter.
0453: *
0454: * @return instance of SmartSteppingFilter
0455: */
0456: public SmartSteppingFilter getSmartSteppingFilter() {
0457: if (smartSteppingFilter == null) {
0458: smartSteppingFilter = lookupProvider.lookupFirst(null,
0459: SmartSteppingFilter.class);
0460: smartSteppingFilter.addExclusionPatterns((Set) Properties
0461: .getDefault().getProperties("debugger")
0462: .getProperties("sources").getProperties(
0463: "class_filters").getCollection("enabled",
0464: Collections.EMPTY_SET));
0465: }
0466: return smartSteppingFilter;
0467: }
0468:
0469: CompoundSmartSteppingListener compoundSmartSteppingListener;
0470:
0471: private CompoundSmartSteppingListener getCompoundSmartSteppingListener() {
0472: if (compoundSmartSteppingListener == null)
0473: compoundSmartSteppingListener = lookupProvider.lookupFirst(
0474: null, CompoundSmartSteppingListener.class);
0475: return compoundSmartSteppingListener;
0476: }
0477:
0478: /**
0479: * Test whether we should stop here according to the smart-stepping rules.
0480: */
0481: boolean stopHere(JPDAThread t) {
0482: return getCompoundSmartSteppingListener().stopHere(
0483: lookupProvider, t, getSmartSteppingFilter());
0484: }
0485:
0486: /**
0487: * Helper method that fires JPDABreakpointEvent on JPDABreakpoints.
0488: *
0489: * @param breakpoint a breakpoint to be changed
0490: * @param event a event to be fired
0491: */
0492: public void fireBreakpointEvent(JPDABreakpoint breakpoint,
0493: JPDABreakpointEvent event) {
0494: super .fireBreakpointEvent(breakpoint, event);
0495: }
0496:
0497: /**
0498: * Adds property change listener.
0499: *
0500: * @param l new listener.
0501: */
0502: public void addPropertyChangeListener(PropertyChangeListener l) {
0503: pcs.addPropertyChangeListener(l);
0504: }
0505:
0506: /**
0507: * Removes property change listener.
0508: *
0509: * @param l removed listener.
0510: */
0511: public void removePropertyChangeListener(PropertyChangeListener l) {
0512: pcs.removePropertyChangeListener(l);
0513: }
0514:
0515: /**
0516: * Adds property change listener.
0517: *
0518: * @param l new listener.
0519: */
0520: public void addPropertyChangeListener(String propertyName,
0521: PropertyChangeListener l) {
0522: pcs.addPropertyChangeListener(propertyName, l);
0523: }
0524:
0525: /**
0526: * Removes property change listener.
0527: *
0528: * @param l removed listener.
0529: */
0530: public void removePropertyChangeListener(String propertyName,
0531: PropertyChangeListener l) {
0532: pcs.removePropertyChangeListener(propertyName, l);
0533: }
0534:
0535: // internal interface ......................................................
0536:
0537: public void popFrames(ThreadReference thread, StackFrame frame) {
0538: synchronized (LOCK) {
0539: JPDAThreadImpl threadImpl = (JPDAThreadImpl) getThread(thread);
0540: setState(STATE_RUNNING);
0541: try {
0542: threadImpl.popFrames(frame);
0543: updateCurrentCallStackFrame(threadImpl);
0544: } catch (IncompatibleThreadStateException ex) {
0545: ErrorManager.getDefault().notify(ex);
0546: } finally {
0547: setState(STATE_STOPPED);
0548: }
0549: }
0550: }
0551:
0552: public void setException(Exception e) {
0553: synchronized (LOCK2) {
0554: exception = e;
0555: starting = false;
0556: LOCK2.notifyAll();
0557: }
0558: }
0559:
0560: public void setCurrentThread(JPDAThread thread) {
0561: Object oldT = currentThread;
0562: currentThread = (JPDAThreadImpl) thread;
0563: if (thread != oldT)
0564: firePropertyChange(PROP_CURRENT_THREAD, oldT, currentThread);
0565: updateCurrentCallStackFrame(thread);
0566: }
0567:
0568: /**
0569: * Set the current thread and call stack, but do not fire changes.
0570: * @return The PropertyChangeEvent associated with this change, it can have
0571: * attached other PropertyChangeEvents as a propagation ID.
0572: */
0573: private PropertyChangeEvent setCurrentThreadNoFire(JPDAThread thread) {
0574: Object oldT = currentThread;
0575: currentThread = (JPDAThreadImpl) thread;
0576: PropertyChangeEvent evt = null;
0577: if (thread != oldT)
0578: evt = new PropertyChangeEvent(this , PROP_CURRENT_THREAD,
0579: oldT, currentThread);
0580: PropertyChangeEvent evt2 = updateCurrentCallStackFrameNoFire(thread);
0581: if (evt == null)
0582: evt = evt2;
0583: else if (evt2 != null)
0584: evt.setPropagationId(evt2);
0585: return evt;
0586: }
0587:
0588: public void setCurrentCallStackFrame(CallStackFrame callStackFrame) {
0589: CallStackFrame old = setCurrentCallStackFrameNoFire(callStackFrame);
0590: if (old == callStackFrame)
0591: return;
0592: firePropertyChange(PROP_CURRENT_CALL_STACK_FRAME, old,
0593: callStackFrame);
0594: }
0595:
0596: private CallStackFrame setCurrentCallStackFrameNoFire(
0597: CallStackFrame callStackFrame) {
0598: CallStackFrame old;
0599: synchronized (this ) {
0600: if (callStackFrame == currentCallStackFrame)
0601: return callStackFrame;
0602: old = currentCallStackFrame;
0603: currentCallStackFrame = callStackFrame;
0604: }
0605: return old;
0606: }
0607:
0608: /**
0609: * Used by AbstractVariable.
0610: */
0611: public Value evaluateIn(String expression)
0612: throws InvalidExpressionException {
0613: Expression expr = null;
0614: try {
0615: expr = Expression.parse(expression,
0616: Expression.LANGUAGE_JAVA_1_5);
0617: return evaluateIn(expr);
0618: } catch (ParseException e) {
0619: InvalidExpressionException iee = new InvalidExpressionException(
0620: e.getMessage());
0621: iee.initCause(e);
0622: throw iee;
0623: }
0624: }
0625:
0626: //PATCH 48174
0627: public void setAltCSF(StackFrame sf) {
0628: altCSF = sf;
0629: }
0630:
0631: public StackFrame getAltCSF() {
0632: return altCSF;
0633: }
0634:
0635: /**
0636: * Used by WatchesModel & BreakpointImpl.
0637: */
0638: public Value evaluateIn(Expression expression)
0639: throws InvalidExpressionException {
0640: synchronized (LOCK) {
0641:
0642: CallStackFrameImpl csf = (CallStackFrameImpl) getCurrentCallStackFrame();
0643: if (csf != null) {
0644: JPDAThread frameThread = csf.getThread();
0645: try {
0646: Value value = evaluateIn(expression, csf
0647: .getStackFrame(), csf.getFrameDepth());
0648: try {
0649: csf.getThread();
0650: } catch (InvalidStackFrameException isfex) {
0651: // The frame is invalidated, set the new current...
0652: int depth = csf.getFrameDepth();
0653: try {
0654: CallStackFrame csf2 = frameThread
0655: .getCallStack(depth, depth + 1)[0];
0656: setCurrentCallStackFrameNoFire(csf2);
0657: } catch (AbsentInformationException aiex) {
0658: setCurrentCallStackFrame(null);
0659: }
0660: }
0661: return value;
0662: } catch (com.sun.jdi.VMDisconnectedException e) {
0663: // Causes kill action when something is being evaluated.
0664: return null;
0665: }
0666: }
0667: //PATCH 48174
0668: if (altCSF != null) {
0669: try {
0670: if (!altCSF.thread().isSuspended()) {
0671: altCSF = null; // Already invalid
0672: } else {
0673: // TODO XXX : Can be resumed in the mean time !!!!
0674: return evaluateIn(expression, altCSF, 0);
0675: }
0676: } catch (InvalidStackFrameException isfex) {
0677: // Will be thrown when the altCSF is invalid
0678: altCSF = null; // throw it
0679: } catch (com.sun.jdi.VMDisconnectedException e) {
0680: // Causes kill action when something is being evaluated.
0681: return null;
0682: }
0683: }
0684: throw new InvalidExpressionException(
0685: "No current context (stack frame)");
0686:
0687: }
0688: }
0689:
0690: private InvalidExpressionException methodCallsUnsupportedExc;
0691:
0692: /**
0693: * Used by BreakpointImpl.
0694: */
0695: public Value evaluateIn(Expression expression,
0696: final StackFrame frame, int frameDepth)
0697: throws InvalidExpressionException {
0698: synchronized (LOCK) {
0699: if (frame == null)
0700: throw new InvalidExpressionException(
0701: "No current context");
0702:
0703: // TODO: get imports from the source file
0704: List<String> imports = new ArrayList<String>();
0705: List<String> staticImports = new ArrayList<String>();
0706: imports.add("java.lang.*");
0707: try {
0708: imports.addAll(Arrays.asList(EditorContextBridge
0709: .getContext().getImports(
0710: getEngineContext()
0711: .getURL(frame, "Java"))));
0712: final ThreadReference tr = frame.thread();
0713: final List<EventRequest>[] disabledBreakpoints = new List[] { null };
0714: final JPDAThreadImpl[] resumedThread = new JPDAThreadImpl[] { null };
0715: boolean useNewEvaluator = !Boolean
0716: .getBoolean("debugger.evaluatorOld");
0717: EvaluationContext context;
0718: if (useNewEvaluator) {
0719: Expression2 expression2 = Expression2.parse(
0720: expression.getExpression(), expression
0721: .getLanguage());
0722: org.netbeans.modules.debugger.jpda.expr.TreeEvaluator evaluator2 = expression2
0723: .evaluator(context = new EvaluationContext(
0724: frame, frameDepth, imports,
0725: staticImports,
0726: methodCallsUnsupportedExc == null,
0727: new Runnable() {
0728: public void run() {
0729: if (disabledBreakpoints[0] == null) {
0730: JPDAThreadImpl theResumedThread = (JPDAThreadImpl) getThread(tr);
0731: try {
0732: theResumedThread
0733: .notifyMethodInvoking();
0734: } catch (PropertyVetoException pvex) {
0735: throw new RuntimeException(
0736: new InvalidExpressionException(
0737: pvex
0738: .getMessage()));
0739: }
0740: disabledBreakpoints[0] = disableAllBreakpoints();
0741: resumedThread[0] = theResumedThread;
0742: }
0743: }
0744: }, this ));
0745: try {
0746: return evaluator2.evaluate();
0747: } finally {
0748: if (methodCallsUnsupportedExc == null
0749: && !context.canInvokeMethods()) {
0750: methodCallsUnsupportedExc = new InvalidExpressionException(
0751: new UnsupportedOperationException());
0752: }
0753: if (disabledBreakpoints[0] != null) {
0754: enableAllBreakpoints(disabledBreakpoints[0]);
0755: }
0756: if (resumedThread[0] != null) {
0757: resumedThread[0].notifyMethodInvokeDone();
0758: }
0759: }
0760: } else {
0761: org.netbeans.modules.debugger.jpda.expr.Evaluator evaluator = expression
0762: .evaluator(context = new EvaluationContext(
0763: frame, frameDepth, imports,
0764: staticImports,
0765: methodCallsUnsupportedExc == null,
0766: new Runnable() {
0767: public void run() {
0768: if (disabledBreakpoints[0] == null) {
0769: JPDAThreadImpl theResumedThread = (JPDAThreadImpl) getThread(tr);
0770: try {
0771: theResumedThread
0772: .notifyMethodInvoking();
0773: } catch (PropertyVetoException pvex) {
0774: throw new RuntimeException(
0775: new InvalidExpressionException(
0776: pvex
0777: .getMessage()));
0778: }
0779: disabledBreakpoints[0] = disableAllBreakpoints();
0780: resumedThread[0] = theResumedThread;
0781: }
0782: }
0783: }, this ));
0784: try {
0785: return evaluator.evaluate();
0786: } finally {
0787: if (methodCallsUnsupportedExc == null
0788: && !context.canInvokeMethods()) {
0789: methodCallsUnsupportedExc = new InvalidExpressionException(
0790: new UnsupportedOperationException());
0791: }
0792: if (disabledBreakpoints[0] != null) {
0793: enableAllBreakpoints(disabledBreakpoints[0]);
0794: }
0795: if (resumedThread[0] != null) {
0796: resumedThread[0].notifyMethodInvokeDone();
0797: }
0798: }
0799: }
0800: } catch (EvaluationException e) {
0801: InvalidExpressionException iee = new InvalidExpressionException(
0802: e);
0803: iee.initCause(e);
0804: throw iee;
0805: } catch (EvaluationException2 e) {
0806: InvalidExpressionException iee = new InvalidExpressionException(
0807: e);
0808: iee.initCause(e);
0809: throw iee;
0810: } catch (IncompatibleThreadStateException itsex) {
0811: ErrorManager.getDefault().notify(itsex);
0812: IllegalStateException isex = new IllegalStateException(
0813: itsex.getLocalizedMessage());
0814: isex.initCause(itsex);
0815: throw isex;
0816: } catch (RuntimeException rex) {
0817: Throwable cause = rex.getCause();
0818: if (cause instanceof InvalidExpressionException) {
0819: throw (InvalidExpressionException) cause;
0820: } else {
0821: throw rex;
0822: }
0823: }
0824: }
0825: }
0826:
0827: /**
0828: * Used by AbstractVariable.
0829: */
0830: public Value invokeMethod(ObjectReference reference, Method method,
0831: Value[] arguments) throws InvalidExpressionException {
0832: if (currentThread == null)
0833: throw new InvalidExpressionException("No current context");
0834: synchronized (LOCK) {
0835: if (methodCallsUnsupportedExc != null) {
0836: throw methodCallsUnsupportedExc;
0837: }
0838: boolean threadSuspended = false;
0839: JPDAThread frameThread = null;
0840: CallStackFrameImpl csf = null;
0841: JPDAThreadImpl thread = null;
0842: List<EventRequest> l = null;
0843: try {
0844: // Remember the current stack frame, it might be necessary to re-set.
0845: csf = (CallStackFrameImpl) getCurrentCallStackFrame();
0846: if (csf != null) {
0847: try {
0848: frameThread = csf.getThread();
0849: } catch (InvalidStackFrameException isfex) {
0850: }
0851: }
0852: ThreadReference tr = getEvaluationThread();
0853: thread = (JPDAThreadImpl) getThread(tr);
0854: synchronized (thread) {
0855: threadSuspended = thread.isSuspended();
0856: if (!threadSuspended) {
0857: throw new InvalidExpressionException(
0858: "No current context");
0859: }
0860: try {
0861: thread.notifyMethodInvoking();
0862: } catch (PropertyVetoException pvex) {
0863: throw new InvalidExpressionException(pvex
0864: .getMessage());
0865: }
0866: }
0867: l = disableAllBreakpoints();
0868: return org.netbeans.modules.debugger.jpda.expr.TreeEvaluator
0869: .invokeVirtual(reference, method, tr, Arrays
0870: .asList(arguments));
0871: } catch (InvalidExpressionException ieex) {
0872: if (ieex.getTargetException() instanceof UnsupportedOperationException) {
0873: methodCallsUnsupportedExc = ieex;
0874: }
0875: throw ieex;
0876: } finally {
0877: if (l != null) {
0878: enableAllBreakpoints(l);
0879: }
0880: if (threadSuspended) {
0881: thread.notifyMethodInvokeDone();
0882: }
0883: if (frameThread != null) {
0884: try {
0885: csf.getThread();
0886: } catch (InvalidStackFrameException isfex) {
0887: // The current frame is invalidated, set the new current...
0888: int depth = csf.getFrameDepth();
0889: try {
0890: CallStackFrame csf2 = frameThread
0891: .getCallStack(depth, depth + 1)[0];
0892: setCurrentCallStackFrameNoFire(csf2);
0893: } catch (AbsentInformationException aiex) {
0894: setCurrentCallStackFrame(null);
0895: }
0896: }
0897: }
0898: }
0899: }
0900: }
0901:
0902: public static String getGenericSignature(TypeComponent component) {
0903: if (tcGenericSignatureMethod == null)
0904: return null;
0905: try {
0906: return (String) tcGenericSignatureMethod.invoke(component,
0907: new Object[0]);
0908: } catch (IllegalAccessException e) {
0909: e.printStackTrace();
0910: return null; // should not happen
0911: } catch (InvocationTargetException e) {
0912: e.printStackTrace();
0913: return null; // should not happen
0914: }
0915: }
0916:
0917: public static String getGenericSignature(LocalVariable component) {
0918: if (lvGenericSignatureMethod == null)
0919: return null;
0920: try {
0921: return (String) lvGenericSignatureMethod.invoke(component,
0922: new Object[0]);
0923: } catch (IllegalAccessException e) {
0924: e.printStackTrace();
0925: return null; // should not happen
0926: } catch (InvocationTargetException e) {
0927: e.printStackTrace();
0928: return null; // should not happen
0929: }
0930: }
0931:
0932: public VirtualMachine getVirtualMachine() {
0933: return virtualMachine;
0934: }
0935:
0936: public Operator getOperator() {
0937: return operator;
0938: }
0939:
0940: public void setStarting() {
0941: setState(STATE_STARTING);
0942: }
0943:
0944: public synchronized void setAttaching(AbstractDICookie cookie) {
0945: this .attachingCookie = cookie;
0946: }
0947:
0948: public void setRunning(VirtualMachine vm, Operator o) {
0949: if (logger.isLoggable(Level.FINE)) {
0950: logger.fine("Start - JPDADebuggerImpl.setRunning ()");
0951: JPDAUtils.printFeatures(logger, vm);
0952: }
0953: synchronized (LOCK2) {
0954: starting = true;
0955: }
0956: synchronized (this ) {
0957: virtualMachine = vm;
0958: }
0959: synchronized (canBeModifiedLock) {
0960: canBeModified = null; // Reset the can be modified flag
0961: }
0962:
0963: initGenericsSupport();
0964: EditorContextBridge.getContext().createTimeStamp(this );
0965:
0966: operator = o;
0967:
0968: // Iterator i = getVirtualMachine ().allThreads ().iterator ();
0969: // while (i.hasNext ()) {
0970: // ThreadReference tr = (ThreadReference) i.next ();
0971: // if (tr.isSuspended ()) {
0972: // if (startVerbose)
0973: // System.out.println("\nS JPDADebuggerImpl.setRunning () - " +
0974: // "thread supended"
0975: // );
0976: // setState (STATE_RUNNING);
0977: // synchronized (LOCK) {
0978: // virtualMachine.resume ();
0979: // }
0980: // if (startVerbose)
0981: // System.out.println("\nS JPDADebuggerImpl.setRunning () - " +
0982: // "thread supended - VM resumed - end"
0983: // );
0984: // synchronized (LOCK2) {
0985: // LOCK2.notify ();
0986: // }
0987: // return;
0988: // }
0989: // }
0990:
0991: setState(STATE_RUNNING);
0992: synchronized (this ) {
0993: vm = virtualMachine; // re-take the VM, it can be nulled by finish()
0994: }
0995: if (vm != null) {
0996: synchronized (LOCK) {
0997: vm.resume();
0998: }
0999: }
1000:
1001: logger
1002: .fine(" JPDADebuggerImpl.setRunning () finished, VM resumed.");
1003: synchronized (LOCK2) {
1004: starting = false;
1005: LOCK2.notifyAll();
1006: }
1007: }
1008:
1009: /**
1010: * Performs stop action.
1011: */
1012: public void setStoppedState(ThreadReference thread) {
1013: PropertyChangeEvent evt;
1014: synchronized (LOCK) {
1015: // this method can be called in stopped state to switch
1016: // the current thread only
1017: JPDAThread t = getThread(thread);
1018: checkJSR45Languages(t);
1019: evt = setCurrentThreadNoFire(t);
1020: PropertyChangeEvent evt2 = setStateNoFire(STATE_STOPPED);
1021:
1022: if (evt == null)
1023: evt = evt2;
1024: else if (evt2 != null) {
1025: PropertyChangeEvent evt3 = evt;
1026: while (evt3.getPropagationId() != null)
1027: evt3 = (PropertyChangeEvent) evt3
1028: .getPropagationId();
1029: evt3.setPropagationId(evt2);
1030: }
1031: }
1032: if (evt != null) {
1033: do {
1034: firePropertyChange(evt);
1035: evt = (PropertyChangeEvent) evt.getPropagationId();
1036: } while (evt != null);
1037: }
1038: }
1039:
1040: /**
1041: * Can be called if the current thread is resumed after stop.
1042: */
1043: public void setRunningState() {
1044: setState(STATE_RUNNING);
1045: }
1046:
1047: /**
1048: * Performs stop action and disable a next call to resume()
1049: */
1050: public void setStoppedStateNoContinue(ThreadReference thread) {
1051: PropertyChangeEvent evt;
1052: synchronized (LOCK) {
1053: // this method can be called in stopped state to switch
1054: // the current thread only
1055: evt = setStateNoFire(STATE_RUNNING);
1056: JPDAThread t = getThread(thread);
1057: checkJSR45Languages(t);
1058: PropertyChangeEvent evt2 = setCurrentThreadNoFire(t);
1059:
1060: if (evt == null)
1061: evt = evt2;
1062: else if (evt2 != null)
1063: evt.setPropagationId(evt2);
1064:
1065: evt2 = setStateNoFire(STATE_STOPPED);
1066:
1067: if (evt == null)
1068: evt = evt2;
1069: else if (evt2 != null) {
1070: PropertyChangeEvent evt3 = evt;
1071: while (evt3.getPropagationId() != null)
1072: evt3 = (PropertyChangeEvent) evt3
1073: .getPropagationId();
1074: evt3.setPropagationId(evt2);
1075: }
1076:
1077: doContinue = false;
1078: }
1079: if (evt != null) {
1080: do {
1081: firePropertyChange(evt);
1082: evt = (PropertyChangeEvent) evt.getPropagationId();
1083: } while (evt != null);
1084: }
1085: }
1086:
1087: private boolean finishing;
1088:
1089: /**
1090: * Used by KillActionProvider.
1091: */
1092: public void finish() {
1093: //Workaround for #56233
1094: //synchronized (LOCK) {
1095: synchronized (this ) {
1096: if (finishing) {
1097: // Can easily be called twice - from the operator termination
1098: return;
1099: }
1100: finishing = true;
1101: }
1102: logger.fine("StartActionProvider.finish ()");
1103: AbstractDICookie di = lookupProvider.lookupFirst(null,
1104: AbstractDICookie.class);
1105: if (getState() == STATE_DISCONNECTED)
1106: return;
1107: Operator o = getOperator();
1108: if (o != null)
1109: o.stop();
1110: synchronized (this ) {
1111: if (attachingCookie != null) {
1112: if (attachingCookie instanceof ListeningDICookie) {
1113: ListeningDICookie listeningCookie = (ListeningDICookie) attachingCookie;
1114: try {
1115: listeningCookie.getListeningConnector()
1116: .stopListening(
1117: listeningCookie.getArgs());
1118: } catch (java.io.IOException ioex) {
1119: } catch (com.sun.jdi.connect.IllegalConnectorArgumentsException icaex) {
1120: } catch (IllegalArgumentException iaex) {
1121: }
1122: }
1123: }
1124: }
1125: try {
1126: waitRunning(); // First wait till the debugger comes up
1127: } catch (DebuggerStartException dsex) {
1128: // We do not want to start it anyway when we're finishing - do not bother
1129: }
1130: VirtualMachine vm;
1131: synchronized (this ) {
1132: vm = virtualMachine;
1133: }
1134: if (vm != null) {
1135: try {
1136: if (di instanceof AttachingDICookie) {
1137: logger
1138: .fine(" StartActionProvider.finish() VM dispose");
1139: vm.dispose();
1140: } else {
1141: logger
1142: .fine(" StartActionProvider.finish() VM exit");
1143: vm.exit(0);
1144: }
1145: } catch (VMDisconnectedException e) {
1146: logger
1147: .fine(" StartActionProvider.finish() VM exception "
1148: + e);
1149: // debugee VM is already disconnected (it finished normally)
1150: }
1151: }
1152: synchronized (this ) {
1153: virtualMachine = null;
1154: }
1155: setState(STATE_DISCONNECTED);
1156: if (jsr45EngineProviders != null) {
1157: for (Iterator<JSR45DebuggerEngineProvider> i = jsr45EngineProviders
1158: .iterator(); i.hasNext();) {
1159: JSR45DebuggerEngineProvider provider = i.next();
1160: provider.getDesctuctor().killEngine();
1161: }
1162: jsr45EngineProviders = null;
1163: }
1164: javaEngineProvider.getDestructor().killEngine();
1165: logger.fine(" StartActionProvider.finish() end.");
1166:
1167: //Notify LOCK2 so that no one is waiting forever
1168: synchronized (LOCK2) {
1169: starting = false;
1170: LOCK2.notifyAll();
1171: }
1172: EditorContextBridge.getContext().disposeTimeStamp(this );
1173: //}
1174: }
1175:
1176: /**
1177: * Suspends the target virtual machine (if any).
1178: * Used by PauseActionProvider.
1179: *
1180: * @see com.sun.jdi.ThreadReference#suspend
1181: */
1182: public void suspend() {
1183: VirtualMachine vm;
1184: synchronized (this ) {
1185: vm = virtualMachine;
1186: }
1187: synchronized (LOCK) {
1188: if (getState() == STATE_STOPPED)
1189: return;
1190: if (vm != null) {
1191: logger.fine("VM suspend");
1192: vm.suspend();
1193: // Check the suspended count
1194: List<ThreadReference> threads = vm.allThreads();
1195: for (ThreadReference t : threads) {
1196: while (t.suspendCount() > 1)
1197: t.resume();
1198: }
1199: }
1200: setState(STATE_STOPPED);
1201: }
1202: notifySuspendAll();
1203: }
1204:
1205: public void notifySuspendAll() {
1206: Collection threads = threadsTranslation.getTranslated();
1207: for (Iterator it = threads.iterator(); it.hasNext();) {
1208: Object threadOrGroup = it.next();
1209: if (threadOrGroup instanceof JPDAThreadImpl) {
1210: int status = ((JPDAThreadImpl) threadOrGroup)
1211: .getState();
1212: boolean invalid = (status == JPDAThread.STATE_NOT_STARTED
1213: || status == JPDAThread.STATE_UNKNOWN || status == JPDAThread.STATE_ZOMBIE);
1214: if (!invalid) {
1215: try {
1216: ((JPDAThreadImpl) threadOrGroup)
1217: .notifySuspended();
1218: } catch (ObjectCollectedException ocex) {
1219: invalid = true;
1220: }
1221: }
1222: if (invalid) {
1223: threadsTranslation
1224: .remove(((JPDAThreadImpl) threadOrGroup)
1225: .getThreadReference());
1226: }
1227: }
1228: }
1229: }
1230:
1231: /**
1232: * Used by ContinueActionProvider & StepActionProvider.
1233: */
1234: public void resume() {
1235: synchronized (LOCK) {
1236: if (!doContinue) {
1237: doContinue = true;
1238: // Continue the next time and do nothing now.
1239: return;
1240: }
1241: }
1242: if (operator.flushStaledEvents()) {
1243: return;
1244: }
1245: setState(STATE_RUNNING);
1246: notifyToBeResumedAll();
1247: VirtualMachine vm;
1248: synchronized (this ) {
1249: vm = virtualMachine;
1250: }
1251: synchronized (LOCK) {
1252: if (vm != null) {
1253: logger.fine("VM resume");
1254: vm.resume();
1255: }
1256: }
1257: }
1258:
1259: /** DO NOT CALL FROM ANYWHERE BUT JPDAThreadImpl.resume(). */
1260: public boolean currentThreadToBeResumed() {
1261: synchronized (LOCK) {
1262: if (!doContinue) {
1263: doContinue = true;
1264: // Continue the next time and do nothing now.
1265: return false;
1266: }
1267: }
1268: if (operator.flushStaledEvents()) {
1269: return false;
1270: }
1271: setState(STATE_RUNNING);
1272: return true;
1273: }
1274:
1275: public void resumeCurrentThread() {
1276: synchronized (LOCK) {
1277: if (!doContinue) {
1278: doContinue = true;
1279: // Continue the next time and do nothing now.
1280: return;
1281: }
1282: }
1283: if (operator.flushStaledEvents()) {
1284: return;
1285: }
1286: setState(STATE_RUNNING);
1287: currentThread.resume();
1288: }
1289:
1290: public void notifyToBeResumedAll() {
1291: Collection threads = threadsTranslation.getTranslated();
1292: for (Iterator it = threads.iterator(); it.hasNext();) {
1293: Object threadOrGroup = it.next();
1294: if (threadOrGroup instanceof JPDAThreadImpl) {
1295: int status = ((JPDAThreadImpl) threadOrGroup)
1296: .getState();
1297: boolean invalid = (status == JPDAThread.STATE_NOT_STARTED
1298: || status == JPDAThread.STATE_UNKNOWN || status == JPDAThread.STATE_ZOMBIE);
1299: if (!invalid) {
1300: ((JPDAThreadImpl) threadOrGroup)
1301: .notifyToBeResumed();
1302: } else {
1303: threadsTranslation
1304: .remove(((JPDAThreadImpl) threadOrGroup)
1305: .getThreadReference());
1306: }
1307: }
1308: }
1309: }
1310:
1311: public JPDAThreadGroup[] getTopLevelThreadGroups() {
1312: VirtualMachine vm;
1313: synchronized (this ) {
1314: vm = virtualMachine;
1315: }
1316: if (vm == null) {
1317: return new JPDAThreadGroup[0];
1318: }
1319: List groupList;
1320: synchronized (LOCK) {
1321: groupList = vm.topLevelThreadGroups();
1322: }
1323: JPDAThreadGroup[] groups = new JPDAThreadGroup[groupList.size()];
1324: for (int i = 0; i < groups.length; i++) {
1325: groups[i] = getThreadGroup((ThreadGroupReference) groupList
1326: .get(i));
1327: }
1328: return groups;
1329: }
1330:
1331: public JPDAThread getThread(ThreadReference tr) {
1332: return (JPDAThread) threadsTranslation.translate(tr);
1333: }
1334:
1335: public JPDAThread getExistingThread(ThreadReference tr) {
1336: return (JPDAThread) threadsTranslation.translateExisting(tr);
1337: }
1338:
1339: public JPDAThreadGroup getThreadGroup(ThreadGroupReference tgr) {
1340: return (JPDAThreadGroup) threadsTranslation.translate(tgr);
1341: }
1342:
1343: public Variable getLocalVariable(LocalVariable lv, Value v) {
1344: return (Variable) localsTranslation.translate(lv, v);
1345: }
1346:
1347: public JPDAClassType getClassType(ReferenceType cr) {
1348: return (JPDAClassType) localsTranslation.translate(cr);
1349: }
1350:
1351: public Variable getVariable(Value value) {
1352: return getLocalsTreeModel().getVariable(value);
1353: }
1354:
1355: public ExpressionPool getExpressionPool() {
1356: return expressionPool;
1357: }
1358:
1359: synchronized void setSingleThreadStepResumeDecision(Boolean decision) {
1360: singleThreadStepResumeDecision = decision;
1361: }
1362:
1363: synchronized Boolean getSingleThreadStepResumeDecision() {
1364: return singleThreadStepResumeDecision;
1365: }
1366:
1367: public synchronized void setStepInterruptByBptResumeDecision(
1368: Boolean decision) {
1369: stepInterruptByBptResumeDecision = decision;
1370: }
1371:
1372: public synchronized Boolean getStepInterruptByBptResumeDecision() {
1373: return stepInterruptByBptResumeDecision;
1374: }
1375:
1376: // private helper methods ..................................................
1377:
1378: private static final java.util.regex.Pattern jvmVersionPattern = java.util.regex.Pattern
1379: .compile("(\\d+)\\.(\\d+)\\.(\\d+)(_\\d+)?(-\\w+)?");
1380: private static java.lang.reflect.Method tcGenericSignatureMethod;
1381: private static java.lang.reflect.Method lvGenericSignatureMethod;
1382:
1383: private void initGenericsSupport() {
1384: tcGenericSignatureMethod = null;
1385: if (Bootstrap.virtualMachineManager().minorInterfaceVersion() >= 5) {
1386: VirtualMachine vm;
1387: synchronized (this ) {
1388: vm = virtualMachine;
1389: }
1390: if (vm == null)
1391: return;
1392: java.util.regex.Matcher m = jvmVersionPattern.matcher(vm
1393: .version());
1394: if (m.matches()) {
1395: int minor = Integer.parseInt(m.group(2));
1396: if (minor >= 5) {
1397: try {
1398: tcGenericSignatureMethod = TypeComponent.class
1399: .getMethod("genericSignature",
1400: new Class[0]);
1401: lvGenericSignatureMethod = LocalVariable.class
1402: .getMethod("genericSignature",
1403: new Class[0]);
1404: } catch (NoSuchMethodException e) {
1405: // the method is not available, ignore generics
1406: }
1407: }
1408: }
1409: }
1410: }
1411:
1412: private PropertyChangeEvent setStateNoFire(int state) {
1413: if (state == this .state)
1414: return null;
1415: int o = this .state;
1416: this .state = state;
1417: //PENDING HACK see issue 46287
1418: System.setProperty(
1419: "org.openide.awt.SwingBrowserImpl.do-not-block-awt",
1420: String.valueOf(state != STATE_DISCONNECTED));
1421: return new PropertyChangeEvent(this , PROP_STATE,
1422: new Integer(o), new Integer(state));
1423: }
1424:
1425: private void setState(int state) {
1426: PropertyChangeEvent evt = setStateNoFire(state);
1427: if (evt != null) {
1428: firePropertyChange(evt);
1429: }
1430: }
1431:
1432: /**
1433: * Fires property change.
1434: */
1435: private void firePropertyChange(String name, Object o, Object n) {
1436: pcs.firePropertyChange(name, o, n);
1437: //System.err.println("ALL Change listeners count = "+pcs.getPropertyChangeListeners().length);
1438: }
1439:
1440: /**
1441: * Fires property change.
1442: */
1443: private void firePropertyChange(PropertyChangeEvent evt) {
1444: pcs.firePropertyChange(evt);
1445: //System.err.println("ALL Change listeners count = "+pcs.getPropertyChangeListeners().length);
1446: }
1447:
1448: private SourcePath engineContext;
1449:
1450: public synchronized SourcePath getEngineContext() {
1451: if (engineContext == null)
1452: engineContext = lookupProvider.lookupFirst(null,
1453: SourcePath.class);
1454: return engineContext;
1455: }
1456:
1457: private LocalsTreeModel localsTreeModel;
1458:
1459: private LocalsTreeModel getLocalsTreeModel() {
1460: if (localsTreeModel == null)
1461: localsTreeModel = (LocalsTreeModel) lookupProvider
1462: .lookupFirst("LocalsView", TreeModel.class);
1463: return localsTreeModel;
1464: }
1465:
1466: private ThreadReference getEvaluationThread() {
1467: if (currentThread != null)
1468: return currentThread.getThreadReference();
1469: VirtualMachine vm;
1470: synchronized (this ) {
1471: vm = virtualMachine;
1472: }
1473: if (vm == null)
1474: return null;
1475: List l = vm.allThreads();
1476: if (l.size() < 1)
1477: return null;
1478: int i, k = l.size();
1479: ThreadReference thread = null;
1480: for (i = 0; i < k; i++) {
1481: ThreadReference t = (ThreadReference) l.get(i);
1482: if (t.isSuspended()) {
1483: thread = t;
1484: if (t.name().equals("Finalizer"))
1485: return t;
1486: }
1487: }
1488: return thread;
1489: }
1490:
1491: private void updateCurrentCallStackFrame(JPDAThread thread) {
1492: if ((thread == null) || (thread.getStackDepth() < 1))
1493: setCurrentCallStackFrame(null);
1494: else
1495: try {
1496: setCurrentCallStackFrame(thread.getCallStack(0, 1)[0]);
1497: } catch (AbsentInformationException e) {
1498: setCurrentCallStackFrame(null);
1499: }
1500: }
1501:
1502: /**
1503: * @param thread The thread to take the top frame from
1504: * @return A PropertyChangeEvent or <code>null</code>.
1505: */
1506: private PropertyChangeEvent updateCurrentCallStackFrameNoFire(
1507: JPDAThread thread) {
1508: CallStackFrame old;
1509: CallStackFrame callStackFrame;
1510: if ((thread == null) || (thread.getStackDepth() < 1))
1511: old = setCurrentCallStackFrameNoFire(callStackFrame = null);
1512: else
1513: try {
1514: old = setCurrentCallStackFrameNoFire(callStackFrame = thread
1515: .getCallStack(0, 1)[0]);
1516: } catch (AbsentInformationException e) {
1517: old = setCurrentCallStackFrameNoFire(callStackFrame = null);
1518: }
1519: if (old == callStackFrame)
1520: return null;
1521: else
1522: return new PropertyChangeEvent(this ,
1523: PROP_CURRENT_CALL_STACK_FRAME, old, callStackFrame);
1524: }
1525:
1526: private List<EventRequest> disableAllBreakpoints() {
1527: logger.fine("disableAllBreakpoints() start.");
1528: List<EventRequest> l = new ArrayList<EventRequest>();
1529: VirtualMachine vm = getVirtualMachine();
1530: if (vm == null)
1531: return l;
1532: EventRequestManager erm = vm.eventRequestManager();
1533: l.addAll(erm.accessWatchpointRequests());
1534: l.addAll(erm.breakpointRequests());
1535: l.addAll(erm.classPrepareRequests());
1536: l.addAll(erm.classUnloadRequests());
1537: l.addAll(erm.exceptionRequests());
1538: l.addAll(erm.methodEntryRequests());
1539: l.addAll(erm.methodExitRequests());
1540: l.addAll(erm.modificationWatchpointRequests());
1541: // l.addAll (erm.stepRequests ());
1542: l.addAll(erm.threadDeathRequests());
1543: l.addAll(erm.threadStartRequests());
1544: int i = l.size() - 1;
1545: for (; i >= 0; i--)
1546: if (!l.get(i).isEnabled())
1547: l.remove(i);
1548: else
1549: l.get(i).disable();
1550: operator.breakpointsDisabled();
1551: logger.fine("disableAllBreakpoints() end.");
1552: return l;
1553: }
1554:
1555: private void enableAllBreakpoints(List<EventRequest> l) {
1556: logger.fine("enableAllBreakpoints() start.");
1557: operator.breakpointsEnabled();
1558: int i, k = l.size();
1559: for (i = 0; i < k; i++)
1560: try {
1561: l.get(i).enable();
1562: } catch (IllegalThreadStateException ex) {
1563: // see #53163
1564: // this can occurre if there is some "old" StepRequest and
1565: // thread named in the request has died
1566: } catch (InvalidRequestStateException ex) {
1567: // workaround for #51176
1568: }
1569: logger.fine("enableAllBreakpoints() end.");
1570: }
1571:
1572: private void checkJSR45Languages(JPDAThread t) {
1573: if (t.getStackDepth() > 0)
1574: try {
1575: CallStackFrame f = t.getCallStack(0, 1)[0];
1576: List l = f.getAvailableStrata();
1577: int i, k = l.size();
1578: for (i = 0; i < k; i++) {
1579: if (!languages.contains(l.get(i))) {
1580: String language = (String) l.get(i);
1581: DebuggerManager
1582: .getDebuggerManager()
1583: .startDebugging(createJSR45DI(language));
1584: languages.add(language);
1585: }
1586: } // for
1587: String stratum = f.getDefaultStratum();
1588: if ((stratum != null)
1589: && (!stratum.equals(lastStratumn)))
1590: javaEngineProvider.getSession().setCurrentLanguage(
1591: stratum);
1592: lastStratumn = stratum;
1593: } catch (AbsentInformationException e) {
1594: System.out.println("NoInformationException");
1595: }
1596: }
1597:
1598: private Set<JSR45DebuggerEngineProvider> jsr45EngineProviders;
1599:
1600: private DebuggerInfo createJSR45DI(final String language) {
1601: if (jsr45EngineProviders == null) {
1602: jsr45EngineProviders = new HashSet<JSR45DebuggerEngineProvider>(
1603: 1);
1604: }
1605: JSR45DebuggerEngineProvider provider = new JSR45DebuggerEngineProvider(
1606: language);
1607: jsr45EngineProviders.add(provider);
1608: return DebuggerInfo.create("netbeans-jpda-JSR45DICookie-"
1609: + language, new Object[] {
1610: new DelegatingSessionProvider() {
1611: public Session getSession(DebuggerInfo debuggerInfo) {
1612: return javaEngineProvider.getSession();
1613: }
1614: }, provider });
1615: }
1616:
1617: public JPDAStep createJPDAStep(int size, int depth) {
1618: Session session = lookupProvider.lookupFirst(null,
1619: Session.class);
1620: return new JPDAStepImpl(this , session, size, depth);
1621: }
1622:
1623: /*public synchronized Heap getHeap() {
1624: if (virtualMachine != null && canGetInstanceInfo(virtualMachine)) {
1625: return new HeapImpl(virtualMachine);
1626: } else {
1627: return null;
1628: }
1629: }*/
1630:
1631: public List<JPDAClassType> getAllClasses() {
1632: List<ReferenceType> classes;
1633: synchronized (this ) {
1634: if (virtualMachine == null) {
1635: classes = Collections.emptyList();
1636: } else {
1637: classes = virtualMachine.allClasses();
1638: }
1639: }
1640: return new ClassTypeList(this , classes);
1641: }
1642:
1643: public List<JPDAClassType> getClassesByName(String name) {
1644: List<ReferenceType> classes;
1645: synchronized (this ) {
1646: if (virtualMachine == null) {
1647: classes = Collections.emptyList();
1648: } else {
1649: classes = virtualMachine.classesByName(name);
1650: }
1651: }
1652: return new ClassTypeList(this , classes);
1653: }
1654:
1655: public long[] getInstanceCounts(List<JPDAClassType> classTypes)
1656: throws UnsupportedOperationException {
1657: if (Java6Methods.isJDK6()) {
1658: VirtualMachine vm;
1659: synchronized (this ) {
1660: vm = virtualMachine;
1661: }
1662: if (vm == null) {
1663: return new long[classTypes.size()];
1664: }
1665: if (classTypes instanceof ClassTypeList) {
1666: ClassTypeList cl = (ClassTypeList) classTypes;
1667: return Java6Methods.instanceCounts(vm, cl.getTypes());
1668: } else {
1669: List<ReferenceType> types = new ArrayList<ReferenceType>(
1670: classTypes.size());
1671: for (JPDAClassType clazz : classTypes) {
1672: types.add(((JPDAClassTypeImpl) clazz).getType());
1673: }
1674: return Java6Methods.instanceCounts(vm, types);
1675: }
1676: } else {
1677: throw new UnsupportedOperationException("Not supported.");
1678: }
1679: }
1680:
1681: public synchronized boolean canGetInstanceInfo() {
1682: return virtualMachine != null
1683: && canGetInstanceInfo(virtualMachine);
1684: }
1685:
1686: private static boolean canGetInstanceInfo(VirtualMachine vm) {
1687: if (Java6Methods.isJDK6()) {
1688: try {
1689: java.lang.reflect.Method canGetInstanceInfoMethod = VirtualMachine.class
1690: .getMethod("canGetInstanceInfo", new Class[] {});
1691: Object canGetInstanceInfo = canGetInstanceInfoMethod
1692: .invoke(vm, new Object[] {});
1693: return Boolean.TRUE.equals(canGetInstanceInfo);
1694: } catch (Exception ex) {
1695: ErrorManager.getDefault().notify(ex);
1696: }
1697: }
1698: return false;
1699: }
1700: }
|