001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.debugger.jpda.breakpoints;
043:
044: import java.awt.EventQueue;
045: import java.beans.PropertyChangeListener;
046: import java.util.HashMap;
047: import java.util.Iterator;
048: import java.util.logging.Logger;
049:
050: import org.netbeans.api.debugger.Breakpoint;
051: import org.netbeans.api.debugger.DebuggerEngine;
052: import org.netbeans.api.debugger.DebuggerManager;
053: import org.netbeans.api.debugger.DebuggerManagerListener;
054: import org.netbeans.api.debugger.LazyActionsManagerListener;
055: import org.netbeans.spi.debugger.ContextProvider;
056: import org.netbeans.api.debugger.Session;
057: import org.netbeans.api.debugger.Watch;
058:
059: import org.netbeans.api.debugger.jpda.ClassLoadUnloadBreakpoint;
060: import org.netbeans.api.debugger.jpda.ExceptionBreakpoint;
061: import org.netbeans.api.debugger.jpda.FieldBreakpoint;
062: import org.netbeans.api.debugger.jpda.JPDADebugger;
063: import org.netbeans.api.debugger.jpda.LineBreakpoint;
064: import org.netbeans.api.debugger.jpda.MethodBreakpoint;
065: import org.netbeans.api.debugger.jpda.ThreadBreakpoint;
066:
067: import org.netbeans.modules.debugger.jpda.SourcePath;
068: import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
069:
070: import org.openide.util.RequestProcessor;
071:
072: /**
073: * Listens on JPDADebugger.PROP_STATE and DebuggerManager.PROP_BREAKPOINTS, and
074: * and creates XXXBreakpointImpl classes for all JPDABreakpoints.
075: *
076: * @author Jan Jancura
077: */
078: public class BreakpointsEngineListener extends
079: LazyActionsManagerListener implements PropertyChangeListener,
080: DebuggerManagerListener {
081:
082: private static Logger logger = Logger
083: .getLogger("org.netbeans.modules.debugger.jpda.breakpoints"); // NOI18N
084:
085: private JPDADebuggerImpl debugger;
086: private SourcePath engineContext;
087: private boolean started = false;
088: private Session session;
089: private BreakpointsReader breakpointsReader;
090:
091: public BreakpointsEngineListener(ContextProvider lookupProvider) {
092: debugger = (JPDADebuggerImpl) lookupProvider.lookupFirst(null,
093: JPDADebugger.class);
094: engineContext = lookupProvider.lookupFirst(null,
095: SourcePath.class);
096: session = lookupProvider.lookupFirst(null, Session.class);
097: debugger.addPropertyChangeListener(JPDADebugger.PROP_STATE,
098: this );
099: breakpointsReader = PersistenceManager.findBreakpointsReader();
100: }
101:
102: protected void destroy() {
103: debugger.removePropertyChangeListener(JPDADebugger.PROP_STATE,
104: this );
105: DebuggerManager.getDebuggerManager().removeDebuggerListener(
106: DebuggerManager.PROP_BREAKPOINTS, this );
107: removeBreakpointImpls();
108: }
109:
110: public String[] getProperties() {
111: return new String[] { "asd" };
112: }
113:
114: public void propertyChange(java.beans.PropertyChangeEvent evt) {
115: if (debugger.getState() == JPDADebugger.STATE_RUNNING) {
116: if (started)
117: return;
118: started = true;
119: createBreakpointImpls();
120: DebuggerManager.getDebuggerManager().addDebuggerListener(
121: DebuggerManager.PROP_BREAKPOINTS, this );
122: }
123: if (debugger.getState() == JPDADebugger.STATE_DISCONNECTED) {
124: removeBreakpointImpls();
125: started = false;
126: DebuggerManager.getDebuggerManager()
127: .removeDebuggerListener(
128: DebuggerManager.PROP_BREAKPOINTS, this );
129: }
130: }
131:
132: public void actionPerformed(Object action) {
133: // if (action == ActionsManager.ACTION_FIX)
134: // fixBreakpointImpls ();
135: }
136:
137: public void breakpointAdded(final Breakpoint breakpoint) {
138: final boolean[] started = new boolean[] { false };
139: if (Thread.holdsLock(debugger.LOCK)) {
140: createBreakpointImpl(breakpoint);
141: return;
142: } // Otherwise:
143: RequestProcessor.getDefault().post(new Runnable() {
144: public void run() {
145: synchronized (debugger.LOCK) {
146: synchronized (started) {
147: started[0] = true;
148: started.notify();
149: }
150: createBreakpointImpl(breakpoint);
151: }
152: }
153: });
154: if (!EventQueue.isDispatchThread()) { // AWT should not wait for debugger.LOCK
155: synchronized (started) {
156: if (!started[0]) {
157: try {
158: started.wait();
159: } catch (InterruptedException iex) {
160: }
161: }
162: }
163: }
164: }
165:
166: public void breakpointRemoved(final Breakpoint breakpoint) {
167: final boolean[] started = new boolean[] { false };
168: if (Thread.holdsLock(debugger.LOCK)) {
169: removeBreakpointImpl(breakpoint);
170: return;
171: } // Otherwise:
172: RequestProcessor.getDefault().post(new Runnable() {
173: public void run() {
174: synchronized (debugger.LOCK) {
175: synchronized (started) {
176: started[0] = true;
177: started.notify();
178: }
179: removeBreakpointImpl(breakpoint);
180: }
181: }
182: });
183: if (!EventQueue.isDispatchThread()) { // AWT should not wait for debugger.LOCK
184: synchronized (started) {
185: if (!started[0]) {
186: try {
187: started.wait();
188: } catch (InterruptedException iex) {
189: }
190: }
191: }
192: }
193: }
194:
195: public Breakpoint[] initBreakpoints() {
196: return new Breakpoint[0];
197: }
198:
199: public void initWatches() {
200: }
201:
202: public void sessionAdded(Session session) {
203: }
204:
205: public void sessionRemoved(Session session) {
206: }
207:
208: public void watchAdded(Watch watch) {
209: }
210:
211: public void watchRemoved(Watch watch) {
212: }
213:
214: public void engineAdded(DebuggerEngine engine) {
215: }
216:
217: public void engineRemoved(DebuggerEngine engine) {
218: }
219:
220: // helper methods ..........................................................
221:
222: private HashMap<Breakpoint, BreakpointImpl> breakpointToImpl = new HashMap<Breakpoint, BreakpointImpl>();
223:
224: private void createBreakpointImpls() {
225: Breakpoint[] bs = DebuggerManager.getDebuggerManager()
226: .getBreakpoints();
227: int i, k = bs.length;
228: for (i = 0; i < k; i++)
229: createBreakpointImpl(bs[i]);
230: }
231:
232: private void removeBreakpointImpls() {
233: Breakpoint[] bs = DebuggerManager.getDebuggerManager()
234: .getBreakpoints();
235: int i, k = bs.length;
236: for (i = 0; i < k; i++)
237: removeBreakpointImpl(bs[i]);
238: }
239:
240: public void fixBreakpointImpls() {
241: Iterator<BreakpointImpl> i = breakpointToImpl.values()
242: .iterator();
243: while (i.hasNext())
244: i.next().fixed();
245: }
246:
247: private synchronized void createBreakpointImpl(Breakpoint b) {
248: if (breakpointToImpl.containsKey(b))
249: return;
250: if (b instanceof LineBreakpoint) {
251: breakpointToImpl.put(b, new LineBreakpointImpl(
252: (LineBreakpoint) b, breakpointsReader, debugger,
253: session, engineContext));
254: } else if (b instanceof ExceptionBreakpoint) {
255: breakpointToImpl.put(b, new ExceptionBreakpointImpl(
256: (ExceptionBreakpoint) b, debugger, session));
257: } else if (b instanceof MethodBreakpoint) {
258: breakpointToImpl.put(b, new MethodBreakpointImpl(
259: (MethodBreakpoint) b, debugger, session));
260: } else if (b instanceof FieldBreakpoint) {
261: breakpointToImpl.put(b, new FieldBreakpointImpl(
262: (FieldBreakpoint) b, debugger, session));
263: } else if (b instanceof ThreadBreakpoint) {
264: breakpointToImpl.put(b, new ThreadBreakpointImpl(
265: (ThreadBreakpoint) b, debugger, session));
266: } else if (b instanceof ClassLoadUnloadBreakpoint) {
267: breakpointToImpl.put(b, new ClassBreakpointImpl(
268: (ClassLoadUnloadBreakpoint) b, debugger, session));
269: }
270: logger.finer("BreakpointsEngineListener: created impl "
271: + breakpointToImpl.get(b) + " for " + b);
272: }
273:
274: private synchronized void removeBreakpointImpl(Breakpoint b) {
275: BreakpointImpl impl = breakpointToImpl.get(b);
276: if (impl == null)
277: return;
278: logger.finer("BreakpointsEngineListener: removed impl " + impl
279: + " for " + b);
280: impl.remove();
281: breakpointToImpl.remove(b);
282: }
283: }
|