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 177561
Collapse All | Expand All

(-)a/api.debugger/apichanges.xml (+20 lines)
Lines 364-369 Link Here
364
        <issue number="178301"/>
364
        <issue number="178301"/>
365
    </change>
365
    </change>
366
366
367
    <change id="LazyActionRegistration">
368
        <api name="DebuggerCoreAPI"/>
369
        <summary>A declarative mechanism that creates action provider instance after a file with specific MIME type becomes active.</summary>
370
        <version major="1" minor="24"/>
371
        <date day="11" month="2" year="2010"/>
372
        <author login="mentlicher"/>
373
        <compatibility binary="compatible" source="compatible" addition="yes"/>
374
        <description>
375
             <p>
376
             ActionsProvider.Registration annotation is enhanced with two additional
377
             methods getActions() and enabledOnMIMETypes(). Until a file with the
378
             listed MIME type is selected in the IDE, the appropriate actions provider
379
             is left disabled for the given list of actions, without instantiating the
380
             implementation class.
381
             </p>
382
        </description>
383
        <class package="org.netbeans.spi.debugger" name="ActionsProvider" />
384
        <issue number="177561"/>
385
    </change>
386
367
</changes>
387
</changes>
368
388
369
  <!-- Now the surrounding HTML text and document structure: -->
389
  <!-- Now the surrounding HTML text and document structure: -->
(-)a/api.debugger/manifest.mf (-1 / +1 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.api.debugger/1
2
OpenIDE-Module: org.netbeans.api.debugger/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.22
4
OpenIDE-Module-Specification-Version: 1.23
5
OpenIDE-Module-Layer: org/netbeans/api/debugger/layer.xml
5
OpenIDE-Module-Layer: org/netbeans/api/debugger/layer.xml
(-)a/api.debugger/src/org/netbeans/debugger/registry/ContextAwareServiceHandler.java (+2 lines)
Lines 70-75 Link Here
70
70
71
    public static final String SERVICE_NAME = "serviceName"; // NOI18N
71
    public static final String SERVICE_NAME = "serviceName"; // NOI18N
72
    public static final String SERVICE_CLASSES = "serviceClasses"; // NOI18N
72
    public static final String SERVICE_CLASSES = "serviceClasses"; // NOI18N
73
    public static final String SERVICE_ACTIONS = "debugger_actions"; // NOI18N
74
    public static final String SERVICE_ENABLED_MIMETYPES = "debugger_enabledOnMIMETypes"; // NOI18N
73
75
74
    private String serviceName;
76
    private String serviceName;
75
    private Class[] serviceClasses;
77
    private Class[] serviceClasses;
(-)a/api.debugger/src/org/netbeans/debugger/registry/DebuggerProcessor.java (-7 / +22 lines)
Lines 66-71 Link Here
66
import org.netbeans.spi.debugger.DebuggerEngineProvider;
66
import org.netbeans.spi.debugger.DebuggerEngineProvider;
67
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
67
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
68
import org.netbeans.spi.debugger.SessionProvider;
68
import org.netbeans.spi.debugger.SessionProvider;
69
import org.openide.filesystems.annotations.LayerBuilder.File;
69
import org.openide.filesystems.annotations.LayerGeneratingProcessor;
70
import org.openide.filesystems.annotations.LayerGeneratingProcessor;
70
import org.openide.filesystems.annotations.LayerGenerationException;
71
import org.openide.filesystems.annotations.LayerGenerationException;
71
import org.openide.util.lookup.ServiceProvider;
72
import org.openide.util.lookup.ServiceProvider;
Lines 102-108 Link Here
102
            ActionsProvider.Registration reg = e.getAnnotation(ActionsProvider.Registration.class);
103
            ActionsProvider.Registration reg = e.getAnnotation(ActionsProvider.Registration.class);
103
104
104
            final String path = reg.path();
105
            final String path = reg.path();
105
            handleProviderRegistrationInner(e, ActionsProvider.class, path);
106
            final String[] actions = reg.getActions();
107
            final String[] mimeTypes = reg.enabledOnMIMETypes();
108
            handleProviderRegistrationInner(e, ActionsProvider.class, path, actions, mimeTypes);
106
            //layer(e).instanceFile("Debugger/"+path, null, ActionsProvider.class).
109
            //layer(e).instanceFile("Debugger/"+path, null, ActionsProvider.class).
107
            //        stringvalue("serviceName", instantiableClassOrMethod(e)).
110
            //        stringvalue("serviceName", instantiableClassOrMethod(e)).
108
            //        stringvalue("serviceClass", ActionsProvider.class.getName()).
111
            //        stringvalue("serviceClass", ActionsProvider.class.getName()).
Lines 186-191 Link Here
186
    }
189
    }
187
190
188
    private void handleProviderRegistrationInner(Element e, Class providerClass, String path) throws IllegalArgumentException, LayerGenerationException {
191
    private void handleProviderRegistrationInner(Element e, Class providerClass, String path) throws IllegalArgumentException, LayerGenerationException {
192
        handleProviderRegistrationInner(e, providerClass, path, null, null);
193
    }
194
195
    private void handleProviderRegistrationInner(Element e, Class providerClass, String path,
196
                                                 String[] actions, String[] enabledOnMIMETypes
197
                                                 ) throws IllegalArgumentException, LayerGenerationException {
189
        String className = instantiableClassOrMethod(e);
198
        String className = instantiableClassOrMethod(e);
190
        if (!isClassOf(e, providerClass)) {
199
        if (!isClassOf(e, providerClass)) {
191
            throw new IllegalArgumentException("Annotated element "+e+" is not an instance of " + providerClass);
200
            throw new IllegalArgumentException("Annotated element "+e+" is not an instance of " + providerClass);
Lines 195-206 Link Here
195
        } else {
204
        } else {
196
            path = "Debugger";
205
            path = "Debugger";
197
        }
206
        }
198
        layer(e).instanceFile(path, null, providerClass).
207
        File f = layer(e).instanceFile(path, null, providerClass).
199
                stringvalue("serviceName", className).
208
                stringvalue(ContextAwareServiceHandler.SERVICE_NAME, className).
200
                stringvalue("serviceClass", providerClass.getName()).
209
                stringvalue("serviceClass", providerClass.getName());
201
                stringvalue("instanceOf", providerClass.getName()).
210
        if (actions != null && actions.length > 0) {
202
                methodvalue("instanceCreate", providerClass.getName()+"$ContextAware", "createService").
211
            f.stringvalue(ContextAwareServiceHandler.SERVICE_ACTIONS, Arrays.toString(actions));
203
                write();
212
        }
213
        if (enabledOnMIMETypes != null && enabledOnMIMETypes.length > 0) {
214
            f.stringvalue(ContextAwareServiceHandler.SERVICE_ENABLED_MIMETYPES, Arrays.toString(enabledOnMIMETypes));
215
        }
216
        f.stringvalue("instanceOf", providerClass.getName());
217
        f.methodvalue("instanceCreate", providerClass.getName()+"$ContextAware", "createService");
218
        f.write();
204
    }
219
    }
205
220
206
    private boolean isClassOf(Element e, Class providerClass) {
221
    private boolean isClassOf(Element e, Class providerClass) {
(-)a/api.debugger/src/org/netbeans/spi/debugger/ActionsProvider.java (-8 / +260 lines)
Lines 41-54 Link Here
41
41
42
package org.netbeans.spi.debugger;
42
package org.netbeans.spi.debugger;
43
43
44
import java.beans.PropertyChangeEvent;
45
import java.beans.PropertyChangeListener;
44
import java.lang.annotation.ElementType;
46
import java.lang.annotation.ElementType;
45
import java.lang.annotation.Retention;
47
import java.lang.annotation.Retention;
46
import java.lang.annotation.RetentionPolicy;
48
import java.lang.annotation.RetentionPolicy;
47
import java.lang.annotation.Target;
49
import java.lang.annotation.Target;
50
import java.lang.reflect.InvocationTargetException;
51
import java.util.ArrayList;
52
import java.util.Arrays;
53
import java.util.Collections;
54
import java.util.HashSet;
55
import java.util.List;
48
import java.util.Map;
56
import java.util.Map;
49
import java.util.Set;
57
import java.util.Set;
58
50
import org.netbeans.debugger.registry.ContextAwareServiceHandler;
59
import org.netbeans.debugger.registry.ContextAwareServiceHandler;
51
import org.netbeans.spi.debugger.ContextAwareSupport;
60
import org.openide.filesystems.FileObject;
61
import org.openide.util.Exceptions;
62
import org.openide.util.Lookup;
52
import org.openide.util.RequestProcessor;
63
import org.openide.util.RequestProcessor;
53
64
54
/**
65
/**
Lines 134-166 Link Here
134
         */
145
         */
135
        String path() default "";
146
        String path() default "";
136
147
148
        /**
149
         * Provide the list of actions that this provider supports.
150
         * This list is used before an instance of the registered class is created,
151
         * it's necessary when {@link #enabledOnMIMETypes()} is overriden
152
         * to prevent from the class instantiation.
153
         * @return The list of actions.
154
         * @since 1.23
155
         */
156
        String[] getActions() default {};
157
158
        /**
159
         * Provide the list of MIME types that are compared to the MIME type of
160
         * a file currently active in the IDE and when matched, this provider
161
         * is activated (an instance of the registered class is created).
162
         * This method is used to delay the instatiation of the implementation
163
         * class for performance reasons.
164
         * @return The list of MIME types
165
         * @since 1.23
166
         */
167
        String[] enabledOnMIMETypes() default {};
168
137
    }
169
    }
138
170
139
    static class ContextAware extends ActionsProvider implements ContextAwareService<ActionsProvider> {
171
    static class ContextAware extends ActionsProvider implements ContextAwareService<ActionsProvider> {
172
173
        private static final String ERROR = "error in getting MIMEType";    // NOI18N
140
174
141
        private String serviceName;
175
        private String serviceName;
142
        private ContextProvider context;
176
        private ContextProvider context;
143
        private ActionsProvider delegate;
177
        private ActionsProvider delegate;
144
178
145
        private ContextAware(String serviceName) {
179
        private Set actions;
180
        private Set<String> enabledOnMIMETypes;
181
        private List<ActionsProviderListener> listeners = new ArrayList<ActionsProviderListener>();
182
        private PropertyChangeListener contextDispatcherListener;
183
184
        private ContextAware(String serviceName, Set actions, Set<String> enabledOnMIMETypes) {
146
            this.serviceName = serviceName;
185
            this.serviceName = serviceName;
186
            this.actions = actions;
187
            this.enabledOnMIMETypes = enabledOnMIMETypes;
147
        }
188
        }
148
189
149
        private ContextAware(String serviceName, ContextProvider context) {
190
        private ContextAware(String serviceName, Set actions, Set<String> enabledOnMIMETypes,
191
                             ContextProvider context) {
150
            this.serviceName = serviceName;
192
            this.serviceName = serviceName;
193
            this.actions = actions;
194
            this.enabledOnMIMETypes = enabledOnMIMETypes;
151
            this.context = context;
195
            this.context = context;
152
        }
196
        }
153
197
154
        private synchronized ActionsProvider getDelegate() {
198
        private synchronized ActionsProvider getDelegate() {
155
            if (delegate == null) {
199
            if (delegate == null) {
156
                delegate = (ActionsProvider) ContextAwareSupport.createInstance(serviceName, context);
200
                delegate = (ActionsProvider) ContextAwareSupport.createInstance(serviceName, context);
201
                for (ActionsProviderListener l : listeners) {
202
                    delegate.addActionsProviderListener(l);
203
                }
204
                listeners.clear();
205
                if (contextDispatcherListener != null) {
206
                    detachContextDispatcherListener();
207
                }
157
            }
208
            }
158
            return delegate;
209
            return delegate;
159
        }
210
        }
160
211
161
        @Override
212
        @Override
162
        public Set getActions() {
213
        public Set getActions() {
163
            return getDelegate().getActions();
214
            ActionsProvider actionsDelegate;
215
            if (actions != null) {
216
                synchronized (this) {
217
                    actionsDelegate = this.delegate;
218
                }
219
            } else {
220
                actionsDelegate = getDelegate();
221
            }
222
            if (actionsDelegate == null) {
223
                return actions;
224
            }
225
            return actionsDelegate.getActions();
164
        }
226
        }
165
227
166
        @Override
228
        @Override
Lines 175-198 Link Here
175
237
176
        @Override
238
        @Override
177
        public boolean isEnabled(Object action) {
239
        public boolean isEnabled(Object action) {
240
            ActionsProvider actionsDelegate;
241
            if (enabledOnMIMETypes != null) {
242
                synchronized (this) {
243
                    actionsDelegate = this.delegate;
244
                }
245
            } else {
246
                actionsDelegate = getDelegate();
247
            }
248
            if (actionsDelegate == null) {
249
                String currentMIMEType = getCurrentMIMEType();
250
                if (currentMIMEType != ERROR) {
251
                    if (!enabledOnMIMETypes.contains(currentMIMEType)) {
252
                        return false;
253
                    }
254
                }
255
            }
178
            return getDelegate().isEnabled(action);
256
            return getDelegate().isEnabled(action);
179
        }
257
        }
180
258
181
        @Override
259
        @Override
182
        public void addActionsProviderListener(ActionsProviderListener l) {
260
        public void addActionsProviderListener(ActionsProviderListener l) {
183
            getDelegate().addActionsProviderListener(l);
261
            ActionsProvider actionsDelegate;
262
            synchronized (this) {
263
                actionsDelegate = delegate;
264
                if (actionsDelegate == null) {
265
                    listeners.add(l);
266
                    if (contextDispatcherListener == null && enabledOnMIMETypes != null) {
267
                        contextDispatcherListener = attachContextDispatcherListener();
268
                    }
269
                    return ;
270
                }
271
            }
272
            actionsDelegate.addActionsProviderListener(l);
184
        }
273
        }
185
274
186
        @Override
275
        @Override
187
        public void removeActionsProviderListener(ActionsProviderListener l) {
276
        public void removeActionsProviderListener(ActionsProviderListener l) {
188
            getDelegate().removeActionsProviderListener(l);
277
            ActionsProvider actionsDelegate;
278
            synchronized (this) {
279
                actionsDelegate = delegate;
280
                if (actionsDelegate == null) {
281
                    listeners.remove(l);
282
                    if (listeners.size() == 0 && contextDispatcherListener != null) {
283
                        detachContextDispatcherListener();
284
                    }
285
                    return ;
286
                }
287
            }
288
            actionsDelegate.removeActionsProviderListener(l);
189
        }
289
        }
190
290
191
        public ActionsProvider forContext(ContextProvider context) {
291
        public ActionsProvider forContext(ContextProvider context) {
192
            if (context == this.context) {
292
            if (context == this.context) {
193
                return this;
293
                return this;
194
            } else {
294
            } else {
195
                return new ActionsProvider.ContextAware(serviceName, context);
295
                return new ActionsProvider.ContextAware(serviceName, actions, enabledOnMIMETypes, context);
196
            }
296
            }
197
        }
297
        }
198
298
Lines 205-211 Link Here
205
         */
305
         */
206
        static ContextAwareService createService(Map attrs) throws ClassNotFoundException {
306
        static ContextAwareService createService(Map attrs) throws ClassNotFoundException {
207
            String serviceName = (String) attrs.get(ContextAwareServiceHandler.SERVICE_NAME);
307
            String serviceName = (String) attrs.get(ContextAwareServiceHandler.SERVICE_NAME);
208
            return new ActionsProvider.ContextAware(serviceName);
308
            String actionsStr = (String) attrs.get(ContextAwareServiceHandler.SERVICE_ACTIONS);
309
            String enabledOnMIMETypesStr = (String) attrs.get(ContextAwareServiceHandler.SERVICE_ENABLED_MIMETYPES);
310
            String[] actions = parseArray(actionsStr);
311
            String[] enabledOnMIMETypes = parseArray(enabledOnMIMETypesStr);
312
            return new ActionsProvider.ContextAware(serviceName,
313
                                                    createSet(actions),
314
                                                    createSet(enabledOnMIMETypes));
315
        }
316
317
        private static String[] parseArray(String strArray) {
318
            if (strArray == null) {
319
                return null;
320
            }
321
            if (strArray.startsWith("[")) strArray = strArray.substring(1);
322
            if (strArray.endsWith("]")) strArray = strArray.substring(0, strArray.length() - 1);
323
            strArray = strArray.trim();
324
            int index = 0;
325
            List<String> strings = new ArrayList<String>();
326
            while (index < strArray.length()) {
327
                int index2 = strArray.indexOf(',', index);
328
                if (index2 < 0) index2 = strArray.length();
329
                if (index2 > index) {
330
                    String s = strArray.substring(index, index2).trim();
331
                    if (s.length() > 0) { // Can be trimmed to 0 length
332
                        strings.add(s);
333
                    }
334
                    index = index2 + 1;
335
                } else {
336
                    index++;
337
                    continue;
338
                }
339
            }
340
            return strings.toArray(new String[0]);
341
        }
342
343
        private static <T> Set<T> createSet(T[] array) {
344
            if (array != null) {
345
                return Collections.unmodifiableSet(new HashSet(Arrays.asList(array)));
346
            } else {
347
                return null;
348
            }
349
        }
350
351
        private static String getCurrentMIMEType() {
352
            // Ask EditorContextDispatcher.getDefault().getMostRecentFile()
353
            // It's not in a dependent module, therefore we have to find it dynamically:
354
            try {
355
                Class editorContextDispatcherClass = Lookup.getDefault().lookup(ClassLoader.class).loadClass("org.netbeans.spi.debugger.ui.EditorContextDispatcher");
356
                try {
357
                    try {
358
                        Object editorContextDispatcher = editorContextDispatcherClass.getMethod("getDefault").invoke(null);
359
                        FileObject file = (FileObject) editorContextDispatcherClass.getMethod("getMostRecentFile").invoke(editorContextDispatcher);
360
                        if (file != null) {
361
                            return file.getMIMEType();
362
                        } else {
363
                            return null;
364
                        }
365
                    } catch (IllegalAccessException ex) {
366
                        Exceptions.printStackTrace(ex);
367
                    } catch (IllegalArgumentException ex) {
368
                        Exceptions.printStackTrace(ex);
369
                    } catch (InvocationTargetException ex) {
370
                        Exceptions.printStackTrace(ex);
371
                    }
372
                } catch (NoSuchMethodException ex) {
373
                    Exceptions.printStackTrace(ex);
374
                } catch (SecurityException ex) {
375
                    Exceptions.printStackTrace(ex);
376
                }
377
            } catch (ClassNotFoundException ex) {
378
            }
379
            return ERROR;
380
        }
381
382
        private PropertyChangeListener attachContextDispatcherListener() {
383
            // Call EditorContextDispatcher.getDefault().addPropertyChangeListener(String MIMEType, PropertyChangeListener l)
384
            // It's not in a dependent module, therefore we have to find it dynamically:
385
            PropertyChangeListener l = null;
386
            try {
387
                Class editorContextDispatcherClass = Lookup.getDefault().lookup(ClassLoader.class).loadClass("org.netbeans.spi.debugger.ui.EditorContextDispatcher");
388
                try {
389
                    try {
390
                        Object editorContextDispatcher = editorContextDispatcherClass.getMethod("getDefault").invoke(null);
391
                        java.lang.reflect.Method m = editorContextDispatcherClass.getMethod(
392
                                "addPropertyChangeListener",
393
                                String.class,
394
                                PropertyChangeListener.class);
395
                        l = new ContextDispatcherListener();
396
                        for (String mimeType : enabledOnMIMETypes) {
397
                            m.invoke(editorContextDispatcher, mimeType, l);
398
                        }
399
                    } catch (IllegalAccessException ex) {
400
                        Exceptions.printStackTrace(ex);
401
                    } catch (IllegalArgumentException ex) {
402
                        Exceptions.printStackTrace(ex);
403
                    } catch (InvocationTargetException ex) {
404
                        Exceptions.printStackTrace(ex);
405
                    }
406
                } catch (NoSuchMethodException ex) {
407
                    Exceptions.printStackTrace(ex);
408
                } catch (SecurityException ex) {
409
                    Exceptions.printStackTrace(ex);
410
                }
411
            } catch (ClassNotFoundException ex) {
412
            }
413
            return l;
414
        }
415
416
        private void detachContextDispatcherListener() {
417
            // Call EditorContextDispatcher.getDefault().removePropertyChangeListener(PropertyChangeListener l)
418
            // It's not in a dependent module, therefore we have to find it dynamically:
419
            PropertyChangeListener l = null;
420
            try {
421
                Class editorContextDispatcherClass = Lookup.getDefault().lookup(ClassLoader.class).loadClass("org.netbeans.spi.debugger.ui.EditorContextDispatcher");
422
                try {
423
                    try {
424
                        Object editorContextDispatcher = editorContextDispatcherClass.getMethod("getDefault").invoke(null);
425
                        java.lang.reflect.Method m = editorContextDispatcherClass.getMethod(
426
                                "removePropertyChangeListener",
427
                                PropertyChangeListener.class);
428
                        m.invoke(editorContextDispatcher, contextDispatcherListener);
429
                        contextDispatcherListener = null;
430
                    } catch (IllegalAccessException ex) {
431
                        Exceptions.printStackTrace(ex);
432
                    } catch (IllegalArgumentException ex) {
433
                        Exceptions.printStackTrace(ex);
434
                    } catch (InvocationTargetException ex) {
435
                        Exceptions.printStackTrace(ex);
436
                    }
437
                } catch (NoSuchMethodException ex) {
438
                    Exceptions.printStackTrace(ex);
439
                } catch (SecurityException ex) {
440
                    Exceptions.printStackTrace(ex);
441
                }
442
            } catch (ClassNotFoundException ex) {
443
            }
444
        }
445
446
        private class ContextDispatcherListener implements PropertyChangeListener {
447
448
            @Override
449
            public void propertyChange(PropertyChangeEvent evt) {
450
                List<ActionsProviderListener> ls;
451
                synchronized (ContextAware.this) {
452
                    ls = new ArrayList<ActionsProviderListener>(listeners);
453
                }
454
                for (ActionsProviderListener l : ls) {
455
                    for (Object action : actions) {
456
                        l.actionStateChange(action, isEnabled(action));
457
                    }
458
                }
459
            }
460
            
209
        }
461
        }
210
462
211
    }
463
    }
(-)a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EditorContextDispatcher.java (+14 lines)
Lines 277-282 Link Here
277
     */
277
     */
278
    public synchronized FileObject getMostRecentFile() {
278
    public synchronized FileObject getMostRecentFile() {
279
        return mostRecentFileRef.get();
279
        return mostRecentFileRef.get();
280
    }
281
282
    /** Used by unit test only */
283
    void setMostRecentFile(FileObject file) {
284
        Object oldFile;
285
        String MIMEType = null;
286
        synchronized (this) {
287
            oldFile = mostRecentFileRef.get();
288
            mostRecentFileRef = new WeakReference(file);
289
            if (file != null) {
290
                MIMEType = file.getMIMEType();
291
            }
292
        }
293
        refreshProcessor.post(new EventFirer(PROP_EDITOR, oldFile, file, MIMEType));
280
    }
294
    }
281
295
282
    /**
296
    /**
(-)a/spi.debugger.ui/test/unit/src/org/netbeans/api/debugger/ProvidersAnnotationTest.java (-2 / +221 lines)
Lines 39-47 Link Here
39
39
40
package org.netbeans.api.debugger;
40
package org.netbeans.api.debugger;
41
41
42
import java.io.FileNotFoundException;
43
import java.io.IOException;
44
import java.io.InputStream;
45
import java.io.OutputStream;
46
import java.util.Date;
47
import java.util.Enumeration;
42
import java.util.List;
48
import java.util.List;
43
49
44
import junit.framework.Test;
45
import org.netbeans.api.debugger.providers.TestActionProvider;
50
import org.netbeans.api.debugger.providers.TestActionProvider;
46
import org.netbeans.api.debugger.providers.TestAttachType;
51
import org.netbeans.api.debugger.providers.TestAttachType;
47
import org.netbeans.api.debugger.providers.TestBreakpointType;
52
import org.netbeans.api.debugger.providers.TestBreakpointType;
Lines 49-68 Link Here
49
import org.netbeans.api.debugger.providers.TestExtendedNodeModelFilter;
54
import org.netbeans.api.debugger.providers.TestExtendedNodeModelFilter;
50
import org.netbeans.api.debugger.providers.TestLazyActionsManagerListenerAnnotated;
55
import org.netbeans.api.debugger.providers.TestLazyActionsManagerListenerAnnotated;
51
import org.netbeans.api.debugger.providers.TestLazyDebuggerManagerListenerAnnotated;
56
import org.netbeans.api.debugger.providers.TestLazyDebuggerManagerListenerAnnotated;
57
import org.netbeans.api.debugger.providers.TestMIMETypeSensitiveActionProvider;
52
import org.netbeans.api.debugger.providers.TestThreeModels;
58
import org.netbeans.api.debugger.providers.TestThreeModels;
53
import org.netbeans.junit.NbModuleSuite;
54
import org.netbeans.modules.debugger.ui.models.ColumnModels;
59
import org.netbeans.modules.debugger.ui.models.ColumnModels;
55
import org.netbeans.spi.debugger.ActionsProvider;
60
import org.netbeans.spi.debugger.ActionsProvider;
61
import org.netbeans.spi.debugger.ActionsProviderListener;
56
import org.netbeans.spi.debugger.DebuggerEngineProvider;
62
import org.netbeans.spi.debugger.DebuggerEngineProvider;
57
import org.netbeans.spi.debugger.SessionProvider;
63
import org.netbeans.spi.debugger.SessionProvider;
58
import org.netbeans.spi.debugger.ui.AttachType;
64
import org.netbeans.spi.debugger.ui.AttachType;
59
import org.netbeans.spi.debugger.ui.BreakpointType;
65
import org.netbeans.spi.debugger.ui.BreakpointType;
66
import org.netbeans.spi.debugger.ui.EditorContextDispatcherManager;
60
import org.netbeans.spi.viewmodel.ColumnModel;
67
import org.netbeans.spi.viewmodel.ColumnModel;
61
import org.netbeans.spi.viewmodel.ExtendedNodeModelFilter;
68
import org.netbeans.spi.viewmodel.ExtendedNodeModelFilter;
62
import org.netbeans.spi.viewmodel.NodeModel;
69
import org.netbeans.spi.viewmodel.NodeModel;
63
import org.netbeans.spi.viewmodel.NodeModelFilter;
70
import org.netbeans.spi.viewmodel.NodeModelFilter;
64
import org.netbeans.spi.viewmodel.TableModel;
71
import org.netbeans.spi.viewmodel.TableModel;
65
import org.netbeans.spi.viewmodel.TreeModel;
72
import org.netbeans.spi.viewmodel.TreeModel;
73
import org.openide.filesystems.FileChangeListener;
74
import org.openide.filesystems.FileLock;
75
import org.openide.filesystems.FileObject;
76
import org.openide.filesystems.FileStateInvalidException;
77
import org.openide.filesystems.FileSystem;
78
import org.openide.filesystems.LocalFileSystem;
66
79
67
/**
80
/**
68
 *
81
 *
Lines 200-203 Link Here
200
        //assertEquals(ColumnModels.createLocalsToStringColumn().getDisplayName(), list.get(3).getDisplayName()); - was made hidden!
213
        //assertEquals(ColumnModels.createLocalsToStringColumn().getDisplayName(), list.get(3).getDisplayName()); - was made hidden!
201
        }
214
        }
202
    }
215
    }
216
217
    public void testMIMETypeSensitiveActionProviders() throws Exception {
218
        Lookup.MetaInf l = new Lookup.MetaInf("unittest_MIME");
219
220
        List<? extends ActionsProvider> list = l.lookup(null, ActionsProvider.class);
221
        assertEquals("No test action provider instance should be created yet!", 0, TestMIMETypeSensitiveActionProvider.INSTANCES.size());
222
        assertInstanceOf("Wrong looked up object", list.get(0), ActionsProvider.class);
223
        ActionsProvider ap = list.get(0);
224
        Object action = ap.getActions().iterator().next();
225
        assertEquals(TestMIMETypeSensitiveActionProvider.ACTION_OBJECT, action);
226
        assertEquals("No test action provider instance should be created yet!", 0, TestMIMETypeSensitiveActionProvider.INSTANCES.size());
227
        ap.isEnabled(action);
228
        assertEquals("No test action provider instance should be created yet!", 0, TestMIMETypeSensitiveActionProvider.INSTANCES.size());
229
        final Boolean[] actionStateChanged = new Boolean[] { null };
230
        ap.addActionsProviderListener(new ActionsProviderListener() {
231
            @Override
232
            public void actionStateChange(Object action, boolean enabled) {
233
                actionStateChanged[0] = enabled;
234
            }
235
        });
236
        assertEquals("No test action provider instance should be created yet!", 0, TestMIMETypeSensitiveActionProvider.INSTANCES.size());
237
238
        /*
239
        LocalFileSystem fs = new LocalFileSystem();
240
        fs.setRootDirectory(new File("/tmp"));
241
        Repository.getDefault().addFileSystem(fs);
242
         */
243
        FileObject f = createCFile();
244
        EditorContextDispatcherManager.setMostRecentFile(f);
245
        Thread.sleep(500);
246
        assertEquals("No test action provider instance should be created yet!", 0, TestMIMETypeSensitiveActionProvider.INSTANCES.size());
247
248
        f = createJavaFile();
249
        EditorContextDispatcherManager.setMostRecentFile(f);
250
        Thread.sleep(500);
251
        assertEquals("One test action provider instance should be created!", 1, TestMIMETypeSensitiveActionProvider.INSTANCES.size());
252
253
    }
254
255
    private static FileObject createCFile() throws IOException {
256
        /* Creates FileObject with unknown content type without full IDE
257
        File file = File.createTempFile("Foo", ".c");
258
        FileWriter fw = new FileWriter(file);
259
        fw.append("#include <stdio.h>\n\nmain() {\n  printf(\"Hi there!\");\n}\n");
260
        fw.flush();
261
        fw.close();
262
        fs.refresh(true);
263
        return FileUtil.toFileObject(file);
264
         */
265
        return new FileObjectWithMIMEType("text/x-c");
266
    }
267
    
268
    private static FileObject createJavaFile() throws IOException {
269
        /* Creates FileObject with unknown content type without full IDE
270
        File file = File.createTempFile("Foo", ".java");
271
        FileWriter fw = new FileWriter(file);
272
        fw.append("\nmain(String[] args) {\n  System.out.println(\"Hi there!\");\n}\n");
273
        fw.flush();
274
        fw.close();
275
        fs.refresh(true);
276
        return FileUtil.toFileObject(file);
277
         */
278
        return new FileObjectWithMIMEType("text/x-java");
279
    }
280
281
    /** Test FileObject implementation that provides a given MIME type */
282
    private static class FileObjectWithMIMEType extends FileObject {
283
284
        private String MIMEType;
285
286
        public FileObjectWithMIMEType(String MIMEType) {
287
            this.MIMEType = MIMEType;
288
        }
289
290
        @Override
291
        public String getMIMEType() {
292
            return MIMEType;
293
        }
294
295
        @Override
296
        public String getName() {
297
            return "Test Name";
298
        }
299
300
        @Override
301
        public String getExt() {
302
            return "Test ext.";
303
        }
304
305
        @Override
306
        public void rename(FileLock lock, String name, String ext) throws IOException {
307
            throw new UnsupportedOperationException("Not supported.");
308
        }
309
310
        @Override
311
        public FileSystem getFileSystem() throws FileStateInvalidException {
312
            return new LocalFileSystem();
313
        }
314
315
        @Override
316
        public FileObject getParent() {
317
            return null;
318
        }
319
320
        @Override
321
        public boolean isFolder() {
322
            return false;
323
        }
324
325
        @Override
326
        public Date lastModified() {
327
            return new Date();
328
        }
329
330
        @Override
331
        public boolean isRoot() {
332
            return false;
333
        }
334
335
        @Override
336
        public boolean isData() {
337
            return true;
338
        }
339
340
        @Override
341
        public boolean isValid() {
342
            return true;
343
        }
344
345
        @Override
346
        public void delete(FileLock lock) throws IOException {
347
            throw new UnsupportedOperationException("Not supported.");
348
        }
349
350
        @Override
351
        public Object getAttribute(String attrName) {
352
            return null;
353
        }
354
355
        @Override
356
        public void setAttribute(String attrName, Object value) throws IOException {
357
        }
358
359
        @Override
360
        public Enumeration<String> getAttributes() {
361
            return null;
362
        }
363
364
        @Override
365
        public void addFileChangeListener(FileChangeListener fcl) {
366
        }
367
368
        @Override
369
        public void removeFileChangeListener(FileChangeListener fcl) {
370
        }
371
372
        @Override
373
        public long getSize() {
374
            return 1000;
375
        }
376
377
        @Override
378
        public InputStream getInputStream() throws FileNotFoundException {
379
            throw new UnsupportedOperationException("Not supported.");
380
        }
381
382
        @Override
383
        public OutputStream getOutputStream(FileLock lock) throws IOException {
384
            throw new UnsupportedOperationException("Not supported.");
385
        }
386
387
        @Override
388
        public FileLock lock() throws IOException {
389
            throw new UnsupportedOperationException("Not supported.");
390
        }
391
392
        @Override
393
        public void setImportant(boolean b) {
394
        }
395
396
        @Override
397
        public FileObject[] getChildren() {
398
            return new FileObject[] {};
399
        }
400
401
        @Override
402
        public FileObject getFileObject(String name, String ext) {
403
            return null;
404
        }
405
406
        @Override
407
        public FileObject createFolder(String name) throws IOException {
408
            throw new UnsupportedOperationException("Not supported.");
409
        }
410
411
        @Override
412
        public FileObject createData(String name, String ext) throws IOException {
413
            throw new UnsupportedOperationException("Not supported.");
414
        }
415
416
        @Override
417
        public boolean isReadOnly() {
418
            return true;
419
        }
420
        
421
    }
203
}
422
}
(-)3fe06f4d27a4 (+86 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.api.debugger.providers;
41
42
import java.util.Collections;
43
import java.util.HashSet;
44
import java.util.Set;
45
import org.netbeans.spi.debugger.ActionsProvider;
46
import org.netbeans.spi.debugger.ActionsProviderListener;
47
48
/**
49
 *
50
 * @author Martin Entlicher
51
 */
52
@ActionsProvider.Registration(path="unittest_MIME", getActions={"MIMETypeSensitiveAction"}, enabledOnMIMETypes={ "text/x-java" })
53
public class TestMIMETypeSensitiveActionProvider extends ActionsProvider {
54
55
    public static Object ACTION_OBJECT = "MIMETypeSensitiveAction";
56
57
    public static Set<TestMIMETypeSensitiveActionProvider> INSTANCES = new HashSet<TestMIMETypeSensitiveActionProvider>();
58
59
    public TestMIMETypeSensitiveActionProvider() {
60
        INSTANCES.add(this);
61
    }
62
63
    @Override
64
    public Set getActions() {
65
        return Collections.singleton(ACTION_OBJECT);
66
    }
67
68
    @Override
69
    public void doAction(Object action) {
70
        throw new UnsupportedOperationException("Not supported yet.");
71
    }
72
73
    @Override
74
    public boolean isEnabled(Object action) {
75
        return true;
76
    }
77
78
    @Override
79
    public void addActionsProviderListener(ActionsProviderListener l) {
80
    }
81
82
    @Override
83
    public void removeActionsProviderListener(ActionsProviderListener l) {
84
    }
85
86
}
(-)3fe06f4d27a4 (+53 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.spi.debugger.ui;
41
42
import org.openide.filesystems.FileObject;
43
44
/**
45
 * Manages the state of EditorContextDispatcher.
46
 * @author martin
47
 */
48
public class EditorContextDispatcherManager {
49
50
    public static void setMostRecentFile(FileObject file) {
51
        EditorContextDispatcher.getDefault().setMostRecentFile(file);
52
    }
53
}

Return to bug 177561