This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 242800
Collapse All | Expand All

(-)a/api.debugger/src/org/netbeans/api/debugger/EngineBreakpoints.java (+178 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2015 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.debugger;
44
45
import java.beans.PropertyChangeListener;
46
import java.lang.ref.Reference;
47
import java.lang.ref.WeakReference;
48
import java.util.LinkedList;
49
import java.util.List;
50
import java.util.Set;
51
import org.netbeans.spi.debugger.EngineBreakpointsProvider;
52
53
/**
54
 * This class handles the debugger engine-related breakpoints and provides
55
 * a possibility of breakpoints activation/deactivation, which is independent
56
 * on their enabled/disabled state.
57
 * 
58
 * @author Martin Entlicher
59
 * @since 1.51
60
 */
61
public final class EngineBreakpoints {
62
    
63
    /**
64
     * Property change fired when breakpoints activation/deactivation changes.
65
     */
66
    public static final String PROP_BREAKPOINTS_ACTIVE = "breakpointsActive";   // NOI18N
67
    /**
68
     * Property change fired when a set of engine-related breakpoints is changed.
69
     */
70
    public static final String PROP_BREAKPOINTS_CHANGED = "breakpointsChanged"; // NOI18N
71
    
72
    // These two lists are used as a trivial weak map from DebuggerEngine to EngineBreakpoints,
73
    // where both keys and values are held weakly.
74
    private static final List<Reference<DebuggerEngine>> dEngines = new LinkedList<>();
75
    private static final List<Reference<EngineBreakpoints>> eBreakpoints = new LinkedList<>();
76
    
77
    private final EngineBreakpointsProvider ebp;
78
    
79
    /**
80
     * Get an EngineBreakpoints instance for a debugger engine.
81
     * @param debuggerEngine the debugger engine.
82
     * @return The EngineBreakpoints instance, or <code>null</code> when the engine
83
     * does not provide {@link EngineBreakpointsProvider} in it's lookup.
84
     */
85
    public static EngineBreakpoints get(DebuggerEngine debuggerEngine) {
86
        EngineBreakpointsProvider ebp = debuggerEngine.lookupFirst(null, EngineBreakpointsProvider.class);
87
        if (ebp == null) {
88
            return null;
89
        }
90
        synchronized (dEngines) {
91
            for (int i = 0; i < dEngines.size(); i++) {
92
                DebuggerEngine de = dEngines.get(i).get();
93
                if (de == null) {
94
                    dEngines.remove(i);
95
                    eBreakpoints.remove(i);
96
                    i--;
97
                    continue;
98
                }
99
                if (de == debuggerEngine) {
100
                    EngineBreakpoints eb = eBreakpoints.get(i).get();
101
                    if (eb != null) {
102
                        return eb;
103
                    }
104
                }
105
            }
106
            // Not cached, create a new one:
107
            EngineBreakpoints eb = new EngineBreakpoints(ebp);
108
            dEngines.add(new WeakReference<>(debuggerEngine));
109
            eBreakpoints.add(new WeakReference<>(eb));
110
            return eb;
111
        }
112
    }
113
    
114
    private EngineBreakpoints(EngineBreakpointsProvider ebp) {
115
        this.ebp = ebp;
116
    }
117
    
118
    /**
119
     * Test if breakpoint deactivation is supported.
120
     * When <code>false</code> is returned, {@link #setBreakpointsActive(boolean)}
121
     * throws UnsupportedOperationException when called with false argument.
122
     * @return <code>true</code> when engine-related breakpoints can be deactivated,
123
     *         <code>false</code> otherwise.
124
     */
125
    public boolean canDeactivateBreakpoints() {
126
        return ebp.canDeactivateBreakpoints();
127
    }
128
    
129
    /**
130
     * Test if the engine's breakpoints are currently active.
131
     * @return <code>true</code> when breakpoints are active,
132
     *         <code>false</code> otherwise.
133
     */
134
    public boolean areBreakpointsActive() {
135
        return ebp.areBreakpointsActive();
136
    }
137
    
138
    /**
139
     * Activate or deactivate breakpoints handled by this debugger engine.
140
     * The breakpoints activation/deactivation is independent on breakpoints enabled/disabled state.
141
     * 
142
     * @param active <code>true</code> to activate breakpoints,
143
     *               <code>false</code> to deactivate them.
144
     * @throws UnsupportedOperationException when there is an attempt to deactivate
145
     *         breakpoints even though {@link #canDeactivateBreakpoints()} return false
146
     */
147
    public void setBreakpointsActive(boolean active) throws UnsupportedOperationException {
148
        ebp.setBreakpointsActive(active);
149
    }
150
    
151
    /**
152
     * Get the set of breakpoints that are managed by this engine.
153
     * These are the breakpoints that are subject of activation/deactivation
154
     * if it's supported.
155
     * @return A set of breakpoints managed by this engine.
156
     */
157
    public Set<Breakpoint> getEngineBreakpoints() {
158
        return ebp.getEngineBreakpoints();
159
    }
160
    
161
    /**
162
     * Add a property change listener to be notified about properties
163
     * defined as PROP_* constants.
164
     * @param l a property change listener
165
     */
166
    public final void addPropertyChangeListener(PropertyChangeListener l) {
167
        ebp.addPropertyChangeListener(l);
168
    }
169
    
170
    /**
171
     * Remove a property change listener.
172
     * @param l  a property change listener
173
     */
174
    public final void removePropertyChangeListener(PropertyChangeListener l) {
175
        ebp.removePropertyChangeListener(l);
176
    }
177
178
}
(-)a/api.debugger/src/org/netbeans/spi/debugger/EngineBreakpointsProvider.java (+280 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2015 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.spi.debugger;
44
45
import java.beans.PropertyChangeListener;
46
import java.beans.PropertyChangeSupport;
47
import java.lang.annotation.ElementType;
48
import java.lang.annotation.Retention;
49
import java.lang.annotation.RetentionPolicy;
50
import java.lang.annotation.Target;
51
import java.util.Map;
52
import java.util.Set;
53
import java.util.concurrent.atomic.AtomicBoolean;
54
import org.netbeans.api.debugger.Breakpoint;
55
import org.netbeans.api.debugger.DebuggerEngine;
56
import org.netbeans.api.debugger.EngineBreakpoints;
57
import static org.netbeans.api.debugger.EngineBreakpoints.PROP_BREAKPOINTS_ACTIVE;
58
import static org.netbeans.api.debugger.EngineBreakpoints.PROP_BREAKPOINTS_CHANGED;
59
import org.netbeans.debugger.registry.ContextAwareServiceHandler;
60
61
/**
62
 * Provider of debugger engine-related breakpoints and a possibility of their
63
 * activation/deactivation, which is independent on the enabled/disabled state.
64
 * Register an implementation of this class for an appropriate debugger engine
65
 * via {@link Registration} annotation.
66
 * 
67
 * @author Martin Entlicher
68
 * @since 1.51
69
 */
70
public abstract class EngineBreakpointsProvider {
71
    
72
    final PropertyChangeSupport pchs = new PropertyChangeSupport(this);
73
    private final AtomicBoolean breakpointsActive = new AtomicBoolean(areBreakpointsActiveInitially());
74
    
75
    /**
76
     * Provides the initial state of breakpoints active property.
77
     * Override to provide the initial state different from the default one.
78
     * @return <code>true</code> by default.
79
     */
80
    protected boolean areBreakpointsActiveInitially() {
81
        return true;
82
    }
83
    
84
    /**
85
     * Test if breakpoint deactivation is supported.
86
     * When <code>false</code> is returned, {@link #setBreakpointsActive(boolean)}
87
     * throws UnsupportedOperationException when called with false argument.
88
     * @return <code>true</code> when engine-related breakpoints can be deactivated,
89
     *         <code>false</code> otherwise.
90
     */
91
    public abstract boolean canDeactivateBreakpoints();
92
    
93
    /**
94
     * Activate or deactivate breakpoints handled by this debugger engine.
95
     * The breakpoints activation/deactivation is independent on breakpoints enabled/disabled state.
96
     * 
97
     * @param active <code>true</code> to activate breakpoints,
98
     *               <code>false</code> to deactivate them.
99
     * @throws UnsupportedOperationException when there is an attempt to deactivate
100
     *         breakpoints even though {@link #canDeactivateBreakpoints()} return false
101
     */
102
    public final void setBreakpointsActive(boolean active) throws UnsupportedOperationException {
103
        if (!active && !canDeactivateBreakpoints()) {
104
            throw new UnsupportedOperationException("Can not deactivate breakpoints");  // NOI18N
105
        }
106
        if (breakpointsActive.getAndSet(active) != active) {
107
            notifyBreakpointsActive(active);
108
            fireBreakpointsActive(active);
109
        }
110
    }
111
    
112
    /**
113
     * Test if the engine's breakpoints are currently active.
114
     * @return <code>true</code> when breakpoints are active,
115
     *         <code>false</code> otherwise.
116
     */
117
    public final boolean areBreakpointsActive() {
118
        return breakpointsActive.get();
119
    }
120
121
    /**
122
     * The implementation class is notified about breakpoints activation/deactivation
123
     * requests via this method. The implementation of this method should
124
     * actually activate/deactivate breakpoints in the corresponding debugger engine.
125
     * @param active <code>true</code> to activate breakpoints,
126
     *               <code>false</code> otherwise.
127
     */
128
    protected abstract void notifyBreakpointsActive(boolean active);
129
    
130
    private void fireBreakpointsActive(boolean active) {
131
        pchs.firePropertyChange(PROP_BREAKPOINTS_ACTIVE, !active, active);
132
    }
133
    
134
    /**
135
     * Get the set of breakpoints that are managed by this engine.
136
     * These are the breakpoints that are subject of activation/deactivation
137
     * if it's supported.
138
     * @return A set of breakpoints managed by this engine.
139
     */
140
    public abstract Set<Breakpoint> getEngineBreakpoints();
141
    
142
    /**
143
     * Notify about changes of breakpoints that are managed by this engine.
144
     * @param removed a removed breakpoint, or <code>null</code>
145
     * @param added an added breakpoint, or <code>null</code>
146
     */
147
    protected final void fireBreakpointsChanged(Breakpoint removed, Breakpoint added) {
148
        pchs.firePropertyChange(PROP_BREAKPOINTS_CHANGED, removed, added);
149
    }
150
    
151
    /**
152
     * Add a property change listener to be notified about properties
153
     * defined in {@link EngineBreakpoints}.PROP_*
154
     * @param l a property change listener
155
     */
156
    public final void addPropertyChangeListener(PropertyChangeListener l) {
157
        pchs.addPropertyChangeListener(l);
158
    }
159
    
160
    /**
161
     * Remove a property change listener.
162
     * @param l  a property change listener
163
     */
164
    public final void removePropertyChangeListener(PropertyChangeListener l) {
165
        pchs.removePropertyChangeListener(l);
166
    }
167
    
168
    /**
169
     * Declarative registration of an EngineBreakpointsProvider implementation.
170
     * By marking the implementation class with this annotation,
171
     * you automatically register that implementation for use by debugger.
172
     * The class must be public and have a public constructor which takes
173
     * no arguments or takes {@link ContextProvider} as an argument.
174
     */
175
    @Retention(RetentionPolicy.SOURCE)
176
    @Target({ElementType.TYPE})
177
    public @interface Registration {
178
        
179
        /**
180
         * The path to register this implementation in.
181
         * Usually the session/engine ID.
182
         */
183
        String path();
184
        
185
        /**
186
         * Test if breakpoint deactivation is supported.
187
         * By default, the provider instance is created immediately.
188
         * This method can be used to delay the instantiation of the
189
         * implementation class for performance reasons.
190
         * @return <code>true</code> when engine-related breakpoints can be deactivated,
191
         *         <code>false</code> otherwise.
192
         */
193
        boolean canDeactivateBreakpoints() default false;
194
    }
195
    
196
    static class ContextAware extends EngineBreakpointsProvider implements ContextAwareService<EngineBreakpointsProvider> {
197
198
        private final String serviceName;
199
        private ContextProvider context;
200
        private EngineBreakpointsProvider delegate;
201
202
        private boolean canDeactivateBreakpoints;
203
        
204
        private ContextAware(String serviceName, boolean canDeactivateBreakpoints) {
205
            this.serviceName = serviceName;
206
            this.canDeactivateBreakpoints = canDeactivateBreakpoints;
207
        }
208
        
209
        private ContextAware(String serviceName, boolean canDeactivateBreakpoints,
210
                             ContextProvider context) {
211
            this.serviceName = serviceName;
212
            this.canDeactivateBreakpoints = canDeactivateBreakpoints;
213
            this.context = context;
214
        }
215
        
216
        private synchronized EngineBreakpointsProvider getDelegate() {
217
            if (delegate == null) {
218
                delegate = (EngineBreakpointsProvider) ContextAwareSupport.createInstance(serviceName, context);
219
                if (delegate == null) {
220
                    throw new IllegalStateException("No instance created for service "+serviceName+", context = "+context);
221
                }
222
                for (PropertyChangeListener l : pchs.getPropertyChangeListeners()) {
223
                    delegate.addPropertyChangeListener(l);
224
                    pchs.removePropertyChangeListener(l);
225
                }
226
            }
227
            return delegate;
228
        }
229
        
230
        @Override
231
        public boolean canDeactivateBreakpoints() {
232
            EngineBreakpointsProvider ebpDelegate;
233
            synchronized (this) {
234
                ebpDelegate = this.delegate;
235
            }
236
            if (ebpDelegate != null) {
237
                return ebpDelegate.canDeactivateBreakpoints();
238
            } else {
239
                return canDeactivateBreakpoints;
240
            }
241
        }
242
243
        @Override
244
        protected void notifyBreakpointsActive(boolean active) {
245
            getDelegate().notifyBreakpointsActive(active);
246
        }
247
248
        @Override
249
        public Set<Breakpoint> getEngineBreakpoints() {
250
            return getDelegate().getEngineBreakpoints();
251
        }
252
253
        @Override
254
        public EngineBreakpointsProvider forContext(ContextProvider context) {
255
            if (context == this.context) {
256
                return this;
257
            } else {
258
                return getDelegate();
259
            }
260
        }
261
262
        /**
263
         * Creates instance of <code>ContextAwareService</code> based on layer.xml
264
         * attribute values
265
         *
266
         * @param attrs attributes loaded from layer.xml
267
         * @return new <code>ContextAwareService</code> instance
268
         */
269
        static ContextAwareService createService(Map attrs) throws ClassNotFoundException {
270
            String serviceName = (String) attrs.get(ContextAwareServiceHandler.SERVICE_NAME);
271
            String cdbStr = (String) attrs.get(ContextAwareServiceHandler.SERVICE_CAN_DEACTIVATE_BREAKPOINTS);
272
            boolean cdb = Boolean.parseBoolean(cdbStr);
273
            ContextAware ca = new EngineBreakpointsProvider.ContextAware(serviceName,
274
                                                                         cdb);
275
            return ca;
276
        }
277
278
    }
279
280
}

Return to bug 242800