001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model.debug.jpda;
038:
039: import com.sun.jdi.*;
040: import com.sun.jdi.request.*;
041:
042: import java.util.Vector;
043: import java.util.List;
044: import java.io.File;
045:
046: import edu.rice.cs.drjava.model.*;
047: import edu.rice.cs.drjava.model.definitions.ClassNameNotFoundException;
048: import edu.rice.cs.drjava.model.debug.DebugException;
049: import edu.rice.cs.drjava.model.debug.LineNotExecutableException;
050: import javax.swing.text.BadLocationException;
051:
052: /** Superclasses all DebugActions that are associated with specific OpenDefinitionsDocuments.
053: * @version $Id: DocumentDebugAction.java 4255 2007-08-28 19:17:37Z mgricken $
054: */
055: public abstract class DocumentDebugAction<T extends EventRequest>
056: extends DebugAction<T> {
057:
058: protected volatile String _className;
059: protected volatile String _exactClassName;
060: protected volatile File _file;
061: protected volatile OpenDefinitionsDocument _doc;
062: protected int _offset;
063:
064: public final int SHORT_DOC_MAX_LENGTH = 20000;
065:
066: /** Creates a new DocumentDebugAction. Automatically tries to create the EventRequest if a ReferenceType can be
067: * found, or else adds this object to the PendingRequestManager. Any subclass should automatically call
068: * _initializeRequest in its constructor.
069: * @param manager JPDADebugger in charge
070: * @param doc Document this action corresponds to
071: * @param offset Offset into the document that the action affects
072: */
073: public DocumentDebugAction(JPDADebugger manager,
074: OpenDefinitionsDocument doc, int offset)
075: throws DebugException {
076: super (manager);
077: _exactClassName = null;
078: try {
079: if (offset >= 0) {
080: if (doc.getLength() < SHORT_DOC_MAX_LENGTH) {
081: // only do this on short files
082: // in long files, getEnclosingClassName might take too long
083: _exactClassName = doc.getEnclosingClassName(offset,
084: true);
085: }
086: }
087: } catch (ClassNameNotFoundException cnnfe) { /* ignore, we don't need the exact class name */
088: } catch (BadLocationException ble) { /* ignore, we don't need the exact class name */
089: }
090: try {
091: if (offset >= 0) {
092: _className = doc.getQualifiedClassName(offset);
093: }
094: } catch (ClassNameNotFoundException cnnfe) {
095: // Still couldn't find a class name, use ""
096: _className = "";
097: }
098: // System.out.println("Breakpoint added: "+_className+", exact="+_exactClassName);
099:
100: try {
101: _file = doc.getFile();
102: if (_file == null)
103: throw new DebugException(
104: "This document has no source file.");
105: } catch (FileMovedException fme) {
106: throw new DebugException(
107: "This document's file no longer exists: "
108: + fme.getMessage());
109: }
110: _doc = doc;
111: _offset = offset;
112: }
113:
114: /** Returns the class name this DebugAction occurs in. */
115: public String getClassName() {
116: return _className;
117: }
118:
119: /** Returns the file this DebugAction occurs in. */
120: public File getFile() {
121: return _file;
122: }
123:
124: /** Returns the document this DebugAction occurs in. */
125: public OpenDefinitionsDocument getDocument() {
126: return _doc;
127: }
128:
129: /** @return offset of this debug action. */
130: public int getOffset() {
131: return _offset;
132: }
133:
134: /** @return exact class name, or null if not available. */
135: public String getExactClassName() {
136: return _exactClassName;
137: }
138:
139: /** Creates EventRequests corresponding to this DebugAction, using the given ReferenceTypes. This is called either
140: * from the DebugAction constructor or the PendingRequestManager, depending on when the ReferenceTypes become
141: * available. (There may be multiple reference types for the same class if a custom class loader is used.)
142: * @return true if the EventRequest is successfully created
143: */
144: public boolean createRequests(Vector<ReferenceType> refTypes)
145: throws DebugException {
146: _createRequests(refTypes);
147: if (_requests.size() > 0) {
148: _prepareRequests(_requests);
149: return true;
150: } else
151: return false;
152: }
153:
154: /** This should always be called from the constructor of the subclass. Attempts to create EventRequests on the
155: * given ReferenceTypes, and also adds this action to the pending request manager (so identical classes loaded
156: * in the future will also have this action).
157: */
158: protected void _initializeRequests(Vector<ReferenceType> refTypes)
159: throws DebugException {
160: if (refTypes.size() > 0)
161: createRequests(refTypes);
162: else {
163: if (_exactClassName != null) {
164: List<ReferenceType> referenceTypes = _manager.getVM()
165: .classesByName(_exactClassName);
166: if (referenceTypes.size() > 0) {
167: // class has been loaded, but couldn't find this line number
168: throw new LineNotExecutableException(
169: "Cannot set breakpoint, line "
170: + getLineNumber()
171: + " is not an executable line.");
172: }
173: }
174: }
175: //if (_request == null) {
176: // couldn't create the request yet, add to the pending request manager
177:
178: // Experiment: always add to pending request, to deal with multpile class loads
179: _manager.getPendingRequestManager().addPendingRequest(this );
180: //}
181: }
182:
183: /** Creates appropriate EventRequests from the EventRequestManager and stores them in the _requests field.
184: * @param refTypes All (identical) ReferenceTypes to which this action applies. (There may be multiple if a custom
185: * class loader is in use.)
186: * @throws DebugException if the requests could not be created.
187: */
188: protected abstract void _createRequests(
189: Vector<ReferenceType> refTypes) throws DebugException;
190:
191: /** Prepares this EventRequest with the current stored values.
192: * @param request the EventRequest to prepare
193: */
194: protected void _prepareRequest(T request) {
195: super ._prepareRequest(request);
196: request.putProperty("document", _doc);
197: }
198: }
|