KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > breakpoints > LineBreakpointImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.breakpoints;
21
22 import com.sun.jdi.AbsentInformationException;
23 import com.sun.jdi.InternalException;
24 import com.sun.jdi.Location;
25 import com.sun.jdi.ObjectCollectedException;
26 import com.sun.jdi.ReferenceType;
27 import com.sun.jdi.VMDisconnectedException;
28 import com.sun.jdi.ClassNotPreparedException;
29 import com.sun.jdi.event.BreakpointEvent;
30 import com.sun.jdi.event.LocatableEvent;
31 import com.sun.jdi.event.Event;
32 import com.sun.jdi.request.BreakpointRequest;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Collections JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.logging.Level JavaDoc;
38 import java.util.logging.Logger JavaDoc;
39 import java.util.regex.Matcher JavaDoc;
40 import java.util.regex.Pattern JavaDoc;
41 import org.netbeans.api.debugger.Breakpoint;
42 import org.netbeans.api.debugger.jpda.ClassLoadUnloadBreakpoint;
43 import org.netbeans.api.debugger.jpda.JPDABreakpoint;
44 import org.netbeans.api.debugger.jpda.LineBreakpoint;
45 import org.netbeans.api.debugger.Session;
46 import org.netbeans.modules.debugger.jpda.EditorContextBridge;
47 import org.netbeans.modules.debugger.jpda.SourcePath;
48 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
49 import org.openide.ErrorManager;
50 import org.openide.util.NbBundle;
51
52
53
54 /**
55 * Implementation of breakpoint on method.
56 *
57 * @author Jan Jancura
58 */

59 public class LineBreakpointImpl extends ClassBasedBreakpoint {
60     
61     private static Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.breakpoints"); // NOI18N
62

63     private int lineNumber;
64     private BreakpointsReader reader;
65     
66     
67     public LineBreakpointImpl (
68         LineBreakpoint breakpoint,
69         BreakpointsReader reader,
70         JPDADebuggerImpl debugger,
71         Session session,
72         SourcePath sourcePath
73     ) {
74         super (breakpoint, reader, debugger, session);
75         this.reader = reader;
76         lineNumber = breakpoint.getLineNumber ();
77         setSourceRoot(sourcePath.getSourceRoot(breakpoint.getURL()));
78         set ();
79     }
80
81     protected LineBreakpoint getBreakpoint() {
82         return (LineBreakpoint) super.getBreakpoint();
83     }
84     
85     void fixed () {
86         logger.fine("LineBreakpoint fixed: "+this);
87         lineNumber = getBreakpoint().getLineNumber ();
88         super.fixed ();
89     }
90     
91     protected void setRequests () {
92         LineBreakpoint breakpoint = getBreakpoint();
93         lineNumber = breakpoint.getLineNumber ();
94         String JavaDoc className = breakpoint.getPreferredClassName();
95         if (className == null) {
96             className = reader.findCachedClassName(breakpoint);
97             if (className == null) {
98                 className = EditorContextBridge.getClassName (
99                     breakpoint.getURL (),
100                     lineNumber
101                 );
102                 if (className != null) {
103                     reader.storeCachedClassName(breakpoint, className);
104                 }
105             }
106         }
107         if (className == null) {
108             logger.warning("Class name not defined for breakpoint "+breakpoint);
109             return ;
110         }
111         logger.fine("LineBreakpoint "+breakpoint+" - setting request for "+className);
112         setClassRequests (
113             new String JavaDoc[] {
114                 className // The class name is correct even for inner classes now
115
},
116             new String JavaDoc [0],
117             ClassLoadUnloadBreakpoint.TYPE_CLASS_LOADED
118         );
119         checkLoadedClasses (className);
120     }
121
122     protected void classLoaded (ReferenceType referenceType) {
123         LineBreakpoint breakpoint = getBreakpoint();
124         logger.fine("Class "+referenceType+" loaded for breakpoint "+breakpoint);
125         
126         String JavaDoc[] reason = new String JavaDoc[] { null };
127         List JavaDoc locations = getLocations (
128             referenceType,
129             breakpoint.getStratum (),
130             breakpoint.getSourceName (),
131             breakpoint.getSourcePath(),
132             lineNumber,
133             reason
134         );
135         if (locations.isEmpty()) {
136             ErrorManager.getDefault().log(ErrorManager.WARNING,
137                     "Unable to submit line breakpoint to "+referenceType.name()+
138                     " at line "+lineNumber+", reason: "+reason[0]);
139             setValidity(Breakpoint.VALIDITY.INVALID, reason[0]);
140             return;
141         }
142         for (Iterator JavaDoc it = locations.iterator(); it.hasNext();) {
143             Location location = (Location)it.next();
144             try {
145                 BreakpointRequest br = getEventRequestManager ().
146                     createBreakpointRequest (location);
147                 addEventRequest (br);
148                 setValidity(Breakpoint.VALIDITY.VALID, null);
149                 //System.out.println("Breakpoint " + br + location + "created");
150
} catch (VMDisconnectedException e) {
151             }
152         }
153     }
154
155     public boolean exec (Event event) {
156         if (event instanceof BreakpointEvent) {
157             return perform (
158                 getBreakpoint().getCondition (),
159                 ((BreakpointEvent) event).thread (),
160                 ((LocatableEvent) event).location ().declaringType (),
161                 null
162             );
163         }
164         return super.exec (event);
165     }
166     
167     private static List JavaDoc getLocations (
168         ReferenceType referenceType,
169         String JavaDoc stratum,
170         String JavaDoc sourceName,
171         String JavaDoc bpSourcePath,
172         int lineNumber,
173         String JavaDoc[] reason
174     ) {
175         try {
176             reason[0] = null;
177             List JavaDoc locations = locationsOfLineInClass(referenceType, stratum,
178                                                     sourceName, bpSourcePath,
179                                                     lineNumber, reason);
180             /* Obsolete, no special handling of inner classes, referenceType is
181                the correct class now.
182              if (locations.isEmpty()) {
183                 // add lines from innerclasses
184                 Iterator i = referenceType.nestedTypes ().iterator ();
185                 while (i.hasNext ()) {
186                     ReferenceType rt = (ReferenceType) i.next ();
187                     locations = locationsOfLineInClass(rt, stratum, sourceName,
188                                                        bpSourcePath, lineNumber,
189                                                        reason);
190                     if (!locations.isEmpty()) {
191                         break;
192                     }
193                 }
194             }*/

195             if (locations.isEmpty() && reason[0] == null) {
196                 reason[0] = NbBundle.getMessage(LineBreakpointImpl.class, "MSG_NoLocation", Integer.toString(lineNumber));
197             }
198             return locations;
199         } catch (AbsentInformationException ex) {
200             // we are not able to create breakpoint in this situation.
201
// should we write some message?!?
202
// We should indicate somehow that the breakpoint is invalid...
203
reason[0] = NbBundle.getMessage(LineBreakpointImpl.class, "MSG_NoLineInfo");
204         } catch (ObjectCollectedException ex) {
205             // no problem, breakpoint will be created next time the class
206
// is loaded
207
// should not occurre. see [51034]
208
reason[0] = ex.getLocalizedMessage();
209         } catch (ClassNotPreparedException ex) {
210             // should not occurre. VirtualMachine.allClasses () returns prepared
211
// classes only. But...
212
ErrorManager.getDefault().notify(ErrorManager.ERROR, ex);
213         } catch (InternalException iex) {
214             // Something wrong in JDI
215
ErrorManager.getDefault().annotate(iex,
216                     NbBundle.getMessage(LineBreakpointImpl.class,
217                     "MSG_jdi_internal_error") );
218             ErrorManager.getDefault().notify(iex);
219             // We should indicate somehow that the breakpoint is invalid...
220
reason[0] = iex.getLocalizedMessage();
221         }
222         return Collections.EMPTY_LIST;
223     }
224     
225     private static List JavaDoc<Location> locationsOfLineInClass(
226         ReferenceType referenceType,
227         String JavaDoc stratum,
228         String JavaDoc sourceName,
229         String JavaDoc bpSourcePath,
230         int lineNumber,
231         String JavaDoc[] reason) throws AbsentInformationException, ObjectCollectedException,
232                                 ClassNotPreparedException, InternalException {
233         List JavaDoc<Location> list = referenceType.locationsOfLine (
234             stratum,
235             sourceName,
236             lineNumber
237         );
238
239         if (logger.isLoggable(Level.FINER)) {
240             logger.finer("LineBreakpoint: locations for ReferenceType=" +
241                     referenceType + ", stratum=" + stratum +
242                     ", source name=" + sourceName + ", bpSourcePath=" +
243                     bpSourcePath+", lineNumber=" + lineNumber +
244                     " are: {" + list + "}");
245         }
246         if (!list.isEmpty ()) {
247             if (bpSourcePath == null)
248                 return list;
249             bpSourcePath = bpSourcePath.replace(java.io.File.separatorChar, '/');
250             ArrayList JavaDoc<Location> locations = new ArrayList JavaDoc<Location>(list.size());
251             for (Iterator JavaDoc<Location> it = list.iterator(); it.hasNext();) {
252                 Location l = it.next();
253                 String JavaDoc lSourcePath = l.sourcePath().replace(java.io.File.separatorChar, '/');
254                 lSourcePath = normalize(lSourcePath);
255                 if (lSourcePath.equals(bpSourcePath)) {
256                     locations.add(l);
257                 } else {
258                     reason[0] = "Breakpoint source path '"+bpSourcePath+"' is different from the location source path '"+lSourcePath+"'.";
259                 }
260             }
261             if (logger.isLoggable(Level.FINER)) {
262                 logger.finer("LineBreakpoint: relevant location(s) for path '" + bpSourcePath + "': " + locations);
263             }
264             if (!locations.isEmpty())
265                 return locations;
266         }
267         return Collections.emptyList();
268     }
269     
270     /**
271      * Normalizes the given path by removing unnecessary "." and ".." sequences.
272      * This normalization is needed because the compiler stores source paths like "foo/../inc.jsp" into .class files.
273      * Such paths are not supported by our ClassPath API.
274      * TODO: compiler bug? report to JDK?
275      *
276      * @param path path to normalize
277      * @return normalized path without "." and ".." elements
278      */

279     private static String JavaDoc normalize(String JavaDoc path) {
280       Pattern JavaDoc thisDirectoryPattern = Pattern.compile("(/|\\A)\\./");
281       Pattern JavaDoc parentDirectoryPattern = Pattern.compile("(/|\\A)([^/]+?)/\\.\\./");
282       
283       for (Matcher JavaDoc m = thisDirectoryPattern.matcher(path); m.find(); )
284       {
285         path = m.replaceAll("$1");
286         m = thisDirectoryPattern.matcher(path);
287       }
288       for (Matcher JavaDoc m = parentDirectoryPattern.matcher(path); m.find(); )
289       {
290         if (!m.group(2).equals("..")) {
291           path = path.substring(0, m.start()) + m.group(1) + path.substring(m.end());
292           m = parentDirectoryPattern.matcher(path);
293         }
294       }
295       return path;
296     }
297 }
298
299
Popular Tags