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

(-)a/junit/src/org/netbeans/modules/junit/ClassNameTextField.java (-1 / +1 lines)
Lines 42-48 Link Here
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
44
45
package org.netbeans.modules.junit;
45
package org.netbeans.modules.gsf.testrunner;
46
46
47
import javax.swing.JTextField;
47
import javax.swing.JTextField;
48
import javax.swing.event.ChangeEvent;
48
import javax.swing.event.ChangeEvent;
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/CommonTestsCfgOfCreate.java (+1203 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.gsf.testrunner;
46
47
//import org.netbeans.modules.gsf.testrunner.CommonSettings;
48
//import org.netbeans.modules.gsf.testrunner.ClassNameTextField;
49
import java.awt.*;
50
import java.awt.event.ActionListener;
51
import java.awt.event.ItemEvent;
52
import java.awt.event.ItemListener;
53
import java.util.List;
54
import java.util.*;
55
import javax.swing.*;
56
import javax.swing.border.Border;
57
import javax.swing.border.CompoundBorder;
58
import javax.swing.border.TitledBorder;
59
import javax.swing.event.ChangeEvent;
60
import javax.swing.event.ChangeListener;
61
import javax.swing.plaf.UIResource;
62
import javax.swing.text.JTextComponent;
63
import org.netbeans.api.java.classpath.ClassPath;
64
import org.netbeans.api.java.project.JavaProjectConstants;
65
import org.netbeans.api.project.FileOwnerQuery;
66
import org.netbeans.api.project.Project;
67
import org.netbeans.api.project.SourceGroup;
68
import org.netbeans.api.project.SourceGroupModifier;
69
import org.netbeans.modules.gsf.testrunner.ClassNameTextField;
70
//import org.netbeans.modules.gsf.testrunner.CommonSettings;
71
//import org.netbeans.modules.gsf.testrunner.GuiUtils;
72
import org.netbeans.modules.gsf.testrunner.MessageStack;
73
import org.netbeans.modules.gsf.testrunner.api.CommonSettings;
74
import org.netbeans.modules.gsf.testrunner.api.CommonTestUtil;
75
import org.netbeans.modules.gsf.testrunner.api.GuiUtils;
76
import org.netbeans.modules.gsf.testrunner.api.SelfResizingPanel;
77
import org.openide.DialogDescriptor;
78
import org.openide.DialogDisplayer;
79
import org.openide.awt.Mnemonics;
80
import org.openide.filesystems.FileObject;
81
import org.openide.filesystems.FileUtil;
82
import org.openide.loaders.DataFolder;
83
import org.openide.loaders.DataObject;
84
import org.openide.nodes.Node;
85
import org.openide.util.HelpCtx;
86
import org.openide.util.Lookup;
87
import org.openide.util.NbBundle;
88
89
90
/**
91
 *
92
 * @author  vstejskal
93
 * @author  Marian Petras
94
 */
95
@SuppressWarnings("serial")
96
public class CommonTestsCfgOfCreate extends SelfResizingPanel implements ChangeListener {
97
    
98
    /** suffix of test classes */
99
    private static final String TEST_CLASS_SUFFIX = "Test";             //NOI18N
100
    
101
    /**
102
     * nodes selected when the Create Tests action was invoked
103
     */
104
    private  Node[] nodes;
105
    /** whether the tests will be created for multiple classes */
106
    private  boolean multipleClasses;
107
    /** whether a single package/folder is selected */
108
    private boolean singlePackage;
109
    /** whether a single class is selected */
110
    private boolean singleClass;
111
    /** test class name specified in the form (or <code>null</code>) */
112
    private String testClassName;
113
    /** registered change listeners */
114
    private List<ChangeListener> changeListeners;
115
    /** */
116
    private String initialMessage;
117
    /** */
118
    private List<String> testingFrameworks;
119
//    public static final String JUNIT_TEST_FRAMEWORK = "JUnit";             //NOI18N
120
//    public static final String TESTNG_TEST_FRAMEWORK = "TestNG";             //NOI18N
121
    private String selectedTestingFramework = null;
122
    
123
    /**
124
     * is at least one target folder/source group available?
125
     *
126
     * @see  #isAcceptable()
127
     */
128
    private boolean hasTargetFolders = false;
129
130
    /**
131
     * is the entered class name non-empty and valid?
132
     *
133
     * @see  #isAcceptable()
134
     */
135
    private boolean classNameValid;
136
    
137
    /**
138
     * is the current form contents acceptable?
139
     *
140
     * @see  #isAcceptable()
141
     */
142
    private boolean isAcceptable;
143
    
144
    /** layer index for a message about an empty set of target folders */
145
    private static final int MSG_TYPE_NO_TARGET_FOLDERS = 0;
146
    /** layer index for a message about invalid class name */
147
    private static final int MSG_TYPE_CLASSNAME_INVALID = 1;
148
    /** layer index for a message about non-default class name */
149
    private static final int MSG_TYPE_CLASSNAME_NOT_DEFAULT = 2;
150
    /** layer index for a message about modified files */
151
    private static final int MSG_TYPE_MODIFIED_FILES = 3;
152
    /** */
153
    private MessageStack msgStack = new MessageStack(4);
154
    
155
    public CommonTestsCfgOfCreate(Node[] nodes) {
156
        assert (nodes != null) && (nodes.length != 0);
157
        this.nodes = nodes;
158
    }
159
160
    /**
161
     * Creates a configuration panel.
162
     *
163
     * @param nodes  nodes selected when the Create Tests action was invoked
164
     * @param isShowMsgFilesWillBeSaved if {@code true} then a warning message
165
     *        like "Warning: All modified files will be saved." will be
166
     *        displayed on the panel, otherwise (i.e. if {@code false}) then
167
     *        the message won't be displayed.
168
     */
169
    public void createCfgPanel(boolean isShowMsgFilesWillBeSaved) {
170
//        assert (nodes != null) && (nodes.length != 0);
171
//        this.nodes = nodes;
172
        multipleClasses = checkMultipleClasses();
173
        
174
        initBundle();
175
        try {
176
            initComponents();
177
            if(isShowMsgFilesWillBeSaved) {
178
                String msg = bundle.getString("MSG_MODIFIED_FILES"); // NOI18N
179
                setMessage(msg, MSG_TYPE_MODIFIED_FILES);
180
            }
181
            setBorder(BorderFactory.createEmptyBorder(12, 12, 0, 11));
182
            addAccessibleDescriptions();
183
            initializeCheckBoxStates();
184
            fillFormData();
185
            checkAcceptability();
186
            setupUserInteraction();
187
            
188
            /*
189
             * checkAcceptability() must not be called
190
             *        before initializeCheckBoxStates() and fillFormData()
191
             * setupUserInteraction must not be called
192
             *        before initializeCheckBoxStates()
193
             */
194
            
195
        } finally {
196
            unlinkBundle();
197
        }
198
    }
199
    
200
    private void addAccessibleDescriptions() {
201
        
202
        // window
203
        this.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.AD"));
204
        
205
        // text-field and combo-box
206
        
207
        if (this.tfClassName != null) {
208
            this.tfClassName.setToolTipText(
209
                  bundle.getString("CommonTestsCfgOfCreate.clsName.toolTip"));//NOI18N
210
            this.tfClassName.getAccessibleContext().setAccessibleName(
211
                  bundle.getString("CommonTestsCfgOfCreate.clsName.AN"));     //NOI18N
212
            this.tfClassName.getAccessibleContext().setAccessibleDescription(
213
                  bundle.getString("CommonTestsCfgOfCreate.clsName.AD"));     //NOI18N
214
        }
215
        
216
        this.cboxLocation.setToolTipText(
217
                bundle.getString("CommonTestsCfgOfCreate.location.toolTip")); //NOI18N
218
        this.cboxLocation.getAccessibleContext().setAccessibleName(
219
                bundle.getString("CommonTestsCfgOfCreate.location.AN"));      //NOI18N
220
        this.cboxLocation.getAccessibleContext().setAccessibleDescription(
221
                bundle.getString("CommonTestsCfgOfCreate.location.AD"));      //NOI18N
222
        
223
        this.cboxLocation.setToolTipText(
224
                bundle.getString("CommonTestsCfgOfCreate.framework.toolTip")); //NOI18N
225
        this.cboxLocation.getAccessibleContext().setAccessibleName(
226
                bundle.getString("CommonTestsCfgOfCreate.framework.AN"));      //NOI18N
227
        this.cboxLocation.getAccessibleContext().setAccessibleDescription(
228
                bundle.getString("CommonTestsCfgOfCreate.framework.AD"));      //NOI18N
229
        
230
        // check boxes
231
        this.chkPublic.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkPublic.toolTip"));
232
        this.chkPublic.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkPublic.AD"));        
233
        
234
        this.chkProtected.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkProtected.toolTip"));
235
        this.chkProtected.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkProtected.AD"));        
236
        
237
        this.chkPackage.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkPackage.toolTip"));
238
        this.chkPackage.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkPackage.AD"));
239
        
240
        this.chkComments.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkComments.toolTip"));        
241
        this.chkComments.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkComments.AD"));
242
        
243
        this.chkContent.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkContent.toolTip"));
244
        this.chkContent.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkContent.AD"));
245
        
246
        this.chkJavaDoc.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkJavaDoc.toolTip"));
247
        this.chkJavaDoc.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkJavaDoc.AD"));
248
        
249
        if (multipleClasses) {
250
            this.chkExceptions.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkExceptions.toolTip"));
251
            this.chkExceptions.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkExceptions.AD"));
252
        
253
            this.chkAbstractImpl.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkAbstractImpl.toolTip"));
254
            this.chkAbstractImpl.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkAbstractImpl.AD"));
255
        
256
            this.chkPackagePrivateClasses.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkPackagePrivateClasses.toolTip"));
257
            this.chkPackagePrivateClasses.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkPackagePrivateClasses.AD"));
258
        
259
            this.chkGenerateSuites.setToolTipText(bundle.getString("CommonTestsCfgOfCreate.chkGenerateSuites.toolTip"));
260
            this.chkGenerateSuites.getAccessibleContext().setAccessibleDescription(bundle.getString("CommonTestsCfgOfCreate.chkGenerateSuites.AD"));
261
        }
262
        
263
    }
264
    
265
    /**
266
     * Checks whether multiple classes may be selected.
267
     * It also detects whether exactly one package/folder or exactly one class
268
     * is selected and sets values of variables {@link #singlePackage}
269
     * and {@link #singleClass} accordingly.
270
     *
271
     * @return  <code>false</code> if there is exactly one node selected
272
     *          and the node represents a single <code>DataObject</code>,
273
     *          not a folder or another <code>DataObject</code> container;
274
     *          <code>true</code> otherwise
275
     */
276
    private boolean checkMultipleClasses() {
277
        if (nodes.length > 1) {
278
            return true;
279
        }
280
        
281
        Lookup nodeLookup = nodes[0].getLookup();
282
        if (nodeLookup.lookup(DataObject.Container.class) != null) {
283
            singlePackage = nodeLookup.lookup(DataFolder.class)
284
                            != null;
285
            return true;
286
        }
287
        
288
        singleClass = false;
289
        DataObject dataObj = nodeLookup.lookup(DataObject.class);
290
        if (dataObj == null) {
291
            return true;
292
        }
293
        
294
        singleClass = dataObj.getPrimaryFile().isData();
295
        return !singleClass;
296
    }
297
    
298
    /**
299
     * Displays a configuration dialog and updates JUnit options according
300
     * to the user's settings.
301
     *
302
     * @param  nodes  nodes selected when the Create Test action was invoked
303
     */
304
    public boolean configure() {
305
        
306
        // create and display the dialog:
307
        String title = NbBundle.getMessage(GuiUtils.class,
308
                                           "CommonTestsCfgOfCreate.Title");   //NOI18N
309
        ChangeListener changeListener;
310
        final JButton btnOK = new JButton(
311
                NbBundle.getMessage(GuiUtils.class, "LBL_OK")); //NOI18N
312
        btnOK.getAccessibleContext().setAccessibleName(NbBundle.getMessage(GuiUtils.class, "AN_OK"));
313
        btnOK.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(GuiUtils.class, "AD_OK"));
314
        btnOK.setEnabled(isAcceptable());
315
        addChangeListener(changeListener = new ChangeListener() {
316
            @Override
317
            public void stateChanged(ChangeEvent e) {
318
                btnOK.setEnabled(isAcceptable());
319
            }
320
        });
321
        
322
        Object returned = DialogDisplayer.getDefault().notify(
323
                new DialogDescriptor (
324
                        this,
325
                        title,
326
                        true,                       //modal
327
                        new Object[] {btnOK, DialogDescriptor.CANCEL_OPTION},
328
                        btnOK,                      //initial value
329
                        DialogDescriptor.DEFAULT_ALIGN,
330
                        new HelpCtx(CommonTestsCfgOfCreate.class),
331
                        (ActionListener) null
332
                ));
333
        removeChangeListener(changeListener);
334
        
335
        if (returned == btnOK) {
336
            rememberCheckBoxStates();
337
            testClassName = (tfClassName != null) ? tfClassName.getText() 
338
                                                  : null;
339
            return true;
340
        }
341
        return false;
342
    }
343
    
344
    /**
345
     * Returns whether a test for a single class is to be created.
346
     *
347
     * @return  true if there is only one node selected and the node
348
     *          represents a class
349
     */
350
    public boolean isSingleClass() {
351
        return singleClass;
352
    }
353
354
    public boolean isSinglePackage() {
355
        return singlePackage;
356
    }
357
    
358
    /**
359
     * Returns the class name entered in the text-field.
360
     *
361
     * @return  class name entered in the form,
362
     *          or <code>null</code> if the form did not contain
363
     *          the field for entering class name
364
     */
365
    public String getTestClassName() {
366
        return testClassName;
367
    }
368
    
369
    /** resource bundle used during initialization of this panel */
370
    public ResourceBundle bundle;
371
    
372
    /**
373
     * Reads JUnit settings and initializes checkboxes accordingly.
374
     *
375
     * @see  #rememberCheckBoxStates
376
     */
377
    private void initializeCheckBoxStates() {
378
        final CommonSettings settings = CommonSettings.getDefault();
379
        
380
        chkPublic.setSelected(settings.isMembersPublic());
381
        chkProtected.setSelected(settings.isMembersProtected());
382
        chkPackage.setSelected(settings.isMembersPackage());
383
        chkComments.setSelected(settings.isBodyComments());
384
        chkContent.setSelected(settings.isBodyContent());
385
        chkJavaDoc.setSelected(settings.isJavaDoc());        
386
        if (multipleClasses) {
387
            chkGenerateSuites.setSelected(settings.isGenerateSuiteClasses());        
388
            chkPackagePrivateClasses.setSelected(
389
                    settings.isIncludePackagePrivateClasses());
390
            chkAbstractImpl.setSelected(settings.isGenerateAbstractImpl());
391
            chkExceptions.setSelected(settings.isGenerateExceptionClasses());
392
        }
393
        chkSetUp.setSelected(settings.isGenerateSetUp());
394
        chkTearDown.setSelected(settings.isGenerateTearDown());
395
    }
396
    
397
    /**
398
     * Stores settings given by checkbox states to JUnit settings.
399
     *
400
     * @see  #initializeCheckBoxStatesf
401
     */
402
    private void rememberCheckBoxStates() {
403
        final CommonSettings settings = CommonSettings.getDefault();
404
        
405
        settings.setMembersPublic(chkPublic.isSelected());
406
        settings.setMembersProtected(chkProtected.isSelected());
407
        settings.setMembersPackage(chkPackage.isSelected());
408
        settings.setBodyComments(chkComments.isSelected());
409
        settings.setBodyContent(chkContent.isSelected());
410
        settings.setJavaDoc(chkJavaDoc.isSelected());
411
        if (multipleClasses) {
412
            settings.setGenerateSuiteClasses(chkGenerateSuites.isSelected());
413
            settings.setIncludePackagePrivateClasses(
414
                    chkPackagePrivateClasses.isSelected());
415
            settings.setGenerateAbstractImpl(chkAbstractImpl.isSelected());
416
            settings.setGenerateExceptionClasses(chkExceptions.isSelected());
417
        }
418
        settings.setGenerateSetUp(chkSetUp.isSelected());
419
        settings.setGenerateTearDown(chkTearDown.isSelected());
420
    }
421
    
422
    /**
423
     * Loads a resource bundle so that it can be used during intialization
424
     * of this panel.
425
     *
426
     * @see  #unlinkBundle
427
     */
428
    private void initBundle() {
429
        bundle = NbBundle.getBundle(GuiUtils.class);
430
    }
431
    
432
    /**
433
     * Nulls the resource bundle so that it is not held in memory when it is
434
     * not used.
435
     *
436
     * @see  #initBundle
437
     */
438
    private void unlinkBundle() {
439
        bundle = null;
440
    }
441
    
442
    /**
443
     * This method is called from within the constructor to initialize the form.
444
     */
445
    private void initComponents() {
446
        setLayout(new BorderLayout(0, 12));
447
        
448
        add(createNameAndLocationPanel(), BorderLayout.NORTH);
449
        add(createMessagePanel(), BorderLayout.CENTER);
450
        add(createCodeGenPanel(), BorderLayout.SOUTH);
451
    }
452
    
453
    /**
454
     */
455
    private void setupUserInteraction() {
456
        final ItemListener listener = new CheckBoxListener();
457
458
        chkPublic.addItemListener(listener);
459
        chkProtected.addItemListener(listener);
460
        chkPackage.addItemListener(listener);
461
    }
462
    
463
    /**
464
     * Listener object that listens on state changes of some check-boxes.
465
     */
466
    private final class CheckBoxListener implements ItemListener {
467
        public CheckBoxListener () {}
468
        
469
        @Override
470
        public void itemStateChanged(ItemEvent e) {
471
            final Object source = e.getSource();
472
            
473
            assert source == chkPublic
474
                   || source == chkProtected
475
                   || source == chkPackage;
476
            checkAcceptability();
477
        }
478
        
479
    }
480
    
481
//    public String getTestingFramework() {
482
//        Object selectedTestingFramework = cboxFramework.getSelectedItem();
483
//        if(selectedTestingFramework == null) {
484
//            return null;
485
//        }
486
//        return selectedTestingFramework.toString().equals(TESTNG_TEST_FRAMEWORK) ? TESTNG_TEST_FRAMEWORK : JUNIT_TEST_FRAMEWORK;
487
//    }
488
    
489
    private String getTestingFrameworkFolder() {
490
        Object tf = cboxFramework.getSelectedItem();
491
        if(tf == null) {
492
            return "";
493
        }
494
        return tf.toString().equals(GuiUtils.TESTNG_TEST_FRAMEWORK) ? "testng." : ""; //NOI18N
495
    }
496
    
497
    private void fireFrameworkChanged() {
498
        if (tfClassName != null) {
499
            DataObject dataObj = nodes[0].getLookup().lookup(DataObject.class);
500
            FileObject fileObj = dataObj.getPrimaryFile();
501
502
            ClassPath cp = ClassPath.getClassPath(fileObj, ClassPath.SOURCE);
503
            String className = cp.getResourceName(fileObj, '.', false);
504
505
            String prefilledName = getTestingFrameworkFolder() + className + TEST_CLASS_SUFFIX;
506
            tfClassName.setText(prefilledName);
507
            tfClassName.setDefaultText(prefilledName);
508
            tfClassName.setCaretPosition(prefilledName.length());
509
        }
510
        setSelectedTestingFramework();
511
    }
512
    
513
    private void setSelectedTestingFramework() {
514
        Object tf = cboxFramework.getSelectedItem();
515
        if(tf != null) {
516
            selectedTestingFramework = tf.toString();
517
        }
518
    }
519
    
520
    public String getSelectedTestingFramework() {
521
        return selectedTestingFramework;
522
    }
523
    
524
    public void addTestingFrameworks(ArrayList<String> testingFrameworksToAdd) {
525
        for(String testingFramework : testingFrameworksToAdd) {
526
            testingFrameworks.add(testingFramework);
527
        }
528
        cboxFramework.setModel(new DefaultComboBoxModel(testingFrameworks.toArray()));
529
        fireFrameworkChanged();
530
    }
531
    
532
    /**
533
     */
534
    private Component createNameAndLocationPanel() {
535
        JPanel panel = new JPanel();
536
        
537
        final boolean askForClassName = singleClass;
538
        
539
        JLabel lblClassToTest = new JLabel();
540
        JLabel lblClassName = askForClassName ? new JLabel() : null;
541
        JLabel lblLocation = new JLabel();
542
        JLabel lblFramework = new JLabel();
543
        
544
        String classToTestKey = singlePackage
545
                                ? "LBL_PackageToTest"                   //NOI18N
546
                                : singleClass
547
                                  ? "LBL_ClassToTest"                   //NOI18N
548
                                  : "LBL_MultipleClassesSelected";      //NOI18N
549
                                    
550
        Mnemonics.setLocalizedText(
551
                lblClassToTest,
552
                NbBundle.getMessage(GuiUtils.class, classToTestKey));
553
        if (askForClassName) {
554
            Mnemonics.setLocalizedText(
555
                    lblClassName,
556
                    NbBundle.getMessage(GuiUtils.class, "LBL_ClassName"));  //NOI18N
557
        }
558
        Mnemonics.setLocalizedText(
559
                lblLocation,
560
                NbBundle.getMessage(GuiUtils.class, "LBL_Location"));       //NOI18N
561
        Mnemonics.setLocalizedText(
562
                lblFramework,
563
                NbBundle.getMessage(GuiUtils.class, "LBL_Framework"));       //NOI18N
564
        
565
        if (singlePackage || singleClass) {
566
            lblClassToTestValue = new JLabel();
567
        }
568
        if (askForClassName) {
569
            tfClassName = new ClassNameTextField();
570
            tfClassName.setChangeListener(this);
571
        }
572
        cboxLocation = new JComboBox();
573
        cboxFramework = new JComboBox();
574
        testingFrameworks = new ArrayList<String>();
575
        cboxFramework.setModel(new DefaultComboBoxModel(testingFrameworks.toArray()));
576
        cboxFramework.addItemListener(new java.awt.event.ItemListener() {
577
            @Override
578
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
579
                fireFrameworkChanged();
580
            }
581
        });
582
        
583
        if (askForClassName) {
584
            lblClassName.setLabelFor(tfClassName);
585
        }
586
        lblLocation.setLabelFor(cboxLocation);
587
        lblFramework.setLabelFor(cboxFramework);
588
        
589
        if (lblClassToTestValue != null) {
590
            Font labelFont = javax.swing.UIManager.getDefaults()
591
                             .getFont("TextField.font");                //NOI18N
592
            if (labelFont != null) {
593
                lblClassToTestValue.setFont(labelFont);
594
            }
595
        }
596
        
597
        panel.setLayout(new GridBagLayout());
598
        
599
        GridBagConstraints gbcLeft = new GridBagConstraints();
600
        gbcLeft.anchor = GridBagConstraints.WEST;
601
        gbcLeft.insets.bottom = 12;
602
        gbcLeft.insets.right = 6;
603
        
604
        GridBagConstraints gbcRight = new GridBagConstraints();
605
        gbcRight.anchor = GridBagConstraints.WEST;
606
        gbcRight.insets.bottom = 12;
607
        gbcRight.weightx = 1.0f;
608
        gbcRight.fill = GridBagConstraints.BOTH;
609
        gbcRight.gridwidth = GridBagConstraints.REMAINDER;
610
        
611
        if (lblClassToTestValue != null) {
612
            panel.add(lblClassToTest,      gbcLeft);
613
            panel.add(lblClassToTestValue, gbcRight);
614
        } else {
615
            panel.add(lblClassToTest,   gbcRight);
616
        }
617
        if (askForClassName) {
618
            panel.add(lblClassName,     gbcLeft);
619
            panel.add(tfClassName,      gbcRight);
620
        }
621
        panel.add(lblLocation,      gbcLeft);
622
        panel.add(cboxLocation,     gbcRight);
623
        gbcLeft.insets.bottom = 0;
624
        gbcRight.insets.bottom = 0;
625
        panel.add(lblFramework,      gbcLeft);
626
        panel.add(cboxFramework,     gbcRight);
627
        
628
        return panel;
629
    }
630
    
631
    /**
632
     */
633
    private void checkClassNameValidity() {
634
        if (tfClassName == null) {
635
            classNameValid = true;
636
            return;
637
        }
638
        
639
        String key = null;
640
        final int state = tfClassName.getStatus();
641
        switch (state) {
642
            case ClassNameTextField.STATUS_EMPTY:
643
                key = "MSG_ClassnameMustNotBeEmpty";                    //NOI18N
644
                break;
645
            case ClassNameTextField.STATUS_INVALID:
646
                key = "MSG_InvalidClassName";                           //NOI18N
647
                break;
648
            case ClassNameTextField.STATUS_VALID_NOT_DEFAULT:
649
                key = "MSG_ClassNameNotDefault";                        //NOI18N
650
                break;
651
            case ClassNameTextField.STATUS_VALID_END_NOT_TEST:
652
                key = "MSG_ClassNameEndNotTest";                        //NOI18N
653
                break;
654
        }
655
        if (state != ClassNameTextField.STATUS_VALID_NOT_DEFAULT) {
656
            setMessage(null, MSG_TYPE_CLASSNAME_NOT_DEFAULT);
657
        }
658
        setMessage((key != null)
659
                           ? NbBundle.getMessage(GuiUtils.class, key)
660
                           : null,
661
                   MSG_TYPE_CLASSNAME_INVALID);
662
        
663
        classNameValid =
664
                (state == ClassNameTextField.STATUS_VALID)
665
                || (state == ClassNameTextField.STATUS_VALID_NOT_DEFAULT);
666
    }
667
    
668
    /**
669
     * This method gets called if status of contents of the Class Name
670
     * text field changes. See <code>STATUS_xxx</code> constants
671
     * in class <code>ClassNameTextField</code>.
672
     *
673
     * @param  e  event describing the state change event
674
     *            (unused in this method)
675
     */
676
    @Override
677
    public void stateChanged(ChangeEvent e) {
678
        checkClassNameValidity();
679
        checkAcceptability();
680
    }
681
    
682
    /**
683
     */
684
    private void checkAcceptability() {
685
        final boolean wasAcceptable = isAcceptable;
686
        isAcceptable = hasTargetFolders && classNameValid;
687
        if (isAcceptable != wasAcceptable) {
688
            fireStateChange();
689
        }
690
    }
691
    
692
    /**
693
     * Are the values filled in the form acceptable?
694
     *
695
     * @see  #addChangeListener
696
     */
697
    private boolean isAcceptable() {
698
        return isAcceptable;
699
    }
700
    
701
    /**
702
     * This method is called the first time this panel's children are painted.
703
     * By default, this method just calls {@link #adjustWindowSize()}.
704
     *
705
     * @param  g  <code>Graphics</code> used to paint this panel's children
706
     */
707
    @Override
708
    protected void paintedFirstTime(java.awt.Graphics g) {
709
        if (initialMessage != null) {
710
            displayMessage(initialMessage);
711
            initialMessage = null;
712
        }
713
    }
714
    
715
    /**
716
     * Displays a given message in the message panel and resizes the dialog
717
     * if necessary. If the message cannot be displayed immediately,
718
     * because of this panel not displayed (painted) yet, displaying the message
719
     * is deferred until this panel is painted.
720
     *
721
     * @param  message  message to be displayed, or <code>null</code> if
722
     *                  the currently displayed message (if any) should be
723
     *                  removed
724
     */
725
    private void setMessage(final String message, final int msgType) {
726
        String msgToDisplay = msgStack.setMessage(msgType, message);
727
        if (msgToDisplay == null) {
728
            return;                     //no change
729
        }
730
731
        /* display the message: */
732
        if (!isPainted()) {
733
            initialMessage = msgToDisplay;
734
        } else {
735
            displayMessage(msgToDisplay);
736
        }
737
    }
738
    
739
    /**
740
     * Displays a given message in the message panel and resizes the dialog
741
     * if necessary.
742
     *
743
     * @param  message  message to be displayed, or <code>null</code> if
744
     *                  the currently displayed message (if any) should be
745
     *                  removed
746
     * @see  #adjustWindowSize()
747
     */
748
    private void displayMessage(String message) {
749
        if (message == null) {
750
            message = "";                                               //NOI18N
751
        }
752
        
753
        txtAreaMessage.setText(message);
754
        adjustWindowSize();
755
    }
756
    
757
    /**
758
     */
759
    private Component createMessagePanel() {
760
        Color color = UIManager.getColor("nb.errorForeground");         //NOI18N
761
        if (color == null) {
762
            color = new Color(89, 79, 191);   //RGB suggested by Bruce in #28466
763
        }
764
        txtAreaMessage = GuiUtils.createMultilineLabel("", color);      //NOI18N
765
        return txtAreaMessage;
766
    }
767
    
768
    /**
769
     * Creates a panel containing controls for settings code generation options.
770
     *
771
     * @return   created panel
772
     */
773
    private Component createCodeGenPanel() {
774
        
775
        /* create the components: */
776
        String[] chkBoxIDs;
777
        JCheckBox[] chkBoxes;
778
        if (multipleClasses) {
779
            chkBoxIDs = new String[] {
780
                GuiUtils.CHK_PUBLIC,
781
                GuiUtils.CHK_PROTECTED,
782
                GuiUtils.CHK_PACKAGE,
783
                GuiUtils.CHK_PACKAGE_PRIVATE_CLASSES,
784
                GuiUtils.CHK_ABSTRACT_CLASSES,
785
                GuiUtils.CHK_EXCEPTION_CLASSES,
786
                GuiUtils.CHK_SUITES,
787
                GuiUtils.CHK_SETUP,
788
                GuiUtils.CHK_TEARDOWN,
789
                GuiUtils.CHK_METHOD_BODIES,
790
                GuiUtils.CHK_JAVADOC,
791
                GuiUtils.CHK_HINTS
792
            };
793
        } else {
794
            chkBoxIDs = new String[] {
795
                GuiUtils.CHK_PUBLIC,
796
                GuiUtils.CHK_PROTECTED,
797
                GuiUtils.CHK_PACKAGE,
798
                null, // CHK_PACKAGE_PRIVATE_CLASSES,
799
                null, // CHK_ABSTRACT_CLASSES,
800
                null, // CHK_EXCEPTION_CLASSES,
801
                null, // CHK_SUITES,
802
                GuiUtils.CHK_SETUP,
803
                GuiUtils.CHK_TEARDOWN,
804
                GuiUtils.CHK_METHOD_BODIES,
805
                GuiUtils.CHK_JAVADOC,
806
                GuiUtils.CHK_HINTS
807
            };
808
        }
809
        chkBoxes = GuiUtils.createCheckBoxes(chkBoxIDs);
810
        int i = 0;
811
        chkPublic           = chkBoxes[i++];
812
        chkProtected        = chkBoxes[i++];
813
        chkPackage          = chkBoxes[i++];
814
        chkPackagePrivateClasses = chkBoxes[i++];       //may be null
815
        chkAbstractImpl     = chkBoxes[i++];            //may be null
816
        chkExceptions       = chkBoxes[i++];            //may be null
817
        chkGenerateSuites   = chkBoxes[i++];            //may be null
818
        chkSetUp            = chkBoxes[i++];
819
        chkTearDown         = chkBoxes[i++];        
820
        chkContent          = chkBoxes[i++];
821
        chkJavaDoc          = chkBoxes[i++];
822
        chkComments         = chkBoxes[i++];
823
        
824
        /* create groups of checkboxes: */
825
        JComponent methodAccessLevels = GuiUtils.createChkBoxGroup(
826
                bundle.getString("CommonTestsCfgOfCreate.groupAccessLevels"), //NOI18N
827
                new JCheckBox[] {chkPublic, chkProtected, chkPackage});
828
        JComponent classTypes = null;
829
        JComponent optionalClasses = null;
830
        if (multipleClasses) {
831
            classTypes = GuiUtils.createChkBoxGroup(
832
                bundle.getString("CommonTestsCfgOfCreate.groupClassTypes"),   //NOI18N
833
                new JCheckBox[] {chkPackagePrivateClasses,
834
                                 chkAbstractImpl, chkExceptions});
835
            optionalClasses = GuiUtils.createChkBoxGroup(
836
                bundle.getString("CommonTestsCfgOfCreate.groupOptClasses"),   //NOI18N
837
                new JCheckBox[] {chkGenerateSuites});
838
        }
839
        JComponent optionalCode = GuiUtils.createChkBoxGroup(
840
                bundle.getString("CommonTestsCfgOfCreate.groupOptCode"),      //NOI18N
841
                new JCheckBox[] {chkSetUp, chkTearDown, chkContent});
842
        JComponent optionalComments = GuiUtils.createChkBoxGroup(
843
                bundle.getString("CommonTestsCfgOfCreate.groupOptComments"),  //NOI18N
844
                new JCheckBox[] {chkJavaDoc, chkComments});
845
        
846
        /* create the left column of options: */
847
        Box leftColumn = Box.createVerticalBox();
848
        leftColumn.add(methodAccessLevels);
849
        if (multipleClasses) {
850
            leftColumn.add(Box.createVerticalStrut(11));
851
            leftColumn.add(classTypes);
852
        } else {
853
            /*
854
             * This strut ensures that width of the left column is not limited.
855
             * If it was limited, the rigth column would not move when the
856
             * dialog is horizontally resized.
857
             */
858
            leftColumn.add(Box.createVerticalStrut(0));
859
        }
860
        leftColumn.add(Box.createVerticalGlue());
861
        
862
        /* create the right column of options: */
863
        Box rightColumn = Box.createVerticalBox();
864
        if (multipleClasses) {
865
            rightColumn.add(optionalClasses);
866
            rightColumn.add(Box.createVerticalStrut(11));
867
        }
868
        rightColumn.add(optionalCode);
869
        rightColumn.add(Box.createVerticalStrut(11));
870
        rightColumn.add(optionalComments);
871
        rightColumn.add(Box.createVerticalGlue());
872
        
873
        /* compose the final panel: */
874
        //JPanel jpCodeGen = new SizeRestrictedPanel(false, true);
875
        JPanel jpCodeGen = new JPanel();
876
        jpCodeGen.setLayout(new BoxLayout(jpCodeGen, BoxLayout.X_AXIS));
877
        jpCodeGen.add(leftColumn);
878
        jpCodeGen.add(Box.createHorizontalStrut(24));
879
        jpCodeGen.add(rightColumn);
880
        
881
        /* decorate the panel: */
882
        addTitledBorder(jpCodeGen,
883
                  new Insets(12, 12, 11, 12),
884
                  bundle.getString("CommonTestsCfgOfCreate.jpCodeGen.title"));//NOI18N
885
        
886
        /* tune the layout: */
887
        methodAccessLevels.setAlignmentX(0.0f);
888
        if (multipleClasses) {
889
            classTypes.setAlignmentX(0.0f);
890
            optionalClasses.setAlignmentX(0.0f);
891
        }
892
        optionalCode.setAlignmentX(0.0f);
893
        optionalComments.setAlignmentX(0.0f);
894
        
895
        return jpCodeGen;
896
    }
897
    
898
    /**
899
     * Adds a border and a title around a given component.
900
     * If the component already has some border, it is overridden (not kept).
901
     *
902
     * @param  component  component the border and title should be added to
903
     * @param  insets  insets between the component and the titled border
904
     * @param  title  text of the title
905
     */
906
    private static void addTitledBorder(JComponent component,
907
                                        Insets insets,
908
                                        String title) {
909
        Border insideBorder = BorderFactory.createEmptyBorder(
910
                insets.top, insets.left, insets.bottom, insets.right);
911
        Border outsideBorder = new TitledBorder(
912
                BorderFactory.createEtchedBorder(), title);
913
        component.setBorder(new CompoundBorder(outsideBorder, insideBorder));
914
    }
915
    
916
    /**
917
     */
918
    public FileObject getTargetFolder() {
919
        Object selectedLocation = cboxLocation.getSelectedItem();
920
        
921
        if (selectedLocation == null) {
922
            return null;
923
        }
924
        
925
        if (selectedLocation instanceof SourceGroup) {
926
            return ((SourceGroup) selectedLocation).getRootFolder();
927
        }
928
        assert selectedLocation instanceof FileObject;      //root folder
929
        return (FileObject) selectedLocation;
930
    }
931
    
932
    /**
933
     * Initializes form in the Test Settings panel of the dialog.
934
     */
935
    private void fillFormData() {
936
        final DataObject dataObj = nodes[0].getLookup().lookup(DataObject.class);
937
        final FileObject fileObj = dataObj.getPrimaryFile();
938
        
939
        if (singleClass) {
940
            assert nodes.length == 1;
941
            
942
            ClassPath cp = ClassPath.getClassPath(fileObj, ClassPath.SOURCE);
943
            String className = cp.getResourceName(fileObj, '.', false);
944
            lblClassToTestValue.setText(className);
945
            
946
            if (tfClassName != null) {
947
                String prefilledName = getTestingFrameworkFolder() + className + TEST_CLASS_SUFFIX;
948
                tfClassName.setText(prefilledName);
949
                tfClassName.setDefaultText(prefilledName);
950
                tfClassName.setCaretPosition(prefilledName.length());
951
            }
952
        } else if (singlePackage) {
953
            assert nodes.length == 1;
954
            
955
            ClassPath cp = ClassPath.getClassPath(fileObj, ClassPath.SOURCE);
956
            String packageName = cp.getResourceName(fileObj, '.', true);
957
            if (packageName.length() == 0) {
958
                packageName = NbBundle.getMessage(
959
                        GuiUtils.class,
960
                        "DefaultPackageName");                          //NOI18N
961
            }
962
            lblClassToTestValue.setText(packageName);
963
        } else {
964
            //PENDING
965
        }
966
        
967
        setupLocationChooser(fileObj);
968
        
969
        checkClassNameValidity();
970
    }
971
    
972
    /**
973
     */
974
    private void setupLocationChooser(FileObject refFileObject) {
975
        Object[] targetFolders = CommonTestUtil.getTestTargets(refFileObject);
976
        if (targetFolders.length == 0) {
977
            Project owner = FileOwnerQuery.getOwner(refFileObject);
978
            if (owner != null) {
979
                if (SourceGroupModifier.createSourceGroup(owner, JavaProjectConstants.SOURCES_TYPE_JAVA, JavaProjectConstants.SOURCES_HINT_TEST) != null) {
980
                    targetFolders = CommonTestUtil.getTestTargets(refFileObject);
981
                }
982
            }
983
        }
984
985
        if (targetFolders.length != 0) {
986
            hasTargetFolders = true;
987
            cboxLocation.setModel(new DefaultComboBoxModel(targetFolders));
988
            cboxLocation.setRenderer(new LocationChooserRenderer());
989
        } else {
990
            hasTargetFolders = false;
991
            //PENDING - message text:
992
            String msgNoTargetsFound = NbBundle.getMessage(
993
                                        getClass(),
994
                                        refFileObject.isFolder()
995
                                                ? "MSG_NoTestTarget_Fo" //NOI18N
996
                                                : "MSG_NoTestTarget_Fi",//NOI18N
997
                                        refFileObject.getNameExt());
998
            setMessage(msgNoTargetsFound, MSG_TYPE_NO_TARGET_FOLDERS);
999
            disableComponents();
1000
        }
1001
    }
1002
    
1003
    /**
1004
     * Renderer which specially handles values of type
1005
     * <code>SourceGroup</code> and <code>FileObject</code>.
1006
     * It displays display names of these objects, instead of their default
1007
     * string representation (<code>toString()</code>).
1008
     *
1009
     * @see  SourceGroup#getDisplayName()
1010
     * @see  FileUtil#getFileDisplayName(FileObject)
1011
     */
1012
    private final class LocationChooserRenderer extends JLabel implements ListCellRenderer, UIResource {
1013
        
1014
        public LocationChooserRenderer () {
1015
            setOpaque(true);
1016
        }
1017
        
1018
        @Override
1019
        public Component getListCellRendererComponent(
1020
                JList list,
1021
                Object value,
1022
                int index,
1023
                boolean isSelected,
1024
                boolean cellHasFocus) {
1025
            // #93658: GTK needs name to render cell renderer "natively"
1026
            setName("ComboBox.listRenderer"); // NOI18N
1027
            
1028
            String text = value instanceof SourceGroup
1029
                        ? ((SourceGroup) value).getDisplayName()
1030
                        : value instanceof FileObject
1031
                              ?  FileUtil.getFileDisplayName((FileObject) value)
1032
                              : value.toString();
1033
            setText(text);
1034
            
1035
            if ( isSelected ) {
1036
                setBackground(list.getSelectionBackground());
1037
                setForeground(list.getSelectionForeground());             
1038
            }
1039
            else {
1040
                setBackground(list.getBackground());
1041
                setForeground(list.getForeground());
1042
            }
1043
            
1044
            return this;
1045
        }
1046
        
1047
        // #93658: GTK needs name to render cell renderer "natively"
1048
        @Override
1049
        public String getName() {
1050
            String name = super.getName();
1051
            return name == null ? "ComboBox.renderer" : name;  // NOI18N
1052
        }
1053
            
1054
    }
1055
1056
    /**
1057
     * Registers a change listener.
1058
     * Registered change listeners are notified when acceptability
1059
     * of values in the form changes.
1060
     *
1061
     * @param  l  listener to be registered
1062
     * @see  #isAcceptable
1063
     * @see  #removeChangeListener
1064
     */
1065
    private void addChangeListener(ChangeListener l) {
1066
        if (changeListeners == null) {
1067
            changeListeners = new ArrayList<ChangeListener>(3);
1068
        }
1069
        changeListeners.add(l);
1070
    }
1071
    
1072
    /**
1073
     * Unregisters the given change listener.
1074
     * If the given listener has not been registered before, calling this
1075
     * method does not have any effect.
1076
     *
1077
     * @param  l  change listener to be removed
1078
     * @see  #addChangeListener
1079
     */
1080
    private void removeChangeListener(ChangeListener l) {
1081
        if (changeListeners != null
1082
                && changeListeners.remove(l)
1083
                && changeListeners.isEmpty()) {
1084
            changeListeners = null;
1085
        }
1086
    }
1087
    
1088
    /**
1089
     * Notifies all registered change listeners about a change.
1090
     *
1091
     * @see  #addChangeListener
1092
     */
1093
    private void fireStateChange() {
1094
        if (changeListeners != null) {
1095
            ChangeEvent e = new ChangeEvent(this);
1096
            for (Iterator i = changeListeners.iterator(); i.hasNext(); ) {
1097
                ((ChangeListener) i.next()).stateChanged(e);
1098
            }
1099
        }
1100
    }
1101
    
1102
    /**
1103
     * Disables all interactive visual components of this dialog
1104
     * except the OK, Cancel and Help buttons.
1105
     */
1106
    private void disableComponents() {
1107
        final Stack<Container> stack = new Stack<Container>();
1108
        stack.push(this);
1109
        
1110
        while (!stack.empty()) {
1111
            Container container = stack.pop();
1112
            Component comps[] = container.getComponents();
1113
            for (int i = 0; i < comps.length; i++) {
1114
                final java.awt.Component comp = comps[i];
1115
                
1116
                if (comp == txtAreaMessage) {
1117
                    continue;
1118
                }
1119
                if (comp instanceof JPanel) {
1120
                    JPanel panel = (JPanel) comp;
1121
                    stack.push(panel);
1122
1123
                    final Border border = panel.getBorder();
1124
                    if (border != null) {
1125
                        disableBorderTitles(border);
1126
                    }
1127
                    continue;
1128
                }
1129
                comp.setEnabled(false);
1130
                if (comp instanceof java.awt.Container) {
1131
                    Container nestedCont = (Container) comp;
1132
                    if (nestedCont.getComponentCount() != 0) {
1133
                        stack.push(nestedCont);
1134
                    }
1135
                }
1136
            }
1137
        }
1138
    }
1139
    
1140
    /**
1141
     */
1142
    private static void disableBorderTitles(Border border) {
1143
        
1144
        if (border instanceof TitledBorder) {
1145
            disableBorderTitle((TitledBorder) border);
1146
            return;
1147
        }
1148
        
1149
        if (!(border instanceof CompoundBorder)) {
1150
            return;
1151
        }
1152
        
1153
        Stack<CompoundBorder> stack = new Stack<CompoundBorder>();
1154
        stack.push((CompoundBorder) border);
1155
        while (!stack.empty()) {
1156
            CompoundBorder cb = stack.pop();
1157
            
1158
            Border b;
1159
            b = cb.getOutsideBorder();
1160
            if (b instanceof CompoundBorder) {
1161
                stack.push((CompoundBorder) b);
1162
            } else if (b instanceof TitledBorder) {
1163
                disableBorderTitle((TitledBorder) b);
1164
            }
1165
            
1166
            b = cb.getInsideBorder();
1167
            if (b instanceof CompoundBorder) {
1168
                stack.push((CompoundBorder) b);
1169
            } else if (b instanceof TitledBorder) {
1170
                disableBorderTitle((TitledBorder) b);
1171
            }
1172
        }
1173
    }
1174
    
1175
    /**
1176
     */
1177
    private static void disableBorderTitle(TitledBorder border) {
1178
        final Color color = UIManager.getColor(
1179
                "Label.disabledForeground");                        //NOI18N
1180
        if (color != null) {
1181
            border.setTitleColor(color);
1182
        }
1183
    }
1184
1185
    private JLabel lblClassToTestValue;
1186
    private ClassNameTextField tfClassName;
1187
    private JTextComponent txtAreaMessage;
1188
    private JComboBox cboxLocation;
1189
    private JComboBox cboxFramework;
1190
    private JCheckBox chkAbstractImpl;
1191
    private JCheckBox chkComments;
1192
    private JCheckBox chkContent;
1193
    private JCheckBox chkExceptions;
1194
    private JCheckBox chkGenerateSuites;
1195
    private JCheckBox chkJavaDoc;
1196
    private JCheckBox chkPackage;
1197
    private JCheckBox chkPackagePrivateClasses;
1198
    private JCheckBox chkProtected;
1199
    private JCheckBox chkPublic;
1200
    private JCheckBox chkSetUp;
1201
    private JCheckBox chkTearDown;
1202
1203
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/EmptyTestCaseWizard.java (+83 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 2004-2007 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.gsf.testrunner;
46
47
//import org.netbeans.modules.junit.GuiUtils;
48
//import org.netbeans.modules.junit.CommonSettings;
49
import org.netbeans.modules.gsf.testrunner.api.GuiUtils;
50
import org.netbeans.modules.gsf.testrunner.api.CommonSettings;
51
import org.openide.loaders.TemplateWizard;
52
53
/**
54
 * Wizard for an empty test case.
55
 *
56
 * @author  Marian Petras
57
 */
58
public class EmptyTestCaseWizard extends TemplateWizard {
59
60
    /** name of property &quot;package&quot; */
61
    static final String PROP_PACKAGE = "package";                       //NOI18N
62
    /** name of property &quot;class name&quot; */
63
    static final String PROP_CLASS_NAME = "className";                  //NOI18N
64
    
65
    // PENDING - should not be hard-coded:
66
    static final String TESTS_ROOT_NAME = "test";               //NOI18N
67
    
68
    /**
69
     * initializes the settings for the settings panel
70
     */
71
    @Override
72
    public void initialize() {
73
        CommonSettings settings = CommonSettings.getDefault();
74
        
75
        putProperty(GuiUtils.CHK_SETUP,
76
                    Boolean.valueOf(settings.isGenerateSetUp()));
77
        putProperty(GuiUtils.CHK_TEARDOWN,
78
                    Boolean.valueOf(settings.isGenerateTearDown()));
79
        putProperty(GuiUtils.CHK_HINTS,
80
                    Boolean.valueOf(settings.isBodyComments()));
81
    }
82
    
83
}
(-)a/junit/src/org/netbeans/modules/junit/MessageStack.java (-1 / +1 lines)
Lines 42-48 Link Here
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
44
45
package org.netbeans.modules.junit;
45
package org.netbeans.modules.gsf.testrunner;
46
46
47
/**
47
/**
48
 * Manager of layered messages.
48
 * Manager of layered messages.
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/Utils.java (+782 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 2004-2007 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.gsf.testrunner;
46
47
import org.netbeans.modules.gsf.testrunner.EmptyTestCaseWizard;
48
import org.netbeans.modules.gsf.testrunner.api.CommonTestUtil;
49
import java.io.IOException;
50
import java.net.URL;
51
import java.util.ArrayList;
52
import java.util.Arrays;
53
import java.util.Collection;
54
import java.util.Collections;
55
import java.util.HashMap;
56
import java.util.List;
57
import java.util.Map;
58
import org.netbeans.api.java.project.JavaProjectConstants;
59
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
60
import org.netbeans.api.project.FileOwnerQuery;
61
import org.netbeans.api.project.Project;
62
import org.netbeans.api.project.ProjectUtils;
63
import org.netbeans.api.project.SourceGroup;
64
//import org.netbeans.modules.junit.CommonTestUtil;
65
import org.openide.ErrorManager;
66
import org.openide.cookies.EditorCookie;
67
import org.openide.filesystems.FileObject;
68
import org.openide.filesystems.FileUtil;
69
import org.openide.filesystems.URLMapper;
70
import org.openide.loaders.DataObject;
71
import org.openide.loaders.DataObjectNotFoundException;
72
import org.openide.text.Line;
73
import org.openide.text.Line.ShowOpenType;
74
import org.openide.text.Line.ShowVisibilityType;
75
import org.openide.util.Utilities;
76
77
/**
78
 *
79
 * @author  Marian Petras
80
 */
81
public final class Utils {
82
83
    /** */
84
    private final Project project;
85
    /** <!-- PENDING --> */
86
    private boolean sourceGroupsOnly = true;
87
    /** <!-- PENDING --> */
88
    private SourceGroup[] javaSourceGroups;
89
    /** <!-- PENDING --> */
90
    private Map<SourceGroup,Object[]> sourcesToTestsMap;
91
    /** <!-- PENDING --> */
92
    private Map<FileObject,Object> foldersToSourceGroupsMap;
93
    
94
    /**
95
     * <!-- PENDING -->
96
     */
97
    public Utils(Project project) {
98
        this.project = project;
99
    }
100
    
101
    /** <!-- PENDING --> */
102
    static FileObject findTestsRoot(Project project) {
103
        final SourceGroup[] sourceGroups
104
                = new Utils(project).getJavaSourceGroups();
105
        for (int i = 0; i < sourceGroups.length; i++) {
106
            FileObject root = sourceGroups[i].getRootFolder();
107
            if (root.getName().equals(EmptyTestCaseWizard.TESTS_ROOT_NAME)) {
108
                return root;
109
            }
110
        }
111
        return null;
112
    }
113
    
114
    /** */
115
    static FileObject getPackageFolder(
116
            FileObject root,
117
            String pkgName) throws IOException {
118
        String relativePathName = pkgName.replace('.', '/');
119
        FileObject folder = root.getFileObject(relativePathName);
120
        if (folder == null) {
121
            folder = FileUtil.createFolder(root, relativePathName);
122
        }
123
        return folder;
124
    }
125
    
126
    /**
127
     * Identifies and collects <code>SourceGroup</code>s and folders
128
     * of a given project which may serve as target folders for newly created
129
     * test classes.
130
     *
131
     * @param  project  project whose folders are to be checked
132
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
133
     *                           - ignore target folders not having
134
     *                           a corresponding <code>SourceGroup</code>
135
     * @return  collection which may contain <code>FileObject</code>s
136
     *          or <code>SourceGroup</code>s (or both);
137
     *          it may be empty but not <code>null</code>
138
     * @author  Marian Petras
139
     */
140
    static Collection getTestTargets(Project project,
141
                                     final boolean sourceGroupsOnly) {
142
        final Utils utils = new Utils(project);
143
        return utils.getTestTargets(sourceGroupsOnly);
144
    }
145
146
    /**
147
     * Identifies and collects root test folders of a given project.
148
     * 
149
     * @param  project  project whose test folders are to be found
150
     * @return  collection of found {@code FileObject}s, possibly empty
151
     *          (but not {@code null})
152
     */
153
    public static Collection<FileObject> getTestFolders(Project project) {
154
        return new Utils(project).getTestFolders();
155
    }
156
    
157
    /**
158
     * Builds a map that containing relation between <code>SourceGroup</code>s
159
     * and their respective test <code>SourceGroup</code>s.
160
     * Each entry of the map contains a <code>SourceGroup</code> as a key
161
     * and an array of test <code>SourceGroup</code>s returned by
162
     * <code>UnitTestForSourceQuery</code> for that <code>SourceGroup</code>
163
     * as a value. <code>SourceGroup</code>s that have no test
164
     * <code>SourceGroup</code>s assigned are omitted, i.e. the resulting
165
     * map does not contain entries that would have empty arrays as their
166
     * values.
167
     *
168
     * @param  project  project whose <code>SourceGroup</code>s are to be
169
     *                  checked
170
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
171
     *                           - ignore test folders not having
172
     *                           a corresponding <code>SourceGroup</code>
173
     * @return  created map - may be empty, may be unmodifiable
174
     *                        never <code>null</code>
175
     */
176
    static Map getSourcesToTestsMap(Project project,
177
                                    final boolean sourceGroupsOnly) {
178
        final Utils utils = new Utils(project);
179
        return utils.getSourcesToTestsMap(sourceGroupsOnly);
180
    }
181
    
182
    /**
183
     * <!-- PENDING -->
184
     */
185
    Project getProject() {
186
        return project;
187
    }
188
189
    /**
190
     * Identifies and collects root test folders of the project.
191
     * 
192
     * @return  collection of found {@code FileObject}s
193
     *          - may be empty but never {@code null}
194
     */
195
    private Collection<FileObject> getTestFolders() {
196
        
197
        /*
198
         * Idea:
199
         * 1) Get all SourceGroups
200
         * 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
201
         *    test SourceGroups
202
         */
203
204
        /* .) get all SourceGroups: */
205
        final SourceGroup[] sourceGroups = getJavaSourceGroups();
206
        if (sourceGroups.length == 0) {
207
            return Collections.<FileObject>emptyList();
208
        }
209
210
        List<FileObject> result = null;
211
212
        /* .) for each SourceGroup, ask for test root folders: */
213
        for (SourceGroup sourceGroup : sourceGroups) {
214
            FileObject srcFolder = sourceGroup.getRootFolder();
215
            FileObject[] tstFoldersRaw = getTestFoldersRaw(srcFolder);
216
            if (tstFoldersRaw.length == 0) {
217
                continue;
218
            }
219
220
            for (FileObject tstFolder : tstFoldersRaw) {
221
                if (tstFolder == null) {
222
                    continue;
223
                }
224
225
                if (result == null) {
226
                    result = new ArrayList<FileObject>(2);
227
                }
228
                if (!result.contains(tstFolder)) {
229
                    result.add(tstFolder);
230
                }
231
            }
232
        }
233
234
        /* .) pack the results: */
235
        if (result == null) {
236
            return Collections.<FileObject>emptyList();
237
        } else {
238
            assert !result.isEmpty();
239
            return (result.size() == 1)
240
                   ? Collections.<FileObject>singleton(result.get(0))
241
                   : result;
242
        }
243
    }
244
245
    /**
246
     * Identifies and collects <code>SourceGroup</code>s and folders
247
     * which may serve as target folders for newly created test classes.
248
     *
249
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
250
     *                           (skip target folders without matching
251
     *                           <code>SourceGroup</code>)
252
     * @return  collection which may contain <code>FileObject</code>s
253
     *          or <code>SourceGroup</code>s (or both);
254
     *          it may be empty but not <code>null</code>
255
     * @see  #getTestTargets(Project, boolean)
256
     * @author  Marian Petras
257
     */
258
    private Collection<Object> getTestTargets(final boolean sourceGroupsOnly) {
259
260
        /*
261
         * Idea:
262
         * 1) Get all SourceGroups
263
         * 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
264
         *    test SourceGroups
265
         *
266
         * Union of all SourceGroups returned by UnitTestForSourceQuery
267
         * are the test SourceGroups.
268
         */
269
270
        /* .) get all SourceGroups: */
271
        final SourceGroup[] sourceGroups = getJavaSourceGroups();
272
        if (sourceGroups.length == 0) {
273
            return Collections.<Object>emptyList();
274
        }
275
276
        /* .) */
277
        createFoldersToSourceGroupsMap(sourceGroups);
278
        Object testTargetsUnion[] = new Object[sourceGroups.length];
279
        int size = 0;
280
        for (int i = 0; i < sourceGroups.length; i++) {
281
            Object[] testTargets = getTestTargets(sourceGroups[i],
282
                                                  sourceGroupsOnly);
283
            size = merge(testTargets, testTargetsUnion, size);
284
        }
285
286
        if (size != testTargetsUnion.length) {
287
            testTargetsUnion = CommonTestUtil.skipNulls(testTargetsUnion, new Object[0]);
288
        }
289
290
        return Collections.unmodifiableCollection(
291
                      Arrays.asList(testTargetsUnion));
292
    }
293
    
294
    /**
295
     * <!-- PENDING -->
296
     */
297
    Map<SourceGroup,Object[]> getSourcesToTestsMap() {
298
        if (sourcesToTestsMap == null) {
299
            sourcesToTestsMap = createSourcesToTestsMap(sourceGroupsOnly);
300
        }
301
        return sourcesToTestsMap;
302
    }
303
    
304
    /**
305
     * <!-- PENDING -->
306
     */
307
    Map<SourceGroup,Object[]> getSourcesToTestsMap(final boolean sourceGroupsOnly) {
308
        if (sourceGroupsOnly != this.sourceGroupsOnly) {
309
            sourcesToTestsMap = null;
310
            this.sourceGroupsOnly = sourceGroupsOnly;
311
        }
312
        return getSourcesToTestsMap();
313
    }
314
315
    /**
316
     * Builds a map that containing relation between <code>SourceGroup</code>s
317
     * and their respective test <code>SourceGroup</code>s.
318
     * Each entry of the map contains a <code>SourceGroup</code> as a key
319
     * and an array of test <code>SourceGroup</code>s returned by
320
     * <code>UnitTestForSourceQuery</code> for that <code>SourceGroup</code>
321
     * as a value. <code>SourceGroup</code>s that have no test
322
     * <code>SourceGroup</code>s assigned are omitted, i.e. the resulting
323
     * map does not contain entries that would have empty arrays as their
324
     * values.
325
     *
326
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
327
     *                           - ignore test folders not having
328
     *                           a corresponding <code>SourceGroup</code>
329
     * @return  created map - may be empty, may be unmodifiable,
330
     *                        cannot be <code>null</code>
331
     */
332
    private Map<SourceGroup,Object[]> createSourcesToTestsMap(final boolean sourceGroupsOnly) {
333
        
334
        /*
335
         * Idea:
336
         * 1) Get all SourceGroups
337
         * 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
338
         *    test SourceGroups
339
         */
340
341
        /* .) get all SourceGroups: */
342
        final SourceGroup[] sourceGroups = getJavaSourceGroups();
343
        if (sourceGroups.length == 0) {
344
            return Collections.<SourceGroup,Object[]>emptyMap();
345
        }
346
347
        /* .) get test SourceGroups for each SourceGroup: */
348
        createFoldersToSourceGroupsMap(sourceGroups);
349
        Object testTargetsUnion[] = new Object[sourceGroups.length];
350
        Map<SourceGroup,Object[]> map;
351
        map = new HashMap<SourceGroup,Object[]>(
352
                            (int) ((float) sourceGroups.length * 1.33f + 0.5f),
353
                            .75f);
354
        for (int i = 0; i < sourceGroups.length; i++) {
355
            Object[] testTargets = getTestTargets(sourceGroups[i],
356
                                                  sourceGroupsOnly);
357
            if (testTargets.length != 0) {
358
                map.put(sourceGroups[i], testTargets);
359
            }
360
        }
361
        if (map.isEmpty()) {
362
            return Collections.<SourceGroup,Object[]>emptyMap();
363
        }
364
        if (map.size() == 1) {
365
            Map.Entry<SourceGroup,Object[]> entry
366
                    = map.entrySet().iterator().next();
367
            return Collections.singletonMap(entry.getKey(), entry.getValue());
368
        }
369
370
        final int finalMapSize = map.size();
371
        if (finalMapSize >= (sourceGroups.length - 5)) {
372
            return map;
373
        }
374
        
375
        final Map<SourceGroup,Object[]> targetMap;
376
        targetMap = new HashMap<SourceGroup,Object[]>(
377
                                    (int) ((float) finalMapSize * 1.25f + .5f),
378
                                    .8f);
379
        targetMap.putAll(map);
380
        return targetMap;
381
    }
382
383
    /**
384
     * Merges a given set of <code>FileObject</code>s and
385
     * <code>SourceGroup</code>s to the given target set (which may contain
386
     * same types of elements).
387
     * The source set (array) is not modified during merge. The target
388
     * set (array) is not modified otherwise than by adding (overwriting
389
     * <code>null</code>s) elements from the source set or by replacing elements
390
     * with equivalent elements (i.e. pointing to the same folder). Elements are
391
     * always added after the last non-<code>null</code> element of the target
392
     * set. After the merge, it is guaranteed that all <code>null</code>
393
     * elements of the target array are located at the end. The above
394
     * constraints can only be fulfilled if parameter
395
     * <code>currTargetSetSize</code> is correct and if all <code>null</code>
396
     * elements of the target set are placed at the end of the array at the
397
     * moment this method is called. The target array must contain enough
398
     * <code>null</code> elements so that all elements to be added to the set
399
     * can fit.
400
     *
401
     * @param  setToAdd  elements to be added to the target set
402
     *                   - must not contain <code>null</code> elements
403
     * @param  targetSet  array to add elements to
404
     * @param  currTargetSetSize  current count of non-null elements in the
405
     *                            target set (<code>null</code> elements are
406
     *                            always at the end of the array)
407
     * @return  new size of the target set
408
     *          (number of non-<code>null</code> elements)
409
     */
410
    private static int merge(final Object[] setToAdd,
411
                             final Object[] targetSet,
412
                             final int currTargetSetSize) {
413
        if (setToAdd.length == 0) {
414
            return currTargetSetSize;
415
        }
416
        if (currTargetSetSize == 0) {
417
            System.arraycopy(setToAdd, 0, targetSet, 0, setToAdd.length);
418
            return setToAdd.length;
419
        }
420
        int targetSetSize = currTargetSetSize;
421
        toAdd:
422
        for (int i = 0; i < setToAdd.length; i++) {
423
            final Object objToAdd = setToAdd[i];
424
            for (int j = 0; j < targetSetSize; j++) {
425
                final Object chosen = chooseTarget(targetSet[j], objToAdd);
426
                if (chosen != null) {           //both point to the same folder
427
                    targetSet[j] = chosen;
428
                    continue toAdd;
429
                }
430
            }
431
            targetSet[targetSetSize++] = objToAdd;
432
        }
433
        return targetSetSize;
434
    }
435
436
    /**
437
     * Finds whether the given two objects defining a target folder are equal
438
     * or not and if so, suggests which one is preferred.
439
     * Each of the folder targets may be either a <code>SourceGroup<code>
440
     * object or a <code>FileObject</code> folder. If both targets point
441
     * to the same folder, one of them which is preferred is returned.
442
     * Otherwise <code>null</code> is returned.
443
     * <p>
444
     * If both targets are <code>SourceGroup</code>s, the first target is used.
445
     * If none of the targets is a <code>SourceGroup</code>, the first target is
446
     * used.
447
     * Otherwise (i.e. one target is a <code>SourceGroup</code>,
448
     * the other is not), the <code>SourceGroup</code> target is returned.
449
     *
450
     * @param  target1  one target
451
     * @param  target2  second target
452
     * @return  <code>null</code> if the two targets define different folders;
453
     *          or the preferred one (of the passed targets) if the two
454
     *          are equal
455
     */
456
    private static Object chooseTarget(Object target1, Object target2) {
457
        final boolean isGroup1 = target1 instanceof SourceGroup;
458
        final boolean isGroup2 = target2 instanceof SourceGroup;
459
460
        assert isGroup1 || (target1 instanceof FileObject);
461
        assert isGroup2 || (target2 instanceof FileObject);
462
        
463
        if (isGroup1 && isGroup2 && target1.equals(target2)) {
464
            return target1;
465
        }
466
467
        final FileObject folder1 = isGroup1
468
                                   ? ((SourceGroup) target1).getRootFolder()
469
                                   : ((FileObject) target1);
470
        final FileObject folder2 = isGroup2
471
                                   ? ((SourceGroup) target2).getRootFolder()
472
                                   : ((FileObject) target2);
473
        if (!(folder1.isFolder())) {
474
            throw new IllegalArgumentException("target1: not a folder");//NOI18N
475
        }
476
        if (!(folder2.isFolder())) {
477
            throw new IllegalArgumentException("target2: not a folder");//NOI18N
478
        }
479
        if (folder1.equals(folder2)) {
480
            return (isGroup1 == isGroup2) ? target1
481
                                          : (isGroup1 ? target1 : target2);
482
        }
483
        return null;
484
    }
485
486
    /**
487
     * Returns test targets for the given <code>SourceGroup</code>.
488
     * The test targets are folders which are searched when tests for a class
489
     * from the <code>SourceGroup</code> are to be found. Each of the returned
490
     * test targets may be either <code>SourceGroup</code> (representing
491
     * a folder plus additional information such as display name) or simply
492
     * a <code>FileObject</code> representing a folder.
493
     * If parameter <code>includeSourceGroups</code> is <code>false</code>,
494
     * only <code>SourceGroup<code>s are returned (target folders without
495
     * corresponding <code>SourceGroup</code>s are ignored).
496
     *
497
     * @param  src  source group to find test targets for
498
     * @param  sourceGroupsOnly  skip target folders without matching
499
     *                           <code>SourceGroup</code>
500
     * @return  array which may contain <code>FileObject</code>s
501
     *          or <code>SourceGroup</code>s (or both);
502
     *          it may be empty but not <code>null</code>
503
     * @see  CommonTestUtil#getFileObject2SourceGroupMap
504
     */
505
    public Object[] getTestTargets(SourceGroup sourceGroup,
506
                                   final boolean sourceGroupsOnly) {
507
        
508
        /* .) find test root folders: */
509
        final FileObject[] testFolders
510
                    = getTestFoldersRaw(sourceGroup.getRootFolder());
511
        
512
        if (testFolders.length == 0) {
513
            return new Object[0];
514
        }
515
        
516
        /* .) find SourceGroups corresponding to the FileObjects: */
517
        final Object[] targets = new Object[testFolders.length];
518
        for (int i = 0; i < targets.length; i++) {
519
            final FileObject testFolder = testFolders[i];
520
            if (testFolder == null) {
521
                continue;
522
            }
523
            Object srcGroup = foldersToSourceGroupsMap.get(testFolder);
524
            targets[i] = (srcGroup != null)
525
                         ? srcGroup
526
                         : sourceGroupsOnly ? null : testFolder;
527
        }
528
        return CommonTestUtil.skipNulls(targets, new Object[0]);
529
    }
530
    
531
    /**
532
     * Returns an array of test folders corresponding to the given source
533
     * folder - may contain <code>null</code>s.
534
     *
535
     * @param  srcFolder  <code>FileObject</code> representing source code root,
536
     *                    for which test root folders should be found
537
     * @return  array of <code>FileObject</code>s representing test root
538
     *          folders, possibly with superfluous <code>null</code> elements
539
     * @see  #getSourceFoldersRaw
540
     */
541
    public FileObject[] getTestFoldersRaw(FileObject srcFolder) {
542
        return getFileObjects(UnitTestForSourceQuery.findUnitTests(srcFolder),
543
                              true);
544
    }
545
    
546
    /**
547
     * Returns an array of source folders corresponding to the given test
548
     * folder - may contain <code>null</code>s.
549
     *
550
     * @param  srcFolder  <code>FileObject</code> representing source code root,
551
     *                    for which source root folders should be found
552
     * @return  array of <code>FileObject</code>s representing source root
553
     *          folders, possibly with superfluous <code>null</code> elements
554
     * @see  #getTestFoldersRaw
555
     */
556
    public FileObject[] getSourceFoldersRaw(FileObject testFolder) {
557
        return getFileObjects(UnitTestForSourceQuery.findSources(testFolder),
558
                              false);
559
    }
560
    
561
    /**
562
     * Returns <code>FileObject</code>s represented by the given URLs.
563
     *
564
     * @param  rootURLs  URLs representing <code>FileObject</code>s
565
     * @param  srcToTest  <code>true</code> if we are searching for test
566
     *                    folders, <code>false</code> if we are searching
567
     *                    for source folders - affects only text of warning
568
     *                    log messages
569
     * @return  array of <code>FileObject</code>s representing source root
570
     *          folders, possibly with superfluous <code>null</code> elements
571
     */
572
    private FileObject[] getFileObjects(final URL[] rootURLs,
573
                                        final boolean srcToTest) {
574
        if (rootURLs.length == 0) {
575
            return new FileObject[0];
576
        }
577
        
578
        FileObject[] sourceRoots = new FileObject[rootURLs.length];
579
        for (int i = 0; i < rootURLs.length; i++) {
580
            if ((sourceRoots[i] = URLMapper.findFileObject(rootURLs[i]))
581
                    == null) {
582
                final int severity = ErrorManager.INFORMATIONAL;
583
                if (ErrorManager.getDefault().isLoggable(severity)) {
584
                    ErrorManager.getDefault().log(
585
                            severity,
586
                            (srcToTest ? "Test" : "Source")             //NOI18N
587
                            + " directory " + rootURLs[i]               //NOI18N
588
                            + " declared by project "                   //NOI18N
589
                            + ProjectUtils.getInformation(project).getName()
590
                            + " does not exist.");                      //NOI18N
591
                }
592
                continue;
593
            }
594
            Project sourceRootOwner = FileOwnerQuery.getOwner(sourceRoots[i]);
595
            if (!project.equals(sourceRootOwner)) {
596
                sourceRoots[i] = null;
597
                
598
                int severity = ErrorManager.INFORMATIONAL;
599
                if (ErrorManager.getDefault().isNotifiable(severity)) {
600
                    ErrorManager.getDefault().notify(
601
                        severity,
602
                        new IllegalStateException(
603
                            "Malformed project: Found test root (" +    //NOI18N
604
                                rootURLs[i] + ')' + ' ' +
605
                                (sourceRootOwner == null
606
                                        ? "does not belong to any"      //NOI18N
607
                                        : "belongs to a different") +   //NOI18N
608
                                " project."));                          //NOI18N
609
                }
610
                continue;
611
            }
612
        }
613
        return sourceRoots;
614
    }
615
616
    /**
617
     */
618
    public static FileObject[] skipNulls(final FileObject[] fileObjs) {
619
        if (fileObjs.length == 0) {
620
            return fileObjs;
621
        }
622
        
623
        int nullsCount = 0;
624
        for (int i = 0; i < fileObjs.length; i++) {
625
            if (fileObjs[i] == null) {
626
                nullsCount++;
627
            }
628
        }
629
        
630
        if (nullsCount == 0) {
631
            return fileObjs;
632
        }
633
        if (nullsCount == fileObjs.length) {
634
            return new FileObject[0];
635
        }
636
        
637
        final FileObject[] fileObjsNew
638
                = new FileObject[fileObjs.length - nullsCount];
639
        int index = 0, indexNew = 0;
640
        while (indexNew < fileObjsNew.length) {
641
            FileObject fileObj = fileObjs[index++];
642
            if (fileObj != null) {
643
                fileObjsNew[indexNew++] = fileObj;
644
            }
645
        }
646
        return fileObjsNew;
647
    }
648
649
    /**
650
     * Creates a map mapping folders to source groups.
651
     * For a folder as a key, the map returns the source group having that
652
     * folder as a root. The created map is stored to variable
653
     * {@link #foldersToSourceGroupsMap}.
654
     *
655
     * @param  sourceGroup  source group to create a map from
656
     * @author  Marian Petras
657
     */
658
    private void createFoldersToSourceGroupsMap(
659
            final SourceGroup[] sourceGroups) {
660
        Map<FileObject,Object> result;
661
662
        if (sourceGroups.length == 0) {
663
            result = Collections.<FileObject,Object>emptyMap();
664
        } else {
665
            result = new HashMap<FileObject,Object>(2 * sourceGroups.length,
666
                                                    .5f);
667
            for (SourceGroup sourceGroup : sourceGroups) {
668
                result.put(sourceGroup.getRootFolder(), sourceGroup);
669
            }
670
        }
671
672
        foldersToSourceGroupsMap = result;
673
    }
674
    
675
    /**
676
     * <!-- PENDING -->
677
     */
678
    public SourceGroup[] getJavaSourceGroups() {
679
        if (javaSourceGroups == null) {
680
            javaSourceGroups = ProjectUtils.getSources(project).getSourceGroups(
681
                                        JavaProjectConstants.SOURCES_TYPE_JAVA);
682
        }
683
        return javaSourceGroups;
684
    }
685
    
686
    /**
687
     * Finds a <code>SourceGroup</code> having the specified root folder.
688
     * If there are more <code>SourceGroup</code>s matching, the first one
689
     * (according to the order of elements in the array) is returned.
690
     *
691
     * @param  sourceGroups  source groups to test
692
     * @param  rootFolder  root folder of a source group to be found
693
     * @return  the found <code>SourceGroup</code>;
694
     *          or <code>null</code> if no matching <code>SourceGroup</code>
695
     *          was found
696
     */
697
    private static SourceGroup findSourceGroup(SourceGroup[] sourceGroups,
698
                                               FileObject rootFolder) {
699
        for (int i = 0; i < sourceGroups.length; i++) {
700
            if (sourceGroups[i].getRootFolder().equals(rootFolder)) {
701
                return sourceGroups[i];
702
            }
703
        }
704
        return (SourceGroup) null;
705
    }
706
    
707
    static boolean isValidClassName(String className) {
708
        if (className.length() == 0) {
709
            return false;
710
        }
711
        char[] chars = className.toCharArray();
712
        int segmentStart = 0;
713
        int i;
714
        for (i = 0; i < chars.length; i++) {
715
            if (chars[i] == '.') {
716
                if (i == segmentStart) {
717
                    return false;         //empty segment
718
                }
719
                if (!Utilities.isJavaIdentifier(
720
                        className.substring(segmentStart, i))) {
721
                    return false;         //illegal name of the segment
722
                }
723
                segmentStart = i + 1;
724
            }
725
        }
726
        if (i == segmentStart) {
727
            return false;                 //empty last segment
728
        }
729
        if (!Utilities.isJavaIdentifier(
730
                className.substring(segmentStart, chars.length))) {
731
            return false;                 //illegal name of the last segment
732
        }
733
        return true;
734
    }
735
    
736
    /**
737
     */
738
    public static void openFile(FileObject file, int lineNum) {
739
740
        /*
741
         * Most of the following code was copied from the Ant module, method
742
         * org.apache.tools.ant.module.run.Hyperlink.outputLineAction(...).
743
         */
744
745
        if (file == null) {
746
            java.awt.Toolkit.getDefaultToolkit().beep();
747
            return;
748
        }
749
750
        try {
751
            DataObject dob = DataObject.find(file);
752
            EditorCookie ed = dob.getCookie(EditorCookie.class);
753
            if (ed != null && /* not true e.g. for *_ja.properties */
754
                              file == dob.getPrimaryFile()) {
755
                if (lineNum == -1) {
756
                    // OK, just open it.
757
                    ed.open();
758
                } else {
759
                    ed.openDocument();//XXX getLineSet doesn't do it for you
760
                    try {
761
                        Line l = ed.getLineSet().getOriginal(lineNum - 1);
762
                        if (!l.isDeleted()) {
763
                            l.show(ShowOpenType.OPEN, ShowVisibilityType.FOCUS);
764
                        }
765
                    } catch (IndexOutOfBoundsException ioobe) {
766
                        // Probably harmless. Bogus line number.
767
                        ed.open();
768
                    }
769
                }
770
            } else {
771
                java.awt.Toolkit.getDefaultToolkit().beep();
772
            }
773
        } catch (DataObjectNotFoundException ex1) {
774
            ErrorManager.getDefault().notify(ErrorManager.WARNING, ex1);
775
        } catch (IOException ex2) {
776
            // XXX see above, should not be necessary to call openDocument
777
            // at all
778
            ErrorManager.getDefault().notify(ErrorManager.WARNING, ex2);
779
        }
780
    }
781
        
782
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/CommonSettings.java (+299 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.gsf.testrunner.api;
46
47
import java.util.prefs.Preferences;
48
import org.openide.util.HelpCtx;
49
import org.openide.util.NbBundle;
50
import org.openide.util.NbPreferences;
51
52
/** Options for JUnit module, control behavior of test creation and execution.
53
 *
54
 * @author  vstejskal
55
 * @author  Marian Petras
56
 */
57
public class CommonSettings {
58
    private static final CommonSettings INSTANCE = new CommonSettings();
59
    
60
    /** prefix for names of generated test classes */
61
    public static final String TEST_CLASSNAME_PREFIX = NbBundle.getMessage(
62
            CommonSettings.class,
63
            "PROP_test_classname_prefix");                //NOI18N
64
    /** suffix for names of generated test classes */
65
    public static final String TEST_CLASSNAME_SUFFIX = NbBundle.getMessage(
66
            CommonSettings.class,
67
            "PROP_test_classname_suffix");                //NOI18N
68
    /** prefix for names of generated test suites */
69
    public static final String SUITE_CLASSNAME_PREFIX = NbBundle.getMessage(
70
            CommonSettings.class,
71
            "PROP_suite_classname_prefix");               //NOI18N
72
    /** suffix for names of generated test suites */
73
    public static final String SUITE_CLASSNAME_SUFFIX = NbBundle.getMessage(
74
            CommonSettings.class,
75
            "PROP_suite_classname_suffix");               //NOI18N
76
    /** should it be possible to create tests for tests? */
77
    public static final boolean GENERATE_TESTS_FROM_TEST_CLASSES = NbBundle.getMessage(
78
            CommonSettings.class,
79
            "PROP_generate_tests_from_test_classes").equals("true");    //NOI18N
80
    /** generate test initializer method by default? */
81
    public static final boolean DEFAULT_GENERATE_SETUP = NbBundle.getMessage(
82
            CommonSettings.class,
83
            "PROP_generate_setUp_default").equals("true");              //NOI18N
84
    /** generate test finalizer method by default? */
85
    public static final boolean DEFAULT_GENERATE_TEARDOWN = NbBundle.getMessage(
86
            CommonSettings.class,
87
            "PROP_generate_tearDown_default").equals("true");           //NOI18N
88
    /** generate test class initializer method by default? */
89
    public static final boolean DEFAULT_GENERATE_CLASS_SETUP = NbBundle.getMessage(
90
            CommonSettings.class,
91
            "PROP_generate_class_setUp_default").equals("true");        //NOI18N
92
    /** generate test class finalizer method by default? */
93
    public static final boolean DEFAULT_GENERATE_CLASS_TEARDOWN = NbBundle.getMessage(
94
            CommonSettings.class,
95
            "PROP_generate_class_tearDown_default").equals("true");     //NOI18N
96
97
    // XXX this property has to go too - will not work any longer, need some src -> test query
98
    private static final String PROP_FILE_SYSTEM         = "fileSystem";
99
    public static final String PROP_MEMBERS_PUBLIC      = "membersPublic";
100
    public static final String PROP_MEMBERS_PROTECTED   = "membersProtected";
101
    public static final String PROP_MEMBERS_PACKAGE     = "membersPackage";
102
    public static final String PROP_BODY_COMMENTS       = "bodyComments";
103
    public static final String PROP_BODY_CONTENT        = "bodyContent";
104
    public static final String PROP_JAVADOC             = "javaDoc";
105
    public static final String PROP_GENERATE_EXCEPTION_CLASSES = "generateExceptionClasses";
106
    public static final String PROP_GENERATE_ABSTRACT_IMPL = "generateAbstractImpl";
107
    public static final String PROP_GENERATE_SUITE_CLASSES   = "generateSuiteClasses";
108
    
109
    public static final String PROP_INCLUDE_PACKAGE_PRIVATE_CLASSES = "includePackagePrivateClasses";
110
    public static final String PROP_GENERATE_MAIN_METHOD = "generateMainMethod";
111
    public static final String PROP_GENERATE_MAIN_METHOD_BODY = "generateMainMethodBody";
112
    public static final String PROP_GENERATE_SETUP      = "generateSetUp";
113
    public static final String PROP_GENERATE_TEARDOWN   = "generateTearDown";
114
    public static final String PROP_GENERATE_CLASS_SETUP      = "generateClassSetUp";
115
    public static final String PROP_GENERATE_CLASS_TEARDOWN   = "generateClassTearDown";
116
    public static final String PROP_GENERATOR = "generator";
117
    public static final String PROP_ROOT_SUITE_CLASSNAME = "rootSuiteClassName";                
118
119
    public static final String PROP_RESULTS_SPLITPANE_DIVIDER = "resultsSplitDivider";
120
    
121
    public String displayName () {
122
        return NbBundle.getMessage (CommonSettings.class, "LBL_junit_settings");
123
    }
124
125
    public HelpCtx getHelpCtx () {
126
        return new HelpCtx(CommonSettings.class); 
127
    }
128
129
    private  static Preferences getPreferences() {
130
        return NbPreferences.forModule(CommonSettings.class);
131
    }
132
133
    /** Default instance of this system option, for the convenience of associated classes. */
134
    public static CommonSettings getDefault () {
135
        return INSTANCE;
136
    }
137
138
    public boolean isMembersPublic() {
139
        return getPreferences().getBoolean(PROP_MEMBERS_PUBLIC,true);
140
    }
141
142
    public void setMembersPublic(boolean newVal) {
143
        getPreferences().putBoolean(PROP_MEMBERS_PUBLIC,newVal);
144
    }
145
146
    public boolean isMembersProtected() {
147
        return getPreferences().getBoolean(PROP_MEMBERS_PROTECTED,true);
148
    }
149
150
    public void setMembersProtected(boolean newVal) {
151
        getPreferences().putBoolean(PROP_MEMBERS_PROTECTED,newVal);
152
    }
153
154
    public boolean isMembersPackage() {
155
        return getPreferences().getBoolean(PROP_MEMBERS_PACKAGE,true);
156
    }
157
158
    public void setMembersPackage(boolean newVal) {
159
        getPreferences().putBoolean(PROP_MEMBERS_PACKAGE,newVal);
160
    }
161
162
    public boolean isBodyComments() {
163
        return getPreferences().getBoolean(PROP_BODY_COMMENTS,true);
164
        
165
    }
166
167
    public void setBodyComments(boolean newVal) {
168
        getPreferences().putBoolean(PROP_BODY_COMMENTS,newVal);
169
    }
170
171
    public boolean isBodyContent() {
172
        return getPreferences().getBoolean(PROP_BODY_CONTENT,true);
173
    }
174
175
    public void setBodyContent(boolean newVal) {
176
        getPreferences().putBoolean(PROP_BODY_CONTENT,newVal);
177
    }
178
179
    public boolean isJavaDoc() {
180
        return getPreferences().getBoolean(PROP_JAVADOC,true);
181
    }
182
183
    public void setJavaDoc(boolean newVal) {
184
        getPreferences().putBoolean(PROP_JAVADOC,newVal);
185
    }
186
   
187
    public boolean isGenerateExceptionClasses() {
188
        return getPreferences().getBoolean(PROP_GENERATE_EXCEPTION_CLASSES,true);
189
    }
190
191
    public void setGenerateExceptionClasses(boolean newVal) {
192
        getPreferences().putBoolean(PROP_GENERATE_EXCEPTION_CLASSES,newVal);
193
    }
194
    
195
   
196
    public boolean isGenerateAbstractImpl() {
197
     return getPreferences().getBoolean(PROP_GENERATE_ABSTRACT_IMPL,true);
198
    }
199
200
    public void setGenerateAbstractImpl(boolean newVal) {
201
        getPreferences().putBoolean(PROP_GENERATE_ABSTRACT_IMPL,newVal);
202
    }
203
204
    public boolean isGenerateSuiteClasses() {
205
        return getPreferences().getBoolean(PROP_GENERATE_SUITE_CLASSES,true);
206
    }
207
208
    public void setGenerateSuiteClasses(boolean newVal) {
209
        getPreferences().putBoolean(PROP_GENERATE_SUITE_CLASSES,newVal);
210
    }
211
212
    
213
    public boolean isIncludePackagePrivateClasses() {
214
        return getPreferences().getBoolean(PROP_INCLUDE_PACKAGE_PRIVATE_CLASSES,true);
215
    }
216
217
    public void setIncludePackagePrivateClasses(boolean newVal) {
218
        getPreferences().putBoolean(PROP_INCLUDE_PACKAGE_PRIVATE_CLASSES,newVal);
219
    }    
220
    
221
    public boolean isGenerateMainMethod() {
222
        return getPreferences().getBoolean(PROP_GENERATE_MAIN_METHOD,true);
223
    }
224
225
    public void setGenerateMainMethod(boolean newVal) {
226
        getPreferences().putBoolean(PROP_GENERATE_MAIN_METHOD,newVal);
227
    }
228
    
229
    public boolean isGenerateSetUp() {
230
        return getPreferences().getBoolean(PROP_GENERATE_SETUP,
231
                                           DEFAULT_GENERATE_SETUP);
232
    }
233
234
    public void setGenerateSetUp(boolean newVal) {
235
        getPreferences().putBoolean(PROP_GENERATE_SETUP,newVal);
236
    }
237
    
238
    public boolean isGenerateTearDown() {
239
        return getPreferences().getBoolean(PROP_GENERATE_TEARDOWN,
240
                                           DEFAULT_GENERATE_TEARDOWN);
241
    }
242
243
    public void setGenerateTearDown(boolean newVal) {
244
        getPreferences().putBoolean(PROP_GENERATE_TEARDOWN,newVal);
245
    }
246
    
247
    public boolean isGenerateClassSetUp() {
248
        return getPreferences().getBoolean(PROP_GENERATE_CLASS_SETUP,
249
                                           DEFAULT_GENERATE_CLASS_SETUP);
250
    }
251
252
    public void setGenerateClassSetUp(boolean newVal) {
253
        getPreferences().putBoolean(PROP_GENERATE_CLASS_SETUP, newVal);
254
    }
255
    
256
    public boolean isGenerateClassTearDown() {
257
        return getPreferences().getBoolean(PROP_GENERATE_CLASS_TEARDOWN,
258
                                           DEFAULT_GENERATE_CLASS_TEARDOWN);
259
    }
260
261
    public void setGenerateClassTearDown(boolean newVal) {
262
        getPreferences().putBoolean(PROP_GENERATE_CLASS_TEARDOWN, newVal);
263
    }
264
    
265
    public String getGenerator() {
266
        return null;//getPreferences().get(PROP_GENERATOR, DEFAULT_GENERATOR);
267
    }
268
    
269
    public void setGenerator(String generator) {
270
        getPreferences().put(PROP_GENERATOR, generator);
271
    }
272
    
273
    public String getGenerateMainMethodBody() {
274
        return getPreferences().get(PROP_GENERATE_MAIN_METHOD_BODY,
275
                NbBundle.getMessage(CommonSettings.class, "PROP_generate_main_method_body_default_value"));
276
    }
277
278
    public void setGenerateMainMethodBody(String newVal) {
279
        getPreferences().put(PROP_GENERATE_MAIN_METHOD_BODY,newVal);
280
    }
281
    
282
    public String getRootSuiteClassName() {        
283
        return getPreferences().get(PROP_ROOT_SUITE_CLASSNAME,
284
                NbBundle.getMessage(CommonSettings.class, "PROP_root_suite_classname_default_value"));
285
    }
286
287
    public void setRootSuiteClassName(String newVal) {
288
        getPreferences().put(PROP_ROOT_SUITE_CLASSNAME,newVal);
289
    }    
290
291
    public int getResultsSplitPaneDivider() {        
292
        return getPreferences().getInt(PROP_RESULTS_SPLITPANE_DIVIDER, -1);
293
    }
294
295
    public void setResultsSplitPaneDivider(int newVal) {
296
        getPreferences().putInt(PROP_RESULTS_SPLITPANE_DIVIDER, newVal);
297
    }    
298
    
299
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/CommonTestUtil.java (+381 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.gsf.testrunner.api;
46
47
import java.net.URL;
48
import java.util.*;
49
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
50
import org.netbeans.api.project.FileOwnerQuery;
51
import org.netbeans.api.project.Project;
52
import org.netbeans.api.project.SourceGroup;
53
import org.netbeans.modules.gsf.testrunner.Utils;
54
import org.netbeans.modules.gsf.testrunner.plugin.CommonPlugin.CreateTestParam;
55
import org.openide.ErrorManager;
56
import org.openide.filesystems.FileObject;
57
import org.openide.filesystems.FileUtil;
58
import org.openide.filesystems.URLMapper;
59
import org.openide.loaders.DataFolder;
60
import org.openide.loaders.DataObject;
61
import org.openide.nodes.Node;
62
63
/**
64
 *
65
 * @author  rmatous
66
 * @author  Marian Petras
67
 * @version 1.1
68
 */
69
public class CommonTestUtil {
70
    static private final String JAVA_SOURCES_SUFFIX = "java"; //NOI18N
71
72
    /**
73
     */
74
    public static boolean isJavaFile(FileObject fileObj) {
75
        return "java".equals(fileObj.getExt())                          //NOI18N
76
               || "text/x-java".equals(FileUtil.getMIMEType(fileObj));  //NOI18N
77
    }
78
    
79
    static public FileObject getFileObjectFromNode(Node node) {
80
        DataObject dO;
81
        DataFolder df;
82
83
        dO = node.getLookup().lookup(DataObject.class);
84
        if (null != dO) {
85
            return dO.getPrimaryFile();
86
        }
87
88
        df = node.getLookup().lookup(DataFolder.class);
89
        if (null != df) {
90
            return df.getPrimaryFile();
91
        }
92
        return null;
93
    }
94
    
95
    /**
96
     * Finds all <code>SourceGroup</code>s of the given project
97
     * containing a class of the given name.
98
     *
99
     * @param  project  project to be searched for matching classes
100
     * @param  className  class name pattern
101
     * @return  unmodifiable collection of <code>SourceGroup</code>s
102
     *          which contain files corresponding to the given name
103
     *          (may be empty but not <code>null</code>)
104
     * @author  Marian Petras
105
     */
106
    public static Collection<SourceGroup> findSourceGroupOwners(
107
            final Project project,
108
            final String className) {
109
        final SourceGroup[] sourceGroups
110
                = new Utils(project).getJavaSourceGroups();
111
        if (sourceGroups.length == 0) {
112
            return Collections.<SourceGroup>emptyList();
113
        }
114
        
115
        final String relativePath = className.replace('.', '/')
116
                                    + ".java";                          //NOI18N
117
        
118
        ArrayList<SourceGroup> result = new ArrayList<SourceGroup>(4);
119
        for (int i = 0; i < sourceGroups.length; i++) {
120
            SourceGroup srcGroup = sourceGroups[i];
121
            FileObject root = srcGroup.getRootFolder();
122
            FileObject file = root.getFileObject(relativePath);
123
            if (file != null && FileUtil.isParentOf(root, file)
124
                             && srcGroup.contains(file)) {
125
                result.add(srcGroup);
126
            }
127
        }
128
        if (result.isEmpty()) {
129
            return Collections.<SourceGroup>emptyList();
130
        }
131
        result.trimToSize();
132
        return Collections.unmodifiableList(result);
133
    }
134
135
    /**
136
     * Finds <code>SourceGroup</code>s where a test for the given class
137
     * can be created (so that it can be found by the projects infrastructure
138
     * when a test for the class is to be opened or run).
139
     *
140
     * @param  fileObject  <code>FileObject</code> to find target
141
     *                     <code>SourceGroup</code>(s) for
142
     * @return  an array of objects - each of them can be either
143
     *          a <code>SourceGroup</code> for a possible target folder
144
     *          or simply a <code>FileObject</code> representing a possible
145
     *          target folder (if <code>SourceGroup</code>) for the folder
146
     *          was not found);
147
     *          the returned array may be empty but not <code>null</code>
148
     * @author  Marian Petras
149
     */
150
    public static Object[] getTestTargets(FileObject fileObject) {
151
        
152
        /* .) get project owning the given FileObject: */
153
        final Project project = FileOwnerQuery.getOwner(fileObject);
154
        if (project == null) {
155
            return new Object[0];
156
        }
157
        
158
        SourceGroup sourceGroupOwner = findSourceGroupOwner(fileObject);
159
        if (sourceGroupOwner == null) {
160
            return new Object[0];
161
        }
162
        
163
        /* .) get URLs of target SourceGroup's roots: */
164
        final URL[] rootURLs = UnitTestForSourceQuery.findUnitTests(
165
                                       sourceGroupOwner.getRootFolder());
166
        if (rootURLs.length == 0) {
167
            return new Object[0];
168
        }
169
        
170
        /* .) convert the URLs to FileObjects: */
171
        boolean someSkipped = false;
172
        FileObject[] sourceRoots = new FileObject[rootURLs.length];
173
        for (int i = 0; i < rootURLs.length; i++) {
174
            if ((sourceRoots[i] = URLMapper.findFileObject(rootURLs[i]))
175
                    == null) {
176
                ErrorManager.getDefault().notify(
177
                        ErrorManager.INFORMATIONAL,
178
                        new IllegalStateException(
179
                           "No FileObject found for the following URL: "//NOI18N
180
                           + rootURLs[i]));
181
                someSkipped = true;
182
                continue;
183
            }
184
            if (FileOwnerQuery.getOwner(sourceRoots[i]) != project) {
185
                ErrorManager.getDefault().notify(
186
                        ErrorManager.INFORMATIONAL,
187
                        new IllegalStateException(
188
                    "Source root found by FileOwnerQuery points "       //NOI18N
189
                    + "to a different project for the following URL: "  //NOI18N
190
                    + rootURLs[i]));
191
                sourceRoots[i] = null;
192
                someSkipped = true;
193
                continue;
194
            }
195
        }
196
        
197
        if (someSkipped) {
198
            FileObject roots[] = skipNulls(sourceRoots, new FileObject[0]);
199
            if (roots.length == 0) {
200
                return new Object[0];
201
            }
202
            sourceRoots = roots;
203
        }
204
        
205
        /* .) find SourceGroups corresponding to the FileObjects: */
206
        final Object[] targets = new Object[sourceRoots.length];
207
        Map<FileObject,SourceGroup> map = getFileObject2SourceGroupMap(project);
208
        for (int i = 0; i < sourceRoots.length; i++) {
209
            SourceGroup srcGroup = map.get(sourceRoots[i]);
210
            targets[i] = srcGroup != null ? srcGroup : sourceRoots[i];
211
        }
212
        return targets;
213
    }
214
    
215
    /**
216
     * Finds a <code>SourceGroup</code> the given file belongs to.
217
     * Only Java <code>SourceGroup</code>s are taken into account.
218
     *
219
     * @param  file  <code>FileObject</code> whose owning
220
     *               <code>SourceGroup</code> to be found
221
     * @return  Java <code>SourceGroup</code> containing the given
222
     *          file; or <code>null</code> if no such
223
     *          <code>SourceGroup</code> was found
224
     * @author  Marian Petras
225
     */
226
    public static SourceGroup findSourceGroupOwner(FileObject file) {
227
        final Project project = FileOwnerQuery.getOwner(file);
228
        return findSourceGroupOwner(project, file);
229
    }
230
    
231
    /**
232
     * Finds a <code>SourceGroup</code> the given file belongs to.
233
     * Only Java <code>SourceGroup</code>s are taken into account. 
234
     *
235
     * @param project the <code>Project</code> the file belongs to
236
     * @param  file  <code>FileObject</code> whose owning
237
     *               <code>SourceGroup</code> to be found
238
     * @return  Java <code>SourceGroup</code> containing the given
239
     *          file; or <code>null</code> if no such
240
     *          <code>SourceGroup</code> was found
241
     */
242
243
    public static SourceGroup findSourceGroupOwner(Project project, FileObject file) {        
244
        final SourceGroup[] sourceGroups
245
                = new Utils(project).getJavaSourceGroups();
246
        for (int i = 0; i < sourceGroups.length; i++) {
247
            SourceGroup srcGroup = sourceGroups[i];
248
            FileObject root = srcGroup.getRootFolder();
249
            if (((file==root)||(FileUtil.isParentOf(root,file))) && 
250
                 srcGroup.contains(file)) {
251
                return srcGroup;
252
            }
253
        }
254
        return null;
255
    }
256
    
257
    /**
258
     * Creates a copy of the given array, except that <code>null</code> objects
259
     * are omitted.
260
     * The length of the returned array is (<var>l</var> - <var>n</var>), where
261
     * <var>l</var> is length of the passed array and <var>n</var> is number
262
     * of <code>null</code> elements of the array. Order of
263
     * non-<code>null</code> elements is kept in the returned array.
264
     * The returned array is always a new array, even if the passed
265
     * array does not contain any <code>null</code> elements.
266
     *
267
     * @param  objs  array to copy
268
     * @param  type  an empty array of the correct type to be returned
269
     * @return  array containing the same objects as the passed array, in the
270
     *          same order, just with <code>null</code> elements missing
271
     * @author  Marian Petras
272
     */
273
    public static <T> T[] skipNulls(final T[] objs, final T[] type) {
274
        List<T> resultList = new ArrayList<T>(objs.length);
275
        
276
        for (int i = 0; i < objs.length; i++) {
277
            if (objs[i] != null) {
278
                resultList.add(objs[i]);
279
            }
280
        }
281
        
282
        return resultList.toArray(type);
283
    }
284
    
285
    /**
286
     * Creates a map from folders to <code>SourceGroup</code>s of a given
287
     * project.
288
     * The map allows to ascertian for a given folder
289
     * which <code>SourceGroup</code> it is a root folder of.
290
     *
291
     * @param  project  project whose <code>SourceGroup</code>s should be in the
292
     *                  returned map
293
     * @return  map from containing all <code>SourceGroup</code>s of a given
294
     *          project, having their root folders as keys
295
     * @author  Marian Petras
296
     */
297
    public static Map<FileObject,SourceGroup> getFileObject2SourceGroupMap(
298
                                                              Project project) {
299
        final SourceGroup[] sourceGroups
300
                = new Utils(project).getJavaSourceGroups();
301
        
302
        if (sourceGroups.length == 0) {
303
            return Collections.<FileObject,SourceGroup>emptyMap();
304
        } else if (sourceGroups.length == 1) {
305
            return Collections.singletonMap(sourceGroups[0].getRootFolder(),
306
                                            sourceGroups[0]);
307
        } else {
308
            Map<FileObject,SourceGroup> map;
309
            map = new HashMap<FileObject,SourceGroup>(
310
                    Math.round(sourceGroups.length * 1.4f + .5f),
311
                               .75f);
312
            for (int i = 0; i < sourceGroups.length; i++) {
313
                map.put(sourceGroups[i].getRootFolder(),
314
                        sourceGroups[i]);
315
            }
316
            return map;
317
        }
318
    }
319
320
    /**
321
     * Creates a map of parameters according to the current JUnit module
322
     * settings.<br />
323
     * Note: The map may not contain all the necessary settings,
324
     *       i.g. name of a test class is missing.
325
     *
326
     * @param  multipleFiles  if {@code true}, the map should contain
327
     *                        also settings need for creation of multiple
328
     *                        tests
329
     * @return  map of settings to be used by a
330
     *          {@link org.netbeans.modules.junit.plugin JUnitPlugin}
331
     * @see  org.netbeans.modules.junit.plugin.JUnitPlugin
332
     */
333
    public static Map<CreateTestParam, Object> getSettingsMap(
334
            boolean multipleFiles) {
335
        final CommonSettings settings = CommonSettings.getDefault();
336
        final Map<CreateTestParam, Object> params
337
                    = new HashMap<CreateTestParam, Object>(17);
338
        
339
        params.put(CreateTestParam.INC_PUBLIC,
340
                   Boolean.valueOf(settings.isMembersPublic()));
341
        params.put(CreateTestParam.INC_PROTECTED,
342
                   Boolean.valueOf(settings.isMembersProtected()));
343
        params.put(CreateTestParam.INC_PKG_PRIVATE,
344
                   Boolean.valueOf(settings.isMembersPackage()));
345
        params.put(CreateTestParam.INC_CODE_HINT,
346
                   Boolean.valueOf(settings.isBodyComments()));
347
        params.put(CreateTestParam.INC_METHOD_BODIES,
348
                   Boolean.valueOf(settings.isBodyContent()));
349
        params.put(CreateTestParam.INC_JAVADOC,
350
                   Boolean.valueOf(settings.isJavaDoc()));
351
        
352
        if (multipleFiles) {
353
            params.put(CreateTestParam.INC_GENERATE_SUITE,
354
                       Boolean.valueOf(settings.isGenerateSuiteClasses()));
355
            params.put(CreateTestParam.INC_PKG_PRIVATE_CLASS,
356
                    Boolean.valueOf(settings.isIncludePackagePrivateClasses()));
357
            params.put(CreateTestParam.INC_ABSTRACT_CLASS,
358
                       Boolean.valueOf(settings.isGenerateAbstractImpl()));
359
            params.put(CreateTestParam.INC_EXCEPTION_CLASS,
360
                       Boolean.valueOf(settings.isGenerateExceptionClasses()));
361
        }
362
        else {
363
            // If a class is explicitly selected then corresponding test class
364
            // should be generated in any cases.
365
            params.put(CreateTestParam.INC_PKG_PRIVATE_CLASS,
366
                       Boolean.valueOf(true));
367
            params.put(CreateTestParam.INC_ABSTRACT_CLASS,
368
                       Boolean.valueOf(true));
369
            params.put(CreateTestParam.INC_EXCEPTION_CLASS,
370
                       Boolean.valueOf(true));
371
        }
372
        
373
        params.put(CreateTestParam.INC_SETUP,
374
                   Boolean.valueOf(settings.isGenerateSetUp()));
375
        params.put(CreateTestParam.INC_TEAR_DOWN,
376
                   Boolean.valueOf(settings.isGenerateTearDown()));
377
        
378
        return params;
379
    }
380
    
381
}
(-)a/junit/src/org/netbeans/modules/junit/GuiUtils.java (-2 / +6 lines)
Lines 42-48 Link Here
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
44
45
package org.netbeans.modules.junit;
45
package org.netbeans.modules.gsf.testrunner.api;
46
46
47
import java.awt.BorderLayout;
47
import java.awt.BorderLayout;
48
import java.awt.Color;
48
import java.awt.Color;
Lines 75-80 Link Here
75
    /** */
75
    /** */
76
    public static final String TEMPLATES_DIR = "Templates/JUnit";       //NOI18N
76
    public static final String TEMPLATES_DIR = "Templates/JUnit";       //NOI18N
77
    
77
    
78
    
79
    public static final String JUNIT_TEST_FRAMEWORK = "JUnit";             //NOI18N
80
    public static final String TESTNG_TEST_FRAMEWORK = "TestNG";             //NOI18N
81
    
78
    /** */
82
    /** */
79
    public static final String CHK_PUBLIC = "Public";                   //NOI18N
83
    public static final String CHK_PUBLIC = "Public";                   //NOI18N
80
    /** */
84
    /** */
Lines 197-203 Link Here
197
            }
201
            }
198
            
202
            
199
            JCheckBox chkBox = new JCheckBox();
203
            JCheckBox chkBox = new JCheckBox();
200
            String baseName = "JUnitCfgOfCreate.chk" + id;              //NOI18N
204
            String baseName = "CommonTestsCfgOfCreate.chk" + id;              //NOI18N
201
            AccessibleContext accessCtx = chkBox.getAccessibleContext();
205
            AccessibleContext accessCtx = chkBox.getAccessibleContext();
202
            Mnemonics.setLocalizedText(
206
            Mnemonics.setLocalizedText(
203
                    chkBox,
207
                    chkBox,
(-)a/junit/src/org/netbeans/modules/junit/NamedObject.java (-1 / +1 lines)
Lines 42-48 Link Here
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
44
45
package org.netbeans.modules.junit;
45
package org.netbeans.modules.gsf.testrunner.api;
46
46
47
/**
47
/**
48
 * Object wrapper which allows to assign a name to an object.
48
 * Object wrapper which allows to assign a name to an object.
(-)a/junit/src/org/netbeans/modules/junit/SelfResizingPanel.java (-1 / +1 lines)
Lines 42-48 Link Here
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
44
45
package org.netbeans.modules.junit;
45
package org.netbeans.modules.gsf.testrunner.api;
46
46
47
import java.awt.Dimension;
47
import java.awt.Dimension;
48
import javax.swing.JPanel;
48
import javax.swing.JPanel;
(-)a/junit/src/org/netbeans/modules/junit/SizeRestrictedPanel.java (-1 / +1 lines)
Lines 42-48 Link Here
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 */
44
44
45
package org.netbeans.modules.junit;
45
package org.netbeans.modules.gsf.testrunner.api;
46
46
47
import java.awt.Dimension;
47
import java.awt.Dimension;
48
import java.awt.LayoutManager;
48
import java.awt.LayoutManager;
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/TestCreatorProvider.java (+108 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.gsf.testrunner.api;
43
44
import org.netbeans.api.java.project.JavaProjectConstants;
45
import org.netbeans.api.project.Project;
46
import org.netbeans.api.project.ProjectUtils;
47
import org.netbeans.api.project.SourceGroup;
48
import org.netbeans.api.project.Sources;
49
import org.openide.filesystems.FileObject;
50
import org.openide.filesystems.FileUtil;
51
import org.openide.nodes.Node;
52
53
/**
54
 *
55
 * @author theofanis
56
 */
57
public abstract class TestCreatorProvider {
58
    
59
    private boolean singleClass;
60
    private String testClassName;
61
    private FileObject targetFolder;
62
    
63
    public abstract String getDisplayName();
64
    
65
    public abstract boolean canHandleMultipleClasses(Node[] activatedNodes);
66
    
67
    public abstract boolean enable(Node[] activatedNodes);
68
    
69
    public abstract void createTests(Node[] activatedNodes);
70
    
71
    public static SourceGroup getSourceGroup(FileObject file, Project prj) {
72
        Sources src = ProjectUtils.getSources(prj);
73
        SourceGroup[] srcGrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
74
        for (SourceGroup srcGrp : srcGrps) {
75
            FileObject rootFolder = srcGrp.getRootFolder();
76
            if (((file == rootFolder) || FileUtil.isParentOf(rootFolder, file)) 
77
                    && srcGrp.contains(file)) {
78
                return srcGrp;
79
            }
80
        }
81
        return null;
82
    }
83
84
    public boolean isSingleClass() {
85
        return singleClass;
86
    }
87
88
    public void setSingleClass(boolean singleClass) {
89
        this.singleClass = singleClass;
90
    }
91
92
    public FileObject getTargetFolder() {
93
        return targetFolder;
94
    }
95
96
    public void setTargetFolder(FileObject targetFolder) {
97
        this.targetFolder = targetFolder;
98
    }
99
100
    public String getTestClassName() {
101
        return testClassName;
102
    }
103
104
    public void setTestClassName(String testClassName) {
105
        this.testClassName = testClassName;
106
    }
107
    
108
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/TestMethodDebuggerAction.java (+109 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.gsf.testrunner.api;
43
44
import java.util.Collection;
45
import org.openide.awt.ActionID;
46
import org.openide.awt.ActionReference;
47
import org.openide.awt.ActionReferences;
48
import org.openide.awt.ActionRegistration;
49
import org.openide.nodes.Node;
50
import org.openide.util.HelpCtx;
51
import org.openide.util.Lookup;
52
import org.openide.util.NbBundle;
53
import org.openide.util.actions.NodeAction;
54
55
/**
56
 *
57
 * @author theofanis
58
 */
59
@ActionID(id = "org.netbeans.modules.gsf.testrunner.api.TestMethodDebuggerAction", category = "CommonTestRunner")
60
@ActionRegistration(displayName = "#LBL_Action_DebugTestMethod")
61
@ActionReferences(value = {@ActionReference(path = "Editors/text/x-java/Popup", position=1797)})
62
public class TestMethodDebuggerAction extends NodeAction {
63
    
64
    /** Creates a new instance of TestMethodDebuggerAction */
65
    public TestMethodDebuggerAction() {
66
        putValue("noIconInMenu", Boolean.TRUE);                         //NOI18N
67
    }
68
69
    @Override
70
    public String getName() {
71
        return NbBundle.getMessage(TestMethodDebuggerAction.class, "LBL_Action_DebugTestMethod");
72
    }
73
74
    @Override
75
    public HelpCtx getHelpCtx() {
76
        return HelpCtx.DEFAULT_HELP;
77
    }
78
    
79
    @Override
80
    public boolean asynchronous() {
81
        return false;
82
    }
83
84
    @Override
85
    protected void performAction(Node[] activatedNodes) {
86
        Collection<? extends TestMethodDebuggerProvider> providers = Lookup.getDefault().lookupAll(TestMethodDebuggerProvider.class);
87
        for (TestMethodDebuggerProvider provider : providers) {
88
            if(provider.canHandle(activatedNodes[0])) {
89
                provider.debugTestMethod(activatedNodes[0]);
90
                break;
91
            }
92
        }
93
    }
94
95
    @Override
96
    protected boolean enable(Node[] activatedNodes) {
97
        if (activatedNodes.length == 0) {
98
            return false;
99
        }
100
        Collection<? extends TestMethodDebuggerProvider> providers = Lookup.getDefault().lookupAll(TestMethodDebuggerProvider.class);
101
        for (TestMethodDebuggerProvider provider : providers) {
102
            if(provider.canHandle(activatedNodes[0])) {
103
                return true;
104
            }
105
        }
106
        return false;
107
    }
108
    
109
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/TestMethodDebuggerProvider.java (+65 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.gsf.testrunner.api;
43
44
import org.netbeans.api.java.classpath.ClassPath;
45
import org.netbeans.api.project.FileOwnerQuery;
46
import org.netbeans.api.project.Project;
47
import org.netbeans.api.project.SourceGroup;
48
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
49
import org.openide.filesystems.FileObject;
50
import org.openide.nodes.Node;
51
import org.openide.util.NbBundle;
52
53
/**
54
 *
55
 * @author theofanis
56
 */
57
public abstract class TestMethodDebuggerProvider {
58
    
59
    public abstract String getProviderName();
60
    
61
    public abstract boolean canHandle(Node activatedNode);
62
    
63
    public abstract void debugTestMethod(Node activatedNode);
64
    
65
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/TestMethodRunnerAction.java (+107 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.gsf.testrunner.api;
43
44
import java.util.Collection;
45
import org.openide.awt.ActionID;
46
import org.openide.awt.ActionReference;
47
import org.openide.awt.ActionReferences;
48
import org.openide.awt.ActionRegistration;
49
import org.openide.nodes.Node;
50
import org.openide.util.*;
51
import org.openide.util.actions.NodeAction;
52
53
/**
54
 *
55
 * @author theofanis
56
 */
57
@ActionID(id = "org.netbeans.modules.gsf.testrunner.api.TestMethodRunnerAction", category = "CommonTestRunner")
58
@ActionRegistration(displayName = "#LBL_Action_RunTestMethod")
59
@ActionReferences(value = {@ActionReference(path = "Editors/text/x-java/Popup", position=1795)})
60
public class TestMethodRunnerAction extends NodeAction {
61
    
62
    /** Creates a new instance of TestMethodRunnerAction */
63
    public TestMethodRunnerAction() {
64
        putValue("noIconInMenu", Boolean.TRUE);                         //NOI18N
65
    }
66
67
    @Override
68
    public String getName() {
69
        return NbBundle.getMessage(TestMethodRunnerAction.class, "LBL_Action_RunTestMethod");
70
    }
71
72
    @Override
73
    public HelpCtx getHelpCtx() {
74
        return HelpCtx.DEFAULT_HELP;
75
    }
76
    
77
    @Override
78
    public boolean asynchronous() {
79
        return false;
80
    }
81
82
    @Override
83
    protected void performAction(Node[] activatedNodes) {
84
        Collection<? extends TestMethodRunnerProvider> providers = Lookup.getDefault().lookupAll(TestMethodRunnerProvider.class);
85
        for (TestMethodRunnerProvider provider : providers) {            
86
            if (provider.canHandle(activatedNodes[0])) {
87
                provider.runTestMethod(activatedNodes[0]);
88
                break;
89
            }
90
        }
91
    }
92
93
    @Override
94
    protected boolean enable(Node[] activatedNodes) {
95
        if (activatedNodes.length == 0) {
96
            return false;
97
        }
98
        Collection<? extends TestMethodRunnerProvider> providers = Lookup.getDefault().lookupAll(TestMethodRunnerProvider.class);
99
        for (TestMethodRunnerProvider provider : providers) {
100
            if (provider.canHandle(activatedNodes[0])) {
101
                return true;
102
            }
103
        }
104
        return false;
105
    }
106
107
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/api/TestMethodRunnerProvider.java (+69 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.gsf.testrunner.api;
43
44
import java.io.File;
45
import java.io.IOException;
46
import org.netbeans.api.java.classpath.ClassPath;
47
import org.netbeans.api.project.FileOwnerQuery;
48
import org.netbeans.api.project.Project;
49
import org.netbeans.api.project.ProjectManager;
50
import org.netbeans.api.project.SourceGroup;
51
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
52
import org.openide.filesystems.FileObject;
53
import org.openide.nodes.Node;
54
import org.openide.util.Exceptions;
55
import org.openide.util.NbBundle;
56
57
/**
58
 *
59
 * @author theofanis
60
 */
61
public abstract class TestMethodRunnerProvider {
62
    
63
    public abstract String getProviderName();
64
    
65
    public abstract boolean canHandle(Node activatedNode);
66
    
67
    public abstract void runTestMethod(Node activatedNode);
68
    
69
}
(-)a/gsf.testrunner/src/org/netbeans/modules/gsf/testrunner/plugin/CommonPlugin.java (+329 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 2006-2007 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.gsf.testrunner.plugin;
46
47
import java.util.Map;
48
//import org.netbeans.modules.junit.JUnitPluginTrampoline;
49
import org.openide.filesystems.FileObject;
50
51
/**
52
 * SPI for custom implementations of support for JUnit.
53
 * It declares methods for:
54
 * <ul>
55
 *     <li>navigation between source classes and corresponding test classes
56
 *         ({@link #getTestLocation getTestLocation},
57
 *          {@link #getTestedLocation getTestedLocation})</li>
58
 *     <li>creation of test class skeletons
59
 *         ({@link #createTests createTests})</li>
60
 * </ul>
61
 *
62
 * @author  Marian Petras
63
 */
64
public abstract class CommonPlugin {
65
    
66
    /**
67
     * Default constructor for use by subclasses.
68
     */
69
    protected CommonPlugin() {}
70
71
    /**
72
     * Enumeration of test creation parameters.
73
     */
74
    public enum CreateTestParam {
75
        
76
        /**
77
         * key for the map of test creation parameters
78
         * - name of the test class
79
         */
80
        CLASS_NAME(99310),
81
        /**
82
         * key for the map of test creation parameters
83
         * - include tests for public methods?
84
         */
85
        INC_PUBLIC(99311),
86
        /**
87
         * key for the map of test creation parameters
88
         * - include tests for protected methods?
89
         */
90
        INC_PROTECTED(99312),
91
        /**
92
         * key for the map of test creation parameters
93
         * - include tests for package-private methods?
94
         */
95
        INC_PKG_PRIVATE(99313),
96
        /**
97
         * key for the map of test creation parameters
98
         * - generate test initializer method ({@code setup()}/{@code @Before})?
99
         */
100
        INC_SETUP(99314),
101
        /**
102
         * key for the map of test creation parameters
103
         * - generate test finalizer method ({@code tearDown()}/{@code @After})?
104
         */
105
        INC_TEAR_DOWN(99315),
106
        /**
107
         * key for the map of test creation parameters
108
         * - generate test class initializer method ({@code @BeforeClass})?
109
         */
110
        INC_CLASS_SETUP(99323),
111
        /**
112
         * key for the map of test creation parameters
113
         * - generate test class finalizer method ({@code @AfterClass})?
114
         */
115
        INC_CLASS_TEAR_DOWN(99324),
116
        /**
117
         * key for the map of test creation parameters
118
         * - generate default test method bodies?
119
         */
120
        INC_METHOD_BODIES(99316),
121
        /**
122
         * key for the map of test creation parameters
123
         * - generate Javadoc comments for test methods?
124
         */
125
        INC_JAVADOC(99317),
126
        /**
127
         * key for the map of test creation parameters
128
         * - generate source code hints?
129
         */
130
        INC_CODE_HINT(99318),
131
        /**
132
         * key for the map of test creation parameters
133
         * - generate test classes for package-private classes?
134
         */
135
        INC_PKG_PRIVATE_CLASS(99319),
136
        /**
137
         * key for the map of test creation parameters
138
         * - generate test classes for abstract classes?
139
         */
140
        INC_ABSTRACT_CLASS(99320),
141
        /**
142
         * key for the map of test creation parameters
143
         * - generate test classes for exception classes?
144
         */
145
        INC_EXCEPTION_CLASS(99321),
146
        /**
147
         * key for the map of test creation parameters
148
         * - generate test suites for packages?
149
         */
150
        INC_GENERATE_SUITE(99322);
151
        
152
        private final int idNumber;
153
        
154
        CreateTestParam(int idNumber) {
155
            this.idNumber = idNumber;
156
        }
157
        
158
        /**
159
         * Return a unique number of this enum element.
160
         *
161
         * @return  unique number of this enum element
162
         */
163
        public int getIdNumber() {
164
            return idNumber;
165
        }
166
        
167
    }
168
    
169
    /**
170
     * Data structure for storage of specification of a Java element or
171
     * a Java file.
172
     */
173
    public static final class Location {
174
        //** */
175
        //public static final Set<ElementKind> CLASS_LIKE_ELEM_TYPES;
176
        //** */
177
        //public static final Set<ElementKind> SUPPORTED_ELEM_TYPES;
178
        /**
179
         * holds specification of a Java file
180
         */
181
        private final FileObject fileObject;
182
//        /**
183
//         */
184
//        private final ElementHandle<Element> elementHandle;
185
//        
186
//        static {
187
//            CLASS_LIKE_ELEM_TYPES = EnumSet.of(ElementKind.CLASS,
188
//                                               ElementKind.INTERFACE,
189
//                                               ElementKind.ENUM);
190
//            EnumSet<ElementKind> elemTypes;
191
//            elemTypes = EnumSet.copyOf(CLASS_LIKE_ELEM_TYPES);
192
//            elemTypes.addAll(EnumSet.of(ElementKind.METHOD,
193
//                                        ElementKind.CONSTRUCTOR,
194
//                                        ElementKind.STATIC_INIT));
195
//            SUPPORTED_ELEM_TYPES = Collections.unmodifiableSet(elemTypes);
196
//        }
197
        
198
        /**
199
         * Creates a new instance.
200
         *
201
         * @param  fileObject  the {@code FileObject}
202
         * 
203
         * 
204
         * 
205
         */
206
        public Location(FileObject fileObject/*,
207
                        Element element*/) {
208
            if (fileObject == null) {
209
               throw new IllegalArgumentException("fileObject is null");//NOI18N
210
            }
211
            
212
//            while ((element != null)
213
//                    && !SUPPORTED_ELEM_TYPES.contains(element.getKind())) {
214
//                element = element.getEnclosingElement();
215
//            }
216
            
217
            this.fileObject = fileObject;
218
            //this.elementHandle = (element != null)
219
            //                     ? ElementHandle.create(element)
220
            //                     : null;
221
        }
222
        
223
        /**
224
         * Returns the {@code FileObject}.
225
         *
226
         * @return  the {@code FileObject} held in this instance
227
         */
228
        public FileObject getFileObject() {
229
            return fileObject;
230
        }
231
        
232
//        /**
233
//         */
234
//        public ElementHandle<Element> getElementHandle() {
235
//            return elementHandle;
236
//        }
237
        
238
    }
239
    
240
    /**
241
     * Returns a specification of a Java element or file representing test
242
     * for the given source Java element or file.
243
     *
244
     * @param  sourceLocation  specification of a Java element or file
245
     * @return  specification of a corresponding test Java element or file,
246
     *          or {@code null} if no corresponding test Java file is available
247
     */
248
    protected abstract Location getTestLocation(Location sourceLocation);
249
    
250
    /**
251
     * Returns a specification of a Java element or file that is tested
252
     * by the given test Java element or test file.
253
     *
254
     * @param  testLocation  specification of a Java element or file
255
     * @return  specification of a Java element or file that is tested
256
     *          by the given Java element or file.
257
     */
258
    protected abstract Location getTestedLocation(Location testLocation);
259
    
260
    /**
261
     * Informs whether the plugin is capable of creating tests at the moment.
262
     * The default implementation returns {@code true}.
263
     *
264
     * @return  {@code true} if the plugin is able of creating tests
265
     *          for the given {@code FileObject}s, {@code false} otherwise
266
     * @see  #createTests
267
     */
268
    protected boolean canCreateTests(FileObject... fileObjects) {
269
        return true;
270
    }
271
    
272
    /**
273
     * Creates test classes for given source classes.
274
     * If the plugin does not support creating tests, implementation of this
275
     * method should return {@code null}.
276
     *
277
     * @param  filesToTest  source files for which test classes should be
278
     *                      created
279
     * @param  targetRoot   root folder of the target source root
280
     * @param  params  parameters of creating test class
281
     *                 - each key is an {@code Integer} whose value is equal
282
     *                 to some of the constants defined in the class;
283
     *                 the value is either
284
     *                 a {@code String} (for key with value {@code CLASS_NAME})
285
     *                 or a {@code Boolean} (for other keys)
286
     * @return  created test files, or {@code null} if no test classes were
287
     *          created and/or updated
288
     * @see  #canCreateTests
289
     */
290
    protected abstract FileObject[] createTests(
291
            FileObject[] filesToTest,
292
            FileObject targetRoot,
293
            Map<CreateTestParam, Object> params);
294
295
//    /**
296
//     * Determines whether the &quot;create JUnit tests&quot; functionality
297
//     * should be enabled.
298
//     * Before this method is called, other common pre-requisites are checked
299
//     * (only Java classes or folders selected, all of them from the same source
300
//     * of a Java project, all of them being valid {@code DataObject}s).
301
//     * If some of the pre-requisites are not met, the functionality is disabled
302
//     * and this method is not called.
303
//     *
304
//     * @return  {@code true} if this action should be enabled,
305
//     *          {@code false} otherwise;
306
//     *          the default implementation returns always {@code true}
307
//     */
308
//    protected boolean canCreateTests() {
309
//        return true;
310
//    }
311
312
    /**
313
     * Called immediately after the <em>Create Test</em> action was called.
314
     * It can be used as a trigger for additional checks and/or for displaying
315
     * user dialogs etc. It is always called from the event-dispatching thread.
316
     *
317
     * @param  selectedFiles  files and folders/packages that were selected
318
     *                        when the action was called
319
     * @return  {@code true} if the action can continue,
320
     *          {@code false} if the action should not continue;
321
     *          the default implementation returns always {@code true}
322
     */
323
    protected boolean createTestActionCalled(FileObject[] selectedFiles) {
324
        // assert EventQueue.isDispatchThread(); #170707
325
326
        return true;
327
    }
328
329
}
(-)a/junit/test/unit/src/org/netbeans/modules/junit/ClassNameTextFieldTest.java (-12 / +8 lines)
Lines 1-7 Link Here
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
7
 * Other names may be trademarks of their respective owners.
Lines 24-35 Link Here
24
 * your own identifying information:
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 2005 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
27
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
28
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
29
 * "[Contributor] elects to include this software in this distribution
Lines 40-57 Link Here
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
35
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
43
 */
41
 */
44
42
package org.netbeans.modules.gsf.testrunner;
45
package org.netbeans.modules.junit;
46
43
47
import junit.framework.TestCase;
44
import junit.framework.TestCase;
48
45
49
/**
46
/**
50
 *
47
 *
51
 * @author  Marian Petras
48
 * @author theofanis
52
 */
49
 */
53
public class ClassNameTextFieldTest extends TestCase {
50
public class ClassNameTextFieldTest extends TestCase {
54
51
    
55
    public ClassNameTextFieldTest(String testName) {
52
    public ClassNameTextFieldTest(String testName) {
56
        super(testName);
53
        super(testName);
57
    }
54
    }
Lines 153-157 Link Here
153
                    new ClassNameTextField(testData[i].str).getStatus());
150
                    new ClassNameTextField(testData[i].str).getStatus());
154
        }
151
        }
155
    }
152
    }
156
157
}
153
}
(-)a/junit/test/unit/src/org/netbeans/modules/junit/MessageStackTest.java (-11 / +9 lines)
Lines 1-7 Link Here
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
7
 * Other names may be trademarks of their respective owners.
Lines 24-35 Link Here
24
 * your own identifying information:
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 2005 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
27
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
28
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
29
 * "[Contributor] elects to include this software in this distribution
Lines 40-55 Link Here
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
35
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
43
 */
41
 */
44
42
package org.netbeans.modules.gsf.testrunner;
45
package org.netbeans.modules.junit;
46
43
47
import junit.framework.TestCase;
44
import junit.framework.TestCase;
45
import org.junit.*;
46
import static org.junit.Assert.*;
48
47
49
/**
48
/**
50
 * Test of class <code>MessageStack</code>.
49
 * Test of class <code>MessageStack</code>.
51
 *
50
 *
52
 * @author Marian Petras
51
 * @author theofanis
53
 */
52
 */
54
public class MessageStackTest extends TestCase {
53
public class MessageStackTest extends TestCase {
55
54
Lines 326-330 Link Here
326
                return "ERROR IN TEST CODE";
325
                return "ERROR IN TEST CODE";
327
        }
326
        }
328
    }
327
    }
329
    
330
}
328
}
(-)a/junit/src/org/netbeans/modules/junit/CreateTestAction.java (-456 lines)
Lines 1-456 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.junit;
46
47
import java.awt.EventQueue;
48
import java.io.IOException;
49
import java.util.ArrayList;
50
import java.util.Collection;
51
import java.util.List;
52
import java.util.Map;
53
import javax.swing.Action;
54
import org.netbeans.api.java.classpath.ClassPath;
55
import org.netbeans.api.project.FileOwnerQuery;
56
import org.netbeans.api.project.Project;
57
import org.netbeans.api.project.SourceGroup;
58
import org.netbeans.modules.junit.plugin.JUnitPlugin;
59
import org.netbeans.modules.junit.plugin.JUnitPlugin.CreateTestParam;
60
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
61
import org.openide.DialogDisplayer;
62
import org.openide.NotifyDescriptor;
63
import org.openide.filesystems.FileObject;
64
import org.openide.loaders.DataObject;
65
import org.openide.loaders.DataObjectNotFoundException;
66
import org.openide.nodes.Node;
67
import org.openide.util.Exceptions;
68
import org.openide.util.HelpCtx;
69
import org.openide.util.NbBundle;
70
import org.openide.cookies.EditorCookie;
71
import org.openide.cookies.SaveCookie;
72
import org.openide.loaders.DataFolder;
73
import org.openide.util.RequestProcessor;
74
75
/** Action sensitive to some cookie that does something useful.
76
 *
77
 * @author  vstejskal, David Konecny
78
 * @author  Marian Petras
79
 * @author  Ondrej Rypacek
80
 */
81
public final class CreateTestAction extends TestAction {
82
        
83
    public CreateTestAction() {
84
        putValue("noIconInMenu", Boolean.TRUE);                         //NOI18N
85
    }
86
87
    /* public members */
88
89
    @Override
90
    public String getName() {
91
        return NbBundle.getMessage(CreateTestAction.class,
92
                                   "LBL_Action_CreateTest");            //NOI18N
93
    }
94
95
    @Override
96
    public HelpCtx getHelpCtx() {
97
        return new HelpCtx(CreateTestAction.class);
98
    }
99
100
    @Override
101
    protected void initialize() {
102
        super.initialize();
103
        putProperty(Action.SHORT_DESCRIPTION,
104
                    NbBundle.getMessage(CreateTestAction.class,
105
                                        "HINT_Action_CreateTest"));     //NOI18N
106
    }
107
108
    @Override
109
    protected String iconResource() {
110
        return "org/netbeans/modules/junit/resources/"                  //NOI18N
111
               + "CreateTestActionIcon.gif";                            //NOI18N
112
    }
113
114
    @Override
115
    protected boolean enable(Node[] nodes) {
116
        if (nodes.length == 0) {
117
            return false;
118
        }
119
120
        /*
121
         * In most cases, there is just one node selected - that is why
122
         * this case is handled in a special, more effective way
123
         * (no collections and iterators created).
124
         */
125
        if (nodes.length == 1) {
126
            final Node node = nodes[0];
127
            DataObject dataObj;
128
            FileObject fileObj;
129
            Project project;
130
            if (((dataObj = node.getCookie(DataObject.class)) != null)
131
                && ((fileObj = dataObj.getPrimaryFile()) != null)
132
                && fileObj.isValid()
133
                && ((project = FileOwnerQuery.getOwner(fileObj)) != null)
134
                && (getSourceGroup(fileObj, project) != null)
135
                && (TestUtil.isJavaFile(fileObj)
136
                    || (node.getCookie(DataFolder.class) != null))) {
137
138
                JUnitPlugin plugin = TestUtil.getPluginForProject(project);
139
                return JUnitPluginTrampoline.DEFAULT.canCreateTests(plugin,
140
                                                                    fileObj);
141
            } else {
142
                return false;
143
            }
144
        }
145
146
        final Collection<FileObject> fileObjs
147
                = new ArrayList<FileObject>(nodes.length);
148
        Project theProject = null;
149
        boolean result = false;
150
        for (Node node : nodes) {
151
            DataObject dataObj = node.getCookie(DataObject.class);
152
            if (dataObj != null) {
153
                FileObject fileObj = dataObj.getPrimaryFile();
154
                if ((fileObj == null) || !fileObj.isValid()) {
155
                    continue;
156
                }
157
158
                fileObjs.add(fileObj);
159
                
160
                Project prj = FileOwnerQuery.getOwner(fileObj);
161
                if (prj != null) {
162
                    if (theProject == null) {
163
                        theProject = prj;
164
                    }
165
                    if (prj != theProject) {
166
                        return false;        /* files from different projects */
167
                    }
168
169
                    if ((getSourceGroup(fileObj, prj) != null)
170
                        && (TestUtil.isJavaFile(fileObj)
171
                            || (node.getCookie(DataFolder.class) != null))) {
172
                        result = true;
173
                    }
174
                }
175
            }
176
        }
177
178
        if (theProject != null) {
179
            JUnitPlugin plugin = TestUtil.getPluginForProject(theProject);
180
            result &= JUnitPluginTrampoline.DEFAULT.canCreateTests(
181
                            plugin,
182
                            fileObjs.toArray(new FileObject[fileObjs.size()]));
183
        }
184
185
        return result;
186
    }
187
188
    /**
189
     * Checks that the selection of nodes the dialog is invoked on is valid. 
190
     * @return String message describing the problem found or null, if the
191
     *         selection is ok
192
     */
193
    private static String checkNodesValidity(Node[] nodes) {
194
        FileObject[] files = getFiles(nodes);
195
196
        Project project = getProject(files);
197
        if (project == null) {
198
            return NbBundle.getMessage(CreateTestAction.class,
199
                                       "MSG_multiproject_selection");   //NOI18N
200
        }
201
202
        if (!checkPackages(files)) {
203
            return NbBundle.getMessage(CreateTestAction.class,
204
                                       "MSG_invalid_packages");         //NOI18N
205
        }
206
207
        return null;
208
    }
209
210
    /**
211
     * Check that all the files (folders or java files) have correct java
212
     * package names.
213
     * @return true if all are fine
214
     */
215
    private static boolean checkPackages(FileObject[] files) {
216
        if (files.length == 0) {
217
            return true;
218
        } else {
219
            Project project = FileOwnerQuery.getOwner(files[0]);
220
            for (int i = 0 ; i < files.length; i++) {
221
                String packageName = getPackage(project, files[i]);
222
                if ((packageName == null)
223
                        || !TestUtil.isValidPackageName(packageName)) {
224
                    return false;
225
                }
226
            }
227
            return true;
228
        }
229
    }
230
231
    /**
232
     * Get the package name of <code>file</code>.
233
     *
234
     * @param project owner of the file (for performance reasons)
235
     * @param file the FileObject whose packagename to get
236
     * @return package name of the file or null if it cannot be retrieved
237
     */
238
    private static String getPackage(Project project, FileObject file) {
239
        SourceGroup srcGrp = TestUtil.findSourceGroupOwner(project, file);
240
        if (srcGrp!= null) {
241
            ClassPath cp = ClassPathSupport.createClassPath(
242
                    new FileObject [] {srcGrp.getRootFolder()});
243
            return cp.getResourceName(file, '.', false);
244
        } else {
245
            return null;
246
        }
247
    }
248
249
250
    private static FileObject[] getFiles(Node[] nodes) {
251
        FileObject[] ret = new FileObject[nodes.length];
252
        for (int i = 0 ; i < nodes.length ; i++) {
253
            ret[i]  = TestUtil.getFileObjectFromNode(nodes[i]);
254
        }
255
        return ret;
256
    }
257
258
    /**
259
     * Get the single project for <code>nodes</code> if there is such.
260
     * If the nodes belong to different projects or some of the nodes doesn't
261
     * have a project, return null.
262
     */
263
    private static Project getProject(FileObject[] files) {
264
        Project project = null;
265
        for (int i = 0 ; i < files.length; i++) {
266
            Project nodeProject = FileOwnerQuery.getOwner(files[i]);
267
            if (project == null) {
268
                project = nodeProject;
269
            } else if (project != nodeProject) {
270
                return null;
271
            }
272
        }
273
        return project;
274
    }
275
276
    @Override
277
    protected void performAction(Node[] nodes) {
278
        String problem;
279
        if ((problem = checkNodesValidity(nodes)) != null) {
280
            // TODO report problem
281
            NotifyDescriptor msg = new NotifyDescriptor.Message(
282
                                problem, NotifyDescriptor.WARNING_MESSAGE);
283
            DialogDisplayer.getDefault().notify(msg);
284
            return;
285
        } 
286
287
        final FileObject[] filesToTest = getFileObjectsFromNodes(nodes);
288
        if (filesToTest == null) {
289
            return;     //XXX: display some message
290
        }
291
292
        /* Determine the plugin to be used: */
293
        final JUnitPlugin plugin = TestUtil.getPluginForProject(
294
                FileOwnerQuery.getOwner(filesToTest[0]));
295
296
        if (!JUnitPluginTrampoline.DEFAULT.createTestActionCalled(
297
                                                        plugin, filesToTest)) {
298
            return;
299
        }
300
301
        final DataObject[] modified = DataObject.getRegistry().getModified();
302
303
        // show configuration dialog
304
        // when dialog is canceled, escape the action
305
        JUnitCfgOfCreate cfg = new JUnitCfgOfCreate(nodes, 
306
                                            modified.length == 0 ? false: true);
307
        if (!cfg.configure()) {
308
            return;
309
        }
310
311
        saveAll(modified); // #149048
312
313
        /* Store the configuration data: */
314
        final boolean singleClass = cfg.isSingleClass();
315
        final Map<CreateTestParam, Object> params
316
                = TestUtil.getSettingsMap(!singleClass);
317
        if (singleClass) {
318
            params.put(CreateTestParam.CLASS_NAME, cfg.getTestClassName());
319
        }
320
        final FileObject targetFolder = cfg.getTargetFolder();
321
        cfg = null;
322
323
        RequestProcessor.getDefault().post(new Runnable() {
324
                @Override
325
                public void run() {
326
                    /* Now create the tests: */
327
                    final FileObject[] testFileObjects
328
                            = JUnitPluginTrampoline.DEFAULT.createTests(
329
                                    plugin,
330
                                    filesToTest,
331
                                    targetFolder,
332
                                    params);
333
334
                    /* Open the created/updated test class if appropriate: */
335
                    if (testFileObjects.length == 1) {
336
                        try {
337
                            DataObject dobj = DataObject.find(testFileObjects[0]);
338
                            final EditorCookie ec = dobj.getCookie(EditorCookie.class);
339
                            if (ec != null) {
340
                                EventQueue.invokeLater(new Runnable() {
341
                                        @Override
342
                                        public void run() {
343
                                            ec.open();
344
                                        }
345
                                });
346
                            }
347
                        } catch (DataObjectNotFoundException ex) {
348
                            ex.printStackTrace();
349
                        }
350
                    }
351
                }});
352
    }
353
354
    /**
355
     * Extracts {@code FileObject}s from the given nodes.
356
     * Nodes that have (direct or indirect) parent nodes among the given
357
     * nodes are ignored.
358
     *
359
     * @return  a non-empty array of {@code FileObject}s
360
     *          represented by the given nodes;
361
     *          or {@code null} if no {@code FileObject} was found;
362
     */
363
    private static FileObject[] getFileObjectsFromNodes(final Node[] nodes){
364
        FileObject[] fileObjects = new FileObject[nodes.length];
365
        List<FileObject> fileObjectsList = null;
366
367
        for (int i = 0; i < nodes.length; i++) {
368
            final Node node = nodes[i];
369
            final FileObject fo;
370
            if (!hasParentAmongNodes(nodes, i)
371
                    && ((fo = getTestFileObject(node)) != null)) {
372
                if (fileObjects != null) {
373
                    fileObjects[i] = fo;
374
                } else {
375
                    if (fileObjectsList == null) {
376
                        fileObjectsList = new ArrayList<FileObject>(
377
                                                        nodes.length - i);
378
                    }
379
                    fileObjectsList.add(fo);
380
                }
381
            } else {
382
                fileObjects = null;     //signs that some FOs were skipped
383
            }
384
        }
385
        if (fileObjects == null) {
386
            if (fileObjectsList != null) {
387
                fileObjects = fileObjectsList.toArray(
388
                        new FileObject[fileObjectsList.size()]);
389
                fileObjectsList = null;
390
            }
391
        }
392
393
        return fileObjects;
394
    }
395
396
    /**
397
     * Grabs and checks a <code>FileObject</code> from the given node.
398
     * If either the file could not be grabbed or the file does not pertain
399
     * to any project, a message is displayed.
400
     *
401
     * @param  node  node to get a <code>FileObject</code> from.
402
     * @return  the grabbed <code>FileObject</code>,
403
     *          or <code>null</code> in case of failure
404
     */
405
    private static FileObject getTestFileObject(final Node node) {
406
        final FileObject fo = TestUtil.getFileObjectFromNode(node);
407
        if (fo == null) {
408
            TestUtil.notifyUser(NbBundle.getMessage(
409
                    CreateTestAction.class,
410
                    "MSG_file_from_node_failed"));                      //NOI18N
411
            return null;
412
        }
413
        ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
414
        if (cp == null) {
415
            TestUtil.notifyUser(NbBundle.getMessage(
416
                    CreateTestAction.class,
417
                    "MSG_no_project",                                   //NOI18N
418
                    fo));
419
            return null;
420
        }
421
        return fo;
422
    }
423
424
    private static boolean hasParentAmongNodes(final Node[] nodes,
425
                                               final int idx) {
426
        Node node;
427
428
        node = nodes[idx].getParentNode();
429
        while (null != node) {
430
            for (int i = 0; i < nodes.length; i++) {
431
                if (i == idx) {
432
                    continue;
433
                }
434
                if (node == nodes[i]) {
435
                    return true;
436
                }
437
            }
438
            node = node.getParentNode();
439
        }
440
        return false;
441
    }
442
443
    private void saveAll(DataObject[] dataObjects) {
444
        for(DataObject dataObject: dataObjects) {
445
            SaveCookie saveCookie = dataObject.getCookie(SaveCookie.class);
446
            if(saveCookie != null) {
447
                try {
448
                    saveCookie.save();
449
                } catch (IOException ex) {
450
                    Exceptions.printStackTrace(ex);
451
                }
452
            }
453
        }
454
    }
455
456
}
(-)a/junit/src/org/netbeans/modules/junit/JUnitCfgOfCreate.java (-1128 lines)
Lines 1-1128 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 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
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.junit;
46
47
import java.awt.BorderLayout;
48
import java.awt.Color;
49
import java.awt.Component;
50
import java.awt.Container;
51
import java.awt.Font;
52
import java.awt.GridBagConstraints;
53
import java.awt.GridBagLayout;
54
import java.awt.Insets;
55
import java.awt.event.ActionListener;
56
import java.awt.event.ItemEvent;
57
import java.awt.event.ItemListener;
58
import java.util.ArrayList;
59
import java.util.Iterator;
60
import java.util.List;
61
import java.util.ResourceBundle;
62
import java.util.Stack;
63
import javax.swing.BorderFactory;
64
import javax.swing.Box;
65
import javax.swing.BoxLayout;
66
import javax.swing.DefaultComboBoxModel;
67
import javax.swing.JButton;
68
import javax.swing.JCheckBox;
69
import javax.swing.JComboBox;
70
import javax.swing.JComponent;
71
import javax.swing.JLabel;
72
import javax.swing.JList;
73
import javax.swing.JPanel;
74
import javax.swing.ListCellRenderer;
75
import javax.swing.UIManager;
76
import javax.swing.border.Border;
77
import javax.swing.border.CompoundBorder;
78
import javax.swing.border.TitledBorder;
79
import javax.swing.event.ChangeEvent;
80
import javax.swing.event.ChangeListener;
81
import javax.swing.plaf.UIResource;
82
import javax.swing.text.JTextComponent;
83
import org.netbeans.api.java.classpath.ClassPath;
84
import org.netbeans.api.java.project.JavaProjectConstants;
85
import org.netbeans.api.project.FileOwnerQuery;
86
import org.netbeans.api.project.Project;
87
import org.netbeans.api.project.SourceGroup;
88
import org.netbeans.api.project.SourceGroupModifier;
89
import org.openide.DialogDescriptor;
90
import org.openide.DialogDisplayer;
91
import org.openide.awt.Mnemonics;
92
import org.openide.filesystems.FileObject;
93
import org.openide.filesystems.FileUtil;
94
import org.openide.loaders.DataFolder;
95
import org.openide.loaders.DataObject;
96
import org.openide.nodes.Node;
97
import org.openide.util.HelpCtx;
98
import org.openide.util.Lookup;
99
import org.openide.util.NbBundle;
100
101
102
/**
103
 *
104
 * @author  vstejskal
105
 * @author  Marian Petras
106
 */
107
@SuppressWarnings("serial")
108
public final class JUnitCfgOfCreate extends SelfResizingPanel
109
                                    implements ChangeListener {
110
    
111
    /** suffix of test classes */
112
    private static final String TEST_CLASS_SUFFIX = "Test";             //NOI18N
113
    
114
    /**
115
     * nodes selected when the Create Tests action was invoked
116
     */
117
    private final Node[] nodes;
118
    /** whether the tests will be created for multiple classes */
119
    private final boolean multipleClasses;
120
    /** whether a single package/folder is selected */
121
    private boolean singlePackage;
122
    /** whether a single class is selected */
123
    private boolean singleClass;
124
    /** test class name specified in the form (or <code>null</code>) */
125
    private String testClassName;
126
    /** registered change listeners */
127
    private List<ChangeListener> changeListeners;
128
    /** */
129
    private String initialMessage;
130
    
131
    /**
132
     * is at least one target folder/source group available?
133
     *
134
     * @see  #isAcceptable()
135
     */
136
    private boolean hasTargetFolders = false;
137
138
    /**
139
     * is the entered class name non-empty and valid?
140
     *
141
     * @see  #isAcceptable()
142
     */
143
    private boolean classNameValid;
144
    
145
    /**
146
     * is the current form contents acceptable?
147
     *
148
     * @see  #isAcceptable()
149
     */
150
    private boolean isAcceptable;
151
    
152
    /** layer index for a message about an empty set of target folders */
153
    private static final int MSG_TYPE_NO_TARGET_FOLDERS = 0;
154
    /** layer index for a message about invalid class name */
155
    private static final int MSG_TYPE_CLASSNAME_INVALID = 1;
156
    /** layer index for a message about non-default class name */
157
    private static final int MSG_TYPE_CLASSNAME_NOT_DEFAULT = 2;
158
    /** layer index for a message about modified files */
159
    private static final int MSG_TYPE_MODIFIED_FILES = 3;
160
    /** */
161
    private MessageStack msgStack = new MessageStack(4);
162
163
    /**
164
     * Creates a JUnit configuration panel.
165
     *
166
     * @param nodes  nodes selected when the Create Tests action was invoked
167
     * @param isShowMsgFilesWillBeSaved if {@code true} then a warning message
168
     *        like "Warning: All modified files will be saved." will be
169
     *        displayed on the panel, otherwise (i.e. if {@code false}) then
170
     *        the message won't be displayed.
171
     */
172
    JUnitCfgOfCreate(Node[] nodes, boolean isShowMsgFilesWillBeSaved) {
173
        assert (nodes != null) && (nodes.length != 0);
174
        
175
        this.nodes = nodes;
176
        multipleClasses = checkMultipleClasses();
177
        
178
        initBundle();
179
        try {
180
            initComponents();
181
            if(isShowMsgFilesWillBeSaved) {
182
                String msg = bundle.getString("MSG_MODIFIED_FILES"); // NOI18N
183
                setMessage(msg, MSG_TYPE_MODIFIED_FILES);
184
            }
185
            setBorder(BorderFactory.createEmptyBorder(12, 12, 0, 11));
186
            addAccessibleDescriptions();
187
            initializeCheckBoxStates();
188
            fillFormData();
189
            checkAcceptability();
190
            setupUserInteraction();
191
            
192
            /*
193
             * checkAcceptability() must not be called
194
             *        before initializeCheckBoxStates() and fillFormData()
195
             * setupUserInteraction must not be called
196
             *        before initializeCheckBoxStates()
197
             */
198
            
199
        } finally {
200
            unlinkBundle();
201
        }
202
    }
203
    
204
    private void addAccessibleDescriptions() {
205
        
206
        // window
207
        this.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.AD"));
208
        
209
        // text-field and combo-box
210
        
211
        if (this.tfClassName != null) {
212
            this.tfClassName.setToolTipText(
213
                  bundle.getString("JUnitCfgOfCreate.clsName.toolTip"));//NOI18N
214
            this.tfClassName.getAccessibleContext().setAccessibleName(
215
                  bundle.getString("JUnitCfgOfCreate.clsName.AN"));     //NOI18N
216
            this.tfClassName.getAccessibleContext().setAccessibleDescription(
217
                  bundle.getString("JUnitCfgOfCreate.clsName.AD"));     //NOI18N
218
        }
219
        
220
        this.cboxLocation.setToolTipText(
221
                bundle.getString("JUnitCfgOfCreate.location.toolTip")); //NOI18N
222
        this.cboxLocation.getAccessibleContext().setAccessibleName(
223
                bundle.getString("JUnitCfgOfCreate.location.AN"));      //NOI18N
224
        this.cboxLocation.getAccessibleContext().setAccessibleDescription(
225
                bundle.getString("JUnitCfgOfCreate.location.AD"));      //NOI18N
226
        
227
        // check boxes
228
        this.chkPublic.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkPublic.toolTip"));
229
        this.chkPublic.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkPublic.AD"));        
230
        
231
        this.chkProtected.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkProtected.toolTip"));
232
        this.chkProtected.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkProtected.AD"));        
233
        
234
        this.chkPackage.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkPackage.toolTip"));
235
        this.chkPackage.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkPackage.AD"));
236
        
237
        this.chkComments.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkComments.toolTip"));        
238
        this.chkComments.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkComments.AD"));
239
        
240
        this.chkContent.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkContent.toolTip"));
241
        this.chkContent.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkContent.AD"));
242
        
243
        this.chkJavaDoc.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkJavaDoc.toolTip"));
244
        this.chkJavaDoc.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkJavaDoc.AD"));
245
        
246
        if (multipleClasses) {
247
            this.chkExceptions.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkExceptions.toolTip"));
248
            this.chkExceptions.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkExceptions.AD"));
249
        
250
            this.chkAbstractImpl.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkAbstractImpl.toolTip"));
251
            this.chkAbstractImpl.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkAbstractImpl.AD"));
252
        
253
            this.chkPackagePrivateClasses.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkPackagePrivateClasses.toolTip"));
254
            this.chkPackagePrivateClasses.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkPackagePrivateClasses.AD"));
255
        
256
            this.chkGenerateSuites.setToolTipText(bundle.getString("JUnitCfgOfCreate.chkGenerateSuites.toolTip"));
257
            this.chkGenerateSuites.getAccessibleContext().setAccessibleDescription(bundle.getString("JUnitCfgOfCreate.chkGenerateSuites.AD"));
258
        }
259
        
260
    }
261
    
262
    /**
263
     * Checks whether multiple classes may be selected.
264
     * It also detects whether exactly one package/folder or exactly one class
265
     * is selected and sets values of variables {@link #singlePackage}
266
     * and {@link #singleClass} accordingly.
267
     *
268
     * @return  <code>false</code> if there is exactly one node selected
269
     *          and the node represents a single <code>DataObject</code>,
270
     *          not a folder or another <code>DataObject</code> container;
271
     *          <code>true</code> otherwise
272
     */
273
    private boolean checkMultipleClasses() {
274
        if (nodes.length > 1) {
275
            return true;
276
        }
277
        
278
        Lookup nodeLookup = nodes[0].getLookup();
279
        if (nodeLookup.lookup(DataObject.Container.class) != null) {
280
            singlePackage = nodeLookup.lookup(DataFolder.class)
281
                            != null;
282
            return true;
283
        }
284
        
285
        singleClass = false;
286
        DataObject dataObj = nodeLookup.lookup(DataObject.class);
287
        if (dataObj == null) {
288
            return true;
289
        }
290
        
291
        singleClass = dataObj.getPrimaryFile().isData();
292
        return !singleClass;
293
    }
294
    
295
    /**
296
     * Displays a configuration dialog and updates JUnit options according
297
     * to the user's settings.
298
     *
299
     * @param  nodes  nodes selected when the Create Test action was invoked
300
     */
301
    boolean configure() {
302
        
303
        // create and display the dialog:
304
        String title = NbBundle.getMessage(JUnitCfgOfCreate.class,
305
                                           "JUnitCfgOfCreate.Title");   //NOI18N
306
        ChangeListener changeListener;
307
        final JButton btnOK = new JButton(
308
                NbBundle.getMessage(JUnitCfgOfCreate.class, "LBL_OK")); //NOI18N
309
        btnOK.getAccessibleContext().setAccessibleName(NbBundle.getMessage(JUnitCfgOfCreate.class, "AN_OK"));
310
        btnOK.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(JUnitCfgOfCreate.class, "AD_OK"));
311
        btnOK.setEnabled(isAcceptable());
312
        addChangeListener(changeListener = new ChangeListener() {
313
            @Override
314
            public void stateChanged(ChangeEvent e) {
315
                btnOK.setEnabled(isAcceptable());
316
            }
317
        });
318
        
319
        Object returned = DialogDisplayer.getDefault().notify(
320
                new DialogDescriptor (
321
                        this,
322
                        title,
323
                        true,                       //modal
324
                        new Object[] {btnOK, DialogDescriptor.CANCEL_OPTION},
325
                        btnOK,                      //initial value
326
                        DialogDescriptor.DEFAULT_ALIGN,
327
                        new HelpCtx(JUnitCfgOfCreate.class),
328
                        (ActionListener) null
329
                ));
330
        removeChangeListener(changeListener);
331
        
332
        if (returned == btnOK) {
333
            rememberCheckBoxStates();
334
            testClassName = (tfClassName != null) ? tfClassName.getText() 
335
                                                  : null;
336
            return true;
337
        }
338
        return false;
339
    }
340
    
341
    /**
342
     * Returns whether a test for a single class is to be created.
343
     *
344
     * @return  true if there is only one node selected and the node
345
     *          represents a class
346
     */
347
    boolean isSingleClass() {
348
        return singleClass;
349
    }
350
    
351
    /**
352
     * Returns the class name entered in the text-field.
353
     *
354
     * @return  class name entered in the form,
355
     *          or <code>null</code> if the form did not contain
356
     *          the field for entering class name
357
     */
358
    String getTestClassName() {
359
        return testClassName;
360
    }
361
    
362
    /** resource bundle used during initialization of this panel */
363
    public ResourceBundle bundle;
364
    
365
    /**
366
     * Reads JUnit settings and initializes checkboxes accordingly.
367
     *
368
     * @see  #rememberCheckBoxStates
369
     */
370
    private void initializeCheckBoxStates() {
371
        final JUnitSettings settings = JUnitSettings.getDefault();
372
        
373
        chkPublic.setSelected(settings.isMembersPublic());
374
        chkProtected.setSelected(settings.isMembersProtected());
375
        chkPackage.setSelected(settings.isMembersPackage());
376
        chkComments.setSelected(settings.isBodyComments());
377
        chkContent.setSelected(settings.isBodyContent());
378
        chkJavaDoc.setSelected(settings.isJavaDoc());        
379
        if (multipleClasses) {
380
            chkGenerateSuites.setSelected(settings.isGenerateSuiteClasses());        
381
            chkPackagePrivateClasses.setSelected(
382
                    settings.isIncludePackagePrivateClasses());
383
            chkAbstractImpl.setSelected(settings.isGenerateAbstractImpl());
384
            chkExceptions.setSelected(settings.isGenerateExceptionClasses());
385
        }
386
        chkSetUp.setSelected(settings.isGenerateSetUp());
387
        chkTearDown.setSelected(settings.isGenerateTearDown());
388
    }
389
    
390
    /**
391
     * Stores settings given by checkbox states to JUnit settings.
392
     *
393
     * @see  #initializeCheckBoxStatesf
394
     */
395
    private void rememberCheckBoxStates() {
396
        final JUnitSettings settings = JUnitSettings.getDefault();
397
        
398
        settings.setMembersPublic(chkPublic.isSelected());
399
        settings.setMembersProtected(chkProtected.isSelected());
400
        settings.setMembersPackage(chkPackage.isSelected());
401
        settings.setBodyComments(chkComments.isSelected());
402
        settings.setBodyContent(chkContent.isSelected());
403
        settings.setJavaDoc(chkJavaDoc.isSelected());
404
        if (multipleClasses) {
405
            settings.setGenerateSuiteClasses(chkGenerateSuites.isSelected());
406
            settings.setIncludePackagePrivateClasses(
407
                    chkPackagePrivateClasses.isSelected());
408
            settings.setGenerateAbstractImpl(chkAbstractImpl.isSelected());
409
            settings.setGenerateExceptionClasses(chkExceptions.isSelected());
410
        }
411
        settings.setGenerateSetUp(chkSetUp.isSelected());
412
        settings.setGenerateTearDown(chkTearDown.isSelected());
413
    }
414
    
415
    /**
416
     * Loads a resource bundle so that it can be used during intialization
417
     * of this panel.
418
     *
419
     * @see  #unlinkBundle
420
     */
421
    private void initBundle() {
422
        bundle = NbBundle.getBundle(JUnitCfgOfCreate.class);
423
    }
424
    
425
    /**
426
     * Nulls the resource bundle so that it is not held in memory when it is
427
     * not used.
428
     *
429
     * @see  #initBundle
430
     */
431
    private void unlinkBundle() {
432
        bundle = null;
433
    }
434
    
435
    /**
436
     * This method is called from within the constructor to initialize the form.
437
     */
438
    private void initComponents() {
439
        setLayout(new BorderLayout(0, 12));
440
        
441
        add(createNameAndLocationPanel(), BorderLayout.NORTH);
442
        add(createMessagePanel(), BorderLayout.CENTER);
443
        add(createCodeGenPanel(), BorderLayout.SOUTH);
444
    }
445
    
446
    /**
447
     */
448
    private void setupUserInteraction() {
449
        final ItemListener listener = new CheckBoxListener();
450
451
        chkPublic.addItemListener(listener);
452
        chkProtected.addItemListener(listener);
453
        chkPackage.addItemListener(listener);
454
    }
455
    
456
    /**
457
     * Listener object that listens on state changes of some check-boxes.
458
     */
459
    private final class CheckBoxListener implements ItemListener {
460
        public CheckBoxListener () {}
461
        
462
        @Override
463
        public void itemStateChanged(ItemEvent e) {
464
            final Object source = e.getSource();
465
            
466
            assert source == chkPublic
467
                   || source == chkProtected
468
                   || source == chkPackage;
469
            checkAcceptability();
470
        }
471
        
472
    }
473
    
474
    /**
475
     */
476
    private Component createNameAndLocationPanel() {
477
        JPanel panel = new JPanel();
478
        
479
        final boolean askForClassName = singleClass;
480
        
481
        JLabel lblClassToTest = new JLabel();
482
        JLabel lblClassName = askForClassName ? new JLabel() : null;
483
        JLabel lblLocation = new JLabel();
484
        
485
        String classToTestKey = singlePackage
486
                                ? "LBL_PackageToTest"                   //NOI18N
487
                                : singleClass
488
                                  ? "LBL_ClassToTest"                   //NOI18N
489
                                  : "LBL_MultipleClassesSelected";      //NOI18N
490
                                    
491
        Mnemonics.setLocalizedText(
492
                lblClassToTest,
493
                NbBundle.getMessage(getClass(), classToTestKey));
494
        if (askForClassName) {
495
            Mnemonics.setLocalizedText(
496
                    lblClassName,
497
                    NbBundle.getMessage(getClass(), "LBL_ClassName"));  //NOI18N
498
        }
499
        Mnemonics.setLocalizedText(
500
                lblLocation,
501
                NbBundle.getMessage(getClass(), "LBL_Location"));       //NOI18N
502
        
503
        if (singlePackage || singleClass) {
504
            lblClassToTestValue = new JLabel();
505
        }
506
        if (askForClassName) {
507
            tfClassName = new ClassNameTextField();
508
            tfClassName.setChangeListener(this);
509
        }
510
        cboxLocation = new JComboBox();
511
        
512
        if (askForClassName) {
513
            lblClassName.setLabelFor(tfClassName);
514
        }
515
        lblLocation.setLabelFor(cboxLocation);
516
        
517
        if (lblClassToTestValue != null) {
518
            Font labelFont = javax.swing.UIManager.getDefaults()
519
                             .getFont("TextField.font");                //NOI18N
520
            if (labelFont != null) {
521
                lblClassToTestValue.setFont(labelFont);
522
            }
523
        }
524
        
525
        panel.setLayout(new GridBagLayout());
526
        
527
        GridBagConstraints gbcLeft = new GridBagConstraints();
528
        gbcLeft.anchor = GridBagConstraints.WEST;
529
        gbcLeft.insets.bottom = 12;
530
        gbcLeft.insets.right = 6;
531
        
532
        GridBagConstraints gbcRight = new GridBagConstraints();
533
        gbcRight.anchor = GridBagConstraints.WEST;
534
        gbcRight.insets.bottom = 12;
535
        gbcRight.weightx = 1.0f;
536
        gbcRight.fill = GridBagConstraints.BOTH;
537
        gbcRight.gridwidth = GridBagConstraints.REMAINDER;
538
        
539
        if (lblClassToTestValue != null) {
540
            panel.add(lblClassToTest,      gbcLeft);
541
            panel.add(lblClassToTestValue, gbcRight);
542
        } else {
543
            panel.add(lblClassToTest,   gbcRight);
544
        }
545
        if (askForClassName) {
546
            panel.add(lblClassName,     gbcLeft);
547
            panel.add(tfClassName,      gbcRight);
548
        }
549
        gbcLeft.insets.bottom = 0;
550
        gbcRight.insets.bottom = 0;
551
        panel.add(lblLocation,      gbcLeft);
552
        panel.add(cboxLocation,     gbcRight);
553
        
554
        return panel;
555
    }
556
    
557
    /**
558
     */
559
    private void checkClassNameValidity() {
560
        if (tfClassName == null) {
561
            classNameValid = true;
562
            return;
563
        }
564
        
565
        String key = null;
566
        final int state = tfClassName.getStatus();
567
        switch (state) {
568
            case ClassNameTextField.STATUS_EMPTY:
569
                key = "MSG_ClassnameMustNotBeEmpty";                    //NOI18N
570
                break;
571
            case ClassNameTextField.STATUS_INVALID:
572
                key = "MSG_InvalidClassName";                           //NOI18N
573
                break;
574
            case ClassNameTextField.STATUS_VALID_NOT_DEFAULT:
575
                key = "MSG_ClassNameNotDefault";                        //NOI18N
576
                break;
577
            case ClassNameTextField.STATUS_VALID_END_NOT_TEST:
578
                key = "MSG_ClassNameEndNotTest";                        //NOI18N
579
                break;
580
        }
581
        if (state != ClassNameTextField.STATUS_VALID_NOT_DEFAULT) {
582
            setMessage(null, MSG_TYPE_CLASSNAME_NOT_DEFAULT);
583
        }
584
        setMessage((key != null)
585
                           ? NbBundle.getMessage(getClass(), key)
586
                           : null,
587
                   MSG_TYPE_CLASSNAME_INVALID);
588
        
589
        classNameValid =
590
                (state == ClassNameTextField.STATUS_VALID)
591
                || (state == ClassNameTextField.STATUS_VALID_NOT_DEFAULT);
592
    }
593
    
594
    /**
595
     * This method gets called if status of contents of the Class Name
596
     * text field changes. See <code>STATUS_xxx</code> constants
597
     * in class <code>ClassNameTextField</code>.
598
     *
599
     * @param  e  event describing the state change event
600
     *            (unused in this method)
601
     */
602
    @Override
603
    public void stateChanged(ChangeEvent e) {
604
        checkClassNameValidity();
605
        checkAcceptability();
606
    }
607
    
608
    /**
609
     */
610
    private void checkAcceptability() {
611
        final boolean wasAcceptable = isAcceptable;
612
        isAcceptable = hasTargetFolders && classNameValid;
613
        if (isAcceptable != wasAcceptable) {
614
            fireStateChange();
615
        }
616
    }
617
    
618
    /**
619
     * Are the values filled in the form acceptable?
620
     *
621
     * @see  #addChangeListener
622
     */
623
    private boolean isAcceptable() {
624
        return isAcceptable;
625
    }
626
    
627
    /**
628
     * This method is called the first time this panel's children are painted.
629
     * By default, this method just calls {@link #adjustWindowSize()}.
630
     *
631
     * @param  g  <code>Graphics</code> used to paint this panel's children
632
     */
633
    @Override
634
    protected void paintedFirstTime(java.awt.Graphics g) {
635
        if (initialMessage != null) {
636
            displayMessage(initialMessage);
637
            initialMessage = null;
638
        }
639
    }
640
    
641
    /**
642
     * Displays a given message in the message panel and resizes the dialog
643
     * if necessary. If the message cannot be displayed immediately,
644
     * because of this panel not displayed (painted) yet, displaying the message
645
     * is deferred until this panel is painted.
646
     *
647
     * @param  message  message to be displayed, or <code>null</code> if
648
     *                  the currently displayed message (if any) should be
649
     *                  removed
650
     */
651
    private void setMessage(final String message, final int msgType) {
652
        String msgToDisplay = msgStack.setMessage(msgType, message);
653
        if (msgToDisplay == null) {
654
            return;                     //no change
655
        }
656
657
        /* display the message: */
658
        if (!isPainted()) {
659
            initialMessage = msgToDisplay;
660
        } else {
661
            displayMessage(msgToDisplay);
662
        }
663
    }
664
    
665
    /**
666
     * Displays a given message in the message panel and resizes the dialog
667
     * if necessary.
668
     *
669
     * @param  message  message to be displayed, or <code>null</code> if
670
     *                  the currently displayed message (if any) should be
671
     *                  removed
672
     * @see  #adjustWindowSize()
673
     */
674
    private void displayMessage(String message) {
675
        if (message == null) {
676
            message = "";                                               //NOI18N
677
        }
678
        
679
        txtAreaMessage.setText(message);
680
        adjustWindowSize();
681
    }
682
    
683
    /**
684
     */
685
    private Component createMessagePanel() {
686
        Color color = UIManager.getColor("nb.errorForeground");         //NOI18N
687
        if (color == null) {
688
            color = new Color(89, 79, 191);   //RGB suggested by Bruce in #28466
689
        }
690
        txtAreaMessage = GuiUtils.createMultilineLabel("", color);      //NOI18N
691
        return txtAreaMessage;
692
    }
693
    
694
    /**
695
     * Creates a panel containing controls for settings code generation options.
696
     *
697
     * @return   created panel
698
     */
699
    private Component createCodeGenPanel() {
700
        
701
        /* create the components: */
702
        String[] chkBoxIDs;
703
        JCheckBox[] chkBoxes;
704
        if (multipleClasses) {
705
            chkBoxIDs = new String[] {
706
                GuiUtils.CHK_PUBLIC,
707
                GuiUtils.CHK_PROTECTED,
708
                GuiUtils.CHK_PACKAGE,
709
                GuiUtils.CHK_PACKAGE_PRIVATE_CLASSES,
710
                GuiUtils.CHK_ABSTRACT_CLASSES,
711
                GuiUtils.CHK_EXCEPTION_CLASSES,
712
                GuiUtils.CHK_SUITES,
713
                GuiUtils.CHK_SETUP,
714
                GuiUtils.CHK_TEARDOWN,
715
                GuiUtils.CHK_METHOD_BODIES,
716
                GuiUtils.CHK_JAVADOC,
717
                GuiUtils.CHK_HINTS
718
            };
719
        } else {
720
            chkBoxIDs = new String[] {
721
                GuiUtils.CHK_PUBLIC,
722
                GuiUtils.CHK_PROTECTED,
723
                GuiUtils.CHK_PACKAGE,
724
                null, // CHK_PACKAGE_PRIVATE_CLASSES,
725
                null, // CHK_ABSTRACT_CLASSES,
726
                null, // CHK_EXCEPTION_CLASSES,
727
                null, // CHK_SUITES,
728
                GuiUtils.CHK_SETUP,
729
                GuiUtils.CHK_TEARDOWN,
730
                GuiUtils.CHK_METHOD_BODIES,
731
                GuiUtils.CHK_JAVADOC,
732
                GuiUtils.CHK_HINTS
733
            };
734
        }
735
        chkBoxes = GuiUtils.createCheckBoxes(chkBoxIDs);
736
        int i = 0;
737
        chkPublic           = chkBoxes[i++];
738
        chkProtected        = chkBoxes[i++];
739
        chkPackage          = chkBoxes[i++];
740
        chkPackagePrivateClasses = chkBoxes[i++];       //may be null
741
        chkAbstractImpl     = chkBoxes[i++];            //may be null
742
        chkExceptions       = chkBoxes[i++];            //may be null
743
        chkGenerateSuites   = chkBoxes[i++];            //may be null
744
        chkSetUp            = chkBoxes[i++];
745
        chkTearDown         = chkBoxes[i++];        
746
        chkContent          = chkBoxes[i++];
747
        chkJavaDoc          = chkBoxes[i++];
748
        chkComments         = chkBoxes[i++];
749
        
750
        /* create groups of checkboxes: */
751
        JComponent methodAccessLevels = GuiUtils.createChkBoxGroup(
752
                bundle.getString("JUnitCfgOfCreate.groupAccessLevels"), //NOI18N
753
                new JCheckBox[] {chkPublic, chkProtected, chkPackage});
754
        JComponent classTypes = null;
755
        JComponent optionalClasses = null;
756
        if (multipleClasses) {
757
            classTypes = GuiUtils.createChkBoxGroup(
758
                bundle.getString("JUnitCfgOfCreate.groupClassTypes"),   //NOI18N
759
                new JCheckBox[] {chkPackagePrivateClasses,
760
                                 chkAbstractImpl, chkExceptions});
761
            optionalClasses = GuiUtils.createChkBoxGroup(
762
                bundle.getString("JUnitCfgOfCreate.groupOptClasses"),   //NOI18N
763
                new JCheckBox[] {chkGenerateSuites});
764
        }
765
        JComponent optionalCode = GuiUtils.createChkBoxGroup(
766
                bundle.getString("JUnitCfgOfCreate.groupOptCode"),      //NOI18N
767
                new JCheckBox[] {chkSetUp, chkTearDown, chkContent});
768
        JComponent optionalComments = GuiUtils.createChkBoxGroup(
769
                bundle.getString("JUnitCfgOfCreate.groupOptComments"),  //NOI18N
770
                new JCheckBox[] {chkJavaDoc, chkComments});
771
        
772
        /* create the left column of options: */
773
        Box leftColumn = Box.createVerticalBox();
774
        leftColumn.add(methodAccessLevels);
775
        if (multipleClasses) {
776
            leftColumn.add(Box.createVerticalStrut(11));
777
            leftColumn.add(classTypes);
778
        } else {
779
            /*
780
             * This strut ensures that width of the left column is not limited.
781
             * If it was limited, the rigth column would not move when the
782
             * dialog is horizontally resized.
783
             */
784
            leftColumn.add(Box.createVerticalStrut(0));
785
        }
786
        leftColumn.add(Box.createVerticalGlue());
787
        
788
        /* create the right column of options: */
789
        Box rightColumn = Box.createVerticalBox();
790
        if (multipleClasses) {
791
            rightColumn.add(optionalClasses);
792
            rightColumn.add(Box.createVerticalStrut(11));
793
        }
794
        rightColumn.add(optionalCode);
795
        rightColumn.add(Box.createVerticalStrut(11));
796
        rightColumn.add(optionalComments);
797
        rightColumn.add(Box.createVerticalGlue());
798
        
799
        /* compose the final panel: */
800
        //JPanel jpCodeGen = new SizeRestrictedPanel(false, true);
801
        JPanel jpCodeGen = new JPanel();
802
        jpCodeGen.setLayout(new BoxLayout(jpCodeGen, BoxLayout.X_AXIS));
803
        jpCodeGen.add(leftColumn);
804
        jpCodeGen.add(Box.createHorizontalStrut(24));
805
        jpCodeGen.add(rightColumn);
806
        
807
        /* decorate the panel: */
808
        addTitledBorder(jpCodeGen,
809
                  new Insets(12, 12, 11, 12),
810
                  bundle.getString("JUnitCfgOfCreate.jpCodeGen.title"));//NOI18N
811
        
812
        /* tune the layout: */
813
        methodAccessLevels.setAlignmentX(0.0f);
814
        if (multipleClasses) {
815
            classTypes.setAlignmentX(0.0f);
816
            optionalClasses.setAlignmentX(0.0f);
817
        }
818
        optionalCode.setAlignmentX(0.0f);
819
        optionalComments.setAlignmentX(0.0f);
820
        
821
        return jpCodeGen;
822
    }
823
    
824
    /**
825
     * Adds a border and a title around a given component.
826
     * If the component already has some border, it is overridden (not kept).
827
     *
828
     * @param  component  component the border and title should be added to
829
     * @param  insets  insets between the component and the titled border
830
     * @param  title  text of the title
831
     */
832
    private static void addTitledBorder(JComponent component,
833
                                        Insets insets,
834
                                        String title) {
835
        Border insideBorder = BorderFactory.createEmptyBorder(
836
                insets.top, insets.left, insets.bottom, insets.right);
837
        Border outsideBorder = new TitledBorder(
838
                BorderFactory.createEtchedBorder(), title);
839
        component.setBorder(new CompoundBorder(outsideBorder, insideBorder));
840
    }
841
    
842
    /**
843
     */
844
    FileObject getTargetFolder() {
845
        Object selectedLocation = cboxLocation.getSelectedItem();
846
        
847
        if (selectedLocation == null) {
848
            return null;
849
        }
850
        
851
        if (selectedLocation instanceof SourceGroup) {
852
            return ((SourceGroup) selectedLocation).getRootFolder();
853
        }
854
        assert selectedLocation instanceof FileObject;      //root folder
855
        return (FileObject) selectedLocation;
856
    }
857
    
858
    /**
859
     * Initializes form in the Test Settings panel of the dialog.
860
     */
861
    private void fillFormData() {
862
        final DataObject dataObj = nodes[0].getLookup().lookup(DataObject.class);
863
        final FileObject fileObj = dataObj.getPrimaryFile();
864
        
865
        if (singleClass) {
866
            assert nodes.length == 1;
867
            
868
            ClassPath cp = ClassPath.getClassPath(fileObj, ClassPath.SOURCE);
869
            String className = cp.getResourceName(fileObj, '.', false);
870
            lblClassToTestValue.setText(className);
871
            
872
            if (tfClassName != null) {
873
                String prefilledName = className + TEST_CLASS_SUFFIX;
874
                tfClassName.setText(prefilledName);
875
                tfClassName.setDefaultText(prefilledName);
876
                tfClassName.setCaretPosition(prefilledName.length());
877
            }
878
        } else if (singlePackage) {
879
            assert nodes.length == 1;
880
            
881
            ClassPath cp = ClassPath.getClassPath(fileObj, ClassPath.SOURCE);
882
            String packageName = cp.getResourceName(fileObj, '.', true);
883
            if (packageName.length() == 0) {
884
                packageName = NbBundle.getMessage(
885
                        getClass(),
886
                        "DefaultPackageName");                          //NOI18N
887
            }
888
            lblClassToTestValue.setText(packageName);
889
        } else {
890
            //PENDING
891
        }
892
        
893
        setupLocationChooser(fileObj);
894
        
895
        checkClassNameValidity();
896
    }
897
    
898
    /**
899
     */
900
    private void setupLocationChooser(FileObject refFileObject) {
901
        Object[] targetFolders = TestUtil.getTestTargets(refFileObject);
902
        if (targetFolders.length == 0) {
903
            Project owner = FileOwnerQuery.getOwner(refFileObject);
904
            if (owner != null) {
905
                if (SourceGroupModifier.createSourceGroup(owner, JavaProjectConstants.SOURCES_TYPE_JAVA, JavaProjectConstants.SOURCES_HINT_TEST) != null) {
906
                    targetFolders = TestUtil.getTestTargets(refFileObject);
907
                }
908
            }
909
        }
910
911
        if (targetFolders.length != 0) {
912
            hasTargetFolders = true;
913
            cboxLocation.setModel(new DefaultComboBoxModel(targetFolders));
914
            cboxLocation.setRenderer(new LocationChooserRenderer());
915
        } else {
916
            hasTargetFolders = false;
917
            //PENDING - message text:
918
            String msgNoTargetsFound = NbBundle.getMessage(
919
                                        getClass(),
920
                                        refFileObject.isFolder()
921
                                                ? "MSG_NoTestTarget_Fo" //NOI18N
922
                                                : "MSG_NoTestTarget_Fi",//NOI18N
923
                                        refFileObject.getNameExt());
924
            setMessage(msgNoTargetsFound, MSG_TYPE_NO_TARGET_FOLDERS);
925
            disableComponents();
926
        }
927
    }
928
    
929
    /**
930
     * Renderer which specially handles values of type
931
     * <code>SourceGroup</code> and <code>FileObject</code>.
932
     * It displays display names of these objects, instead of their default
933
     * string representation (<code>toString()</code>).
934
     *
935
     * @see  SourceGroup#getDisplayName()
936
     * @see  FileUtil#getFileDisplayName(FileObject)
937
     */
938
    private final class LocationChooserRenderer extends JLabel implements ListCellRenderer, UIResource {
939
        
940
        public LocationChooserRenderer () {
941
            setOpaque(true);
942
        }
943
        
944
        @Override
945
        public Component getListCellRendererComponent(
946
                JList list,
947
                Object value,
948
                int index,
949
                boolean isSelected,
950
                boolean cellHasFocus) {
951
            // #93658: GTK needs name to render cell renderer "natively"
952
            setName("ComboBox.listRenderer"); // NOI18N
953
            
954
            String text = value instanceof SourceGroup
955
                        ? ((SourceGroup) value).getDisplayName()
956
                        : value instanceof FileObject
957
                              ?  FileUtil.getFileDisplayName((FileObject) value)
958
                              : value.toString();
959
            setText(text);
960
            
961
            if ( isSelected ) {
962
                setBackground(list.getSelectionBackground());
963
                setForeground(list.getSelectionForeground());             
964
            }
965
            else {
966
                setBackground(list.getBackground());
967
                setForeground(list.getForeground());
968
            }
969
            
970
            return this;
971
        }
972
        
973
        // #93658: GTK needs name to render cell renderer "natively"
974
        @Override
975
        public String getName() {
976
            String name = super.getName();
977
            return name == null ? "ComboBox.renderer" : name;  // NOI18N
978
        }
979
            
980
    }
981
982
    /**
983
     * Registers a change listener.
984
     * Registered change listeners are notified when acceptability
985
     * of values in the form changes.
986
     *
987
     * @param  l  listener to be registered
988
     * @see  #isAcceptable
989
     * @see  #removeChangeListener
990
     */
991
    private void addChangeListener(ChangeListener l) {
992
        if (changeListeners == null) {
993
            changeListeners = new ArrayList<ChangeListener>(3);
994
        }
995
        changeListeners.add(l);
996
    }
997
    
998
    /**
999
     * Unregisters the given change listener.
1000
     * If the given listener has not been registered before, calling this
1001
     * method does not have any effect.
1002
     *
1003
     * @param  l  change listener to be removed
1004
     * @see  #addChangeListener
1005
     */
1006
    private void removeChangeListener(ChangeListener l) {
1007
        if (changeListeners != null
1008
                && changeListeners.remove(l)
1009
                && changeListeners.isEmpty()) {
1010
            changeListeners = null;
1011
        }
1012
    }
1013
    
1014
    /**
1015
     * Notifies all registered change listeners about a change.
1016
     *
1017
     * @see  #addChangeListener
1018
     */
1019
    private void fireStateChange() {
1020
        if (changeListeners != null) {
1021
            ChangeEvent e = new ChangeEvent(this);
1022
            for (Iterator i = changeListeners.iterator(); i.hasNext(); ) {
1023
                ((ChangeListener) i.next()).stateChanged(e);
1024
            }
1025
        }
1026
    }
1027
    
1028
    /**
1029
     * Disables all interactive visual components of this dialog
1030
     * except the OK, Cancel and Help buttons.
1031
     */
1032
    private void disableComponents() {
1033
        final Stack<Container> stack = new Stack<Container>();
1034
        stack.push(this);
1035
        
1036
        while (!stack.empty()) {
1037
            Container container = stack.pop();
1038
            Component comps[] = container.getComponents();
1039
            for (int i = 0; i < comps.length; i++) {
1040
                final java.awt.Component comp = comps[i];
1041
                
1042
                if (comp == txtAreaMessage) {
1043
                    continue;
1044
                }
1045
                if (comp instanceof JPanel) {
1046
                    JPanel panel = (JPanel) comp;
1047
                    stack.push(panel);
1048
1049
                    final Border border = panel.getBorder();
1050
                    if (border != null) {
1051
                        disableBorderTitles(border);
1052
                    }
1053
                    continue;
1054
                }
1055
                comp.setEnabled(false);
1056
                if (comp instanceof java.awt.Container) {
1057
                    Container nestedCont = (Container) comp;
1058
                    if (nestedCont.getComponentCount() != 0) {
1059
                        stack.push(nestedCont);
1060
                    }
1061
                }
1062
            }
1063
        }
1064
    }
1065
    
1066
    /**
1067
     */
1068
    private static void disableBorderTitles(Border border) {
1069
        
1070
        if (border instanceof TitledBorder) {
1071
            disableBorderTitle((TitledBorder) border);
1072
            return;
1073
        }
1074
        
1075
        if (!(border instanceof CompoundBorder)) {
1076
            return;
1077
        }
1078
        
1079
        Stack<CompoundBorder> stack = new Stack<CompoundBorder>();
1080
        stack.push((CompoundBorder) border);
1081
        while (!stack.empty()) {
1082
            CompoundBorder cb = stack.pop();
1083
            
1084
            Border b;
1085
            b = cb.getOutsideBorder();
1086
            if (b instanceof CompoundBorder) {
1087
                stack.push((CompoundBorder) b);
1088
            } else if (b instanceof TitledBorder) {
1089
                disableBorderTitle((TitledBorder) b);
1090
            }
1091
            
1092
            b = cb.getInsideBorder();
1093
            if (b instanceof CompoundBorder) {
1094
                stack.push((CompoundBorder) b);
1095
            } else if (b instanceof TitledBorder) {
1096
                disableBorderTitle((TitledBorder) b);
1097
            }
1098
        }
1099
    }
1100
    
1101
    /**
1102
     */
1103
    private static void disableBorderTitle(TitledBorder border) {
1104
        final Color color = UIManager.getColor(
1105
                "Label.disabledForeground");                        //NOI18N
1106
        if (color != null) {
1107
            border.setTitleColor(color);
1108
        }
1109
    }
1110
1111
    private JLabel lblClassToTestValue;
1112
    private ClassNameTextField tfClassName;
1113
    private JTextComponent txtAreaMessage;
1114
    private JComboBox cboxLocation;
1115
    private JCheckBox chkAbstractImpl;
1116
    private JCheckBox chkComments;
1117
    private JCheckBox chkContent;
1118
    private JCheckBox chkExceptions;
1119
    private JCheckBox chkGenerateSuites;
1120
    private JCheckBox chkJavaDoc;
1121
    private JCheckBox chkPackage;
1122
    private JCheckBox chkPackagePrivateClasses;
1123
    private JCheckBox chkProtected;
1124
    private JCheckBox chkPublic;
1125
    private JCheckBox chkSetUp;
1126
    private JCheckBox chkTearDown;
1127
1128
}
(-)a/junit/src/org/netbeans/modules/junit/JUnitTestCreatorProvider.java (+412 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.junit;
43
44
import java.awt.EventQueue;
45
import java.util.ArrayList;
46
import java.util.Collection;
47
import java.util.List;
48
import java.util.Map;
49
import org.netbeans.api.java.classpath.ClassPath;
50
import org.netbeans.api.project.FileOwnerQuery;
51
import org.netbeans.api.project.Project;
52
import org.netbeans.api.project.SourceGroup;
53
import org.netbeans.modules.gsf.testrunner.api.GuiUtils;
54
import org.netbeans.modules.gsf.testrunner.api.TestCreatorProvider;
55
import org.netbeans.modules.gsf.testrunner.plugin.CommonPlugin;
56
import org.netbeans.modules.junit.plugin.JUnitPlugin;
57
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
58
import org.openide.DialogDisplayer;
59
import org.openide.NotifyDescriptor;
60
import org.openide.cookies.EditorCookie;
61
import org.openide.filesystems.FileObject;
62
import org.openide.loaders.DataFolder;
63
import org.openide.loaders.DataObject;
64
import org.openide.loaders.DataObjectNotFoundException;
65
import org.openide.nodes.Node;
66
import org.openide.util.NbBundle;
67
import org.openide.util.RequestProcessor;
68
import org.openide.util.lookup.ServiceProvider;
69
70
/**
71
 *
72
 * @author theofanis
73
 */
74
@ServiceProvider(service=TestCreatorProvider.class, position=10)
75
public class JUnitTestCreatorProvider extends TestCreatorProvider {
76
77
    @Override
78
    public String getDisplayName() {
79
        return GuiUtils.JUNIT_TEST_FRAMEWORK;
80
    }
81
    
82
    @Override
83
    public boolean canHandleMultipleClasses(Node[] activatedNodes) {
84
        return true;
85
    }
86
87
    @Override
88
    public boolean enable(Node[] activatedNodes) {
89
        if (activatedNodes.length == 0) {
90
            return false;
91
        }
92
93
        /*
94
         * In most cases, there is just one node selected - that is why
95
         * this case is handled in a special, more effective way
96
         * (no collections and iterators created).
97
         */
98
        if (activatedNodes.length == 1) {
99
            final Node node = activatedNodes[0];
100
            DataObject dataObj;
101
            FileObject fileObj;
102
            Project project;
103
            if (((dataObj = node.getLookup().lookup(DataObject.class)) != null)
104
                && ((fileObj = dataObj.getPrimaryFile()) != null)
105
                && fileObj.isValid()
106
                && ((project = FileOwnerQuery.getOwner(fileObj)) != null)
107
                && (getSourceGroup(fileObj, project) != null)
108
                && (TestUtil.isJavaFile(fileObj)
109
                    || (node.getLookup().lookup(DataFolder.class) != null))) {
110
111
                JUnitPlugin plugin = TestUtil.getPluginForProject(project);
112
                return JUnitPluginTrampoline.DEFAULT.canCreateTests(plugin,
113
                                                                    fileObj);
114
            } else {
115
                return false;
116
            }
117
        }
118
119
        final Collection<FileObject> fileObjs
120
                = new ArrayList<FileObject>(activatedNodes.length);
121
        Project theProject = null;
122
        boolean result = false;
123
        for (Node node : activatedNodes) {
124
            DataObject dataObj = node.getLookup().lookup(DataObject.class);
125
            if (dataObj != null) {
126
                FileObject fileObj = dataObj.getPrimaryFile();
127
                if ((fileObj == null) || !fileObj.isValid()) {
128
                    continue;
129
                }
130
131
                fileObjs.add(fileObj);
132
                
133
                Project prj = FileOwnerQuery.getOwner(fileObj);
134
                if (prj != null) {
135
                    if (theProject == null) {
136
                        theProject = prj;
137
                    }
138
                    if (prj != theProject) {
139
                        return false;        /* files from different projects */
140
                    }
141
142
                    if ((getSourceGroup(fileObj, prj) != null)
143
                        && (TestUtil.isJavaFile(fileObj)
144
                            || (node.getLookup().lookup(DataFolder.class) != null))) {
145
                        result = true;
146
                    }
147
                }
148
            }
149
        }
150
151
        if (theProject != null) {
152
            JUnitPlugin plugin = TestUtil.getPluginForProject(theProject);
153
            result &= JUnitPluginTrampoline.DEFAULT.canCreateTests(
154
                            plugin,
155
                            fileObjs.toArray(new FileObject[fileObjs.size()]));
156
        }
157
158
        return result;
159
    }
160
161
    @Override
162
    public void createTests(Node[] activatedNodes) {
163
        String problem;
164
        if ((problem = checkNodesValidity(activatedNodes)) != null) {
165
            // TODO report problem
166
            NotifyDescriptor msg = new NotifyDescriptor.Message(
167
                    problem, NotifyDescriptor.WARNING_MESSAGE);
168
            DialogDisplayer.getDefault().notify(msg);
169
            return;
170
        }
171
172
        final FileObject[] filesToTest = getFileObjectsFromNodes(activatedNodes);
173
        if (filesToTest == null) {
174
            return;     //XXX: display some message
175
        }
176
177
        /*
178
         * Determine the plugin to be used:
179
         */
180
        final JUnitPlugin plugin = TestUtil.getPluginForProject(
181
                FileOwnerQuery.getOwner(filesToTest[0]));
182
183
        if (!JUnitPluginTrampoline.DEFAULT.createTestActionCalled(
184
                plugin, filesToTest)) {
185
            return;
186
        }
187
188
        /*
189
         * Store the configuration data:
190
         */
191
        final boolean singleClass = isSingleClass();
192
        final Map<CommonPlugin.CreateTestParam, Object> params = TestUtil.getSettingsMap(!singleClass);
193
        if (singleClass) {
194
            params.put(CommonPlugin.CreateTestParam.CLASS_NAME, getTestClassName());
195
        }
196
        final FileObject targetFolder = getTargetFolder();
197
198
        RequestProcessor.getDefault().post(new Runnable() {
199
200
            @Override
201
            public void run() {
202
                /*
203
                 * Now create the tests:
204
                 */
205
                final FileObject[] testFileObjects = JUnitPluginTrampoline.DEFAULT.createTests(
206
                        plugin,
207
                        filesToTest,
208
                        targetFolder,
209
                        params);
210
211
                /*
212
                 * Open the created/updated test class if appropriate:
213
                 */
214
                if (testFileObjects.length == 1) {
215
                    try {
216
                        DataObject dobj = DataObject.find(testFileObjects[0]);
217
                        final EditorCookie ec = dobj.getLookup().lookup(EditorCookie.class);
218
                        if (ec != null) {
219
                            EventQueue.invokeLater(new Runnable() {
220
221
                                @Override
222
                                public void run() {
223
                                    ec.open();
224
                                }
225
                            });
226
                        }
227
                    } catch (DataObjectNotFoundException ex) {
228
                        ex.printStackTrace();
229
                    }
230
                }
231
            }
232
        });
233
    }
234
235
    /**
236
     * Checks that the selection of nodes the dialog is invoked on is valid. 
237
     * @return String message describing the problem found or null, if the
238
     *         selection is ok
239
     */
240
    private static String checkNodesValidity(Node[] nodes) {
241
        FileObject[] files = getFiles(nodes);
242
243
        Project project = getProject(files);
244
        if (project == null) {
245
            return NbBundle.getMessage(JUnitTestCreatorProvider.class,
246
                                       "MSG_multiproject_selection");   //NOI18N
247
        }
248
249
        if (!checkPackages(files)) {
250
            return NbBundle.getMessage(JUnitTestCreatorProvider.class,
251
                                       "MSG_invalid_packages");         //NOI18N
252
        }
253
254
        return null;
255
    }
256
257
    /**
258
     * Extracts {@code FileObject}s from the given nodes.
259
     * Nodes that have (direct or indirect) parent nodes among the given
260
     * nodes are ignored.
261
     *
262
     * @return  a non-empty array of {@code FileObject}s
263
     *          represented by the given nodes;
264
     *          or {@code null} if no {@code FileObject} was found;
265
     */
266
    private static FileObject[] getFileObjectsFromNodes(final Node[] nodes){
267
        FileObject[] fileObjects = new FileObject[nodes.length];
268
        List<FileObject> fileObjectsList = null;
269
270
        for (int i = 0; i < nodes.length; i++) {
271
            final Node node = nodes[i];
272
            final FileObject fo;
273
            if (!hasParentAmongNodes(nodes, i)
274
                    && ((fo = getTestFileObject(node)) != null)) {
275
                if (fileObjects != null) {
276
                    fileObjects[i] = fo;
277
                } else {
278
                    if (fileObjectsList == null) {
279
                        fileObjectsList = new ArrayList<FileObject>(
280
                                                        nodes.length - i);
281
                    }
282
                    fileObjectsList.add(fo);
283
                }
284
            } else {
285
                fileObjects = null;     //signs that some FOs were skipped
286
            }
287
        }
288
        if (fileObjects == null) {
289
            if (fileObjectsList != null) {
290
                fileObjects = fileObjectsList.toArray(
291
                        new FileObject[fileObjectsList.size()]);
292
                fileObjectsList = null;
293
            }
294
        }
295
296
        return fileObjects;
297
    }
298
299
    /**
300
     * Check that all the files (folders or java files) have correct java
301
     * package names.
302
     * @return true if all are fine
303
     */
304
    private static boolean checkPackages(FileObject[] files) {
305
        if (files.length == 0) {
306
            return true;
307
        } else {
308
            Project project = FileOwnerQuery.getOwner(files[0]);
309
            for (int i = 0 ; i < files.length; i++) {
310
                String packageName = getPackage(project, files[i]);
311
                if ((packageName == null)
312
                        || !TestUtil.isValidPackageName(packageName)) {
313
                    return false;
314
                }
315
            }
316
            return true;
317
        }
318
    }
319
320
    /**
321
     * Get the package name of <code>file</code>.
322
     *
323
     * @param project owner of the file (for performance reasons)
324
     * @param file the FileObject whose packagename to get
325
     * @return package name of the file or null if it cannot be retrieved
326
     */
327
    private static String getPackage(Project project, FileObject file) {
328
        SourceGroup srcGrp = TestUtil.findSourceGroupOwner(project, file);
329
        if (srcGrp!= null) {
330
            ClassPath cp = ClassPathSupport.createClassPath(
331
                    new FileObject [] {srcGrp.getRootFolder()});
332
            return cp.getResourceName(file, '.', false);
333
        } else {
334
            return null;
335
        }
336
    }
337
338
339
    private static FileObject[] getFiles(Node[] nodes) {
340
        FileObject[] ret = new FileObject[nodes.length];
341
        for (int i = 0 ; i < nodes.length ; i++) {
342
            ret[i]  = TestUtil.getFileObjectFromNode(nodes[i]);
343
        }
344
        return ret;
345
    }
346
347
    /**
348
     * Get the single project for <code>nodes</code> if there is such.
349
     * If the nodes belong to different projects or some of the nodes doesn't
350
     * have a project, return null.
351
     */
352
    private static Project getProject(FileObject[] files) {
353
        Project project = null;
354
        for (int i = 0 ; i < files.length; i++) {
355
            Project nodeProject = FileOwnerQuery.getOwner(files[i]);
356
            if (project == null) {
357
                project = nodeProject;
358
            } else if (project != nodeProject) {
359
                return null;
360
            }
361
        }
362
        return project;
363
    }
364
365
    /**
366
     * Grabs and checks a <code>FileObject</code> from the given node.
367
     * If either the file could not be grabbed or the file does not pertain
368
     * to any project, a message is displayed.
369
     *
370
     * @param  node  node to get a <code>FileObject</code> from.
371
     * @return  the grabbed <code>FileObject</code>,
372
     *          or <code>null</code> in case of failure
373
     */
374
    private static FileObject getTestFileObject(final Node node) {
375
        final FileObject fo = TestUtil.getFileObjectFromNode(node);
376
        if (fo == null) {
377
            TestUtil.notifyUser(NbBundle.getMessage(
378
                    JUnitTestCreatorProvider.class,
379
                    "MSG_file_from_node_failed"));                      //NOI18N
380
            return null;
381
        }
382
        ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
383
        if (cp == null) {
384
            TestUtil.notifyUser(NbBundle.getMessage(
385
                    JUnitTestCreatorProvider.class,
386
                    "MSG_no_project",                                   //NOI18N
387
                    fo));
388
            return null;
389
        }
390
        return fo;
391
    }
392
393
    private static boolean hasParentAmongNodes(final Node[] nodes,
394
                                               final int idx) {
395
        Node node;
396
397
        node = nodes[idx].getParentNode();
398
        while (null != node) {
399
            for (int i = 0; i < nodes.length; i++) {
400
                if (i == idx) {
401
                    continue;
402
                }
403
                if (node == nodes[i]) {
404
                    return true;
405
                }
406
            }
407
            node = node.getParentNode();
408
        }
409
        return false;
410
    }
411
    
412
}
(-)a/junit/src/org/netbeans/modules/junit/actions/JUnitMethodDebuggerProvider.java (+162 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.junit.actions;
43
44
import java.io.IOException;
45
import java.util.Arrays;
46
import java.util.concurrent.Future;
47
import java.util.concurrent.atomic.AtomicBoolean;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import javax.swing.JEditorPane;
51
import javax.swing.text.Document;
52
import org.netbeans.api.java.source.JavaSource;
53
import org.netbeans.api.progress.ProgressUtils;
54
import org.netbeans.modules.gsf.testrunner.api.CommonTestUtil;
55
import org.netbeans.modules.gsf.testrunner.api.TestMethodDebuggerProvider;
56
import org.netbeans.modules.junit.output.OutputUtils;
57
import org.netbeans.spi.project.ActionProvider;
58
import org.netbeans.spi.project.SingleMethod;
59
import org.openide.cookies.EditorCookie;
60
import org.openide.filesystems.FileObject;
61
import org.openide.filesystems.FileUtil;
62
import org.openide.nodes.Node;
63
import org.openide.text.NbDocument;
64
import org.openide.util.Exceptions;
65
import org.openide.util.Lookup;
66
import org.openide.util.NbBundle;
67
import org.openide.util.lookup.Lookups;
68
import org.openide.util.lookup.ServiceProvider;
69
70
/**
71
 *
72
 * @author theofanis
73
 */
74
@ServiceProvider(service=TestMethodDebuggerProvider.class, position=10)
75
public class JUnitMethodDebuggerProvider extends TestMethodDebuggerProvider {
76
77
    private static final Logger LOGGER = Logger.getLogger(JUnitMethodDebuggerProvider.class.getName());
78
    private final String command = SingleMethod.COMMAND_DEBUG_SINGLE_METHOD;
79
80
    @Override
81
    public String getProviderName() {
82
        return NbBundle.getMessage(TestMethodDebuggerProvider.class, "NAME_JUnitMethodProvider");
83
    }
84
85
    @Override
86
    public void debugTestMethod(Node activatedNode) {
87
        final Node activeNode = activatedNode;
88
        final Document doc;
89
        final int caret;
90
91
        EditorCookie ec = activeNode.getLookup().lookup(EditorCookie.class);
92
        if (ec != null) {
93
            JEditorPane pane = NbDocument.findRecentEditorPane(ec);
94
            if (pane != null) {
95
                doc = pane.getDocument();
96
                caret = pane.getCaret().getDot();
97
            } else {
98
                doc = null;
99
                caret = -1;
100
            }
101
        } else {
102
            doc = null;
103
            caret = -1;
104
        }
105
106
        ProgressUtils.runOffEventDispatchThread(new Runnable() {
107
108
            @Override
109
            public void run() {
110
                SingleMethod sm = getTestMethod(activeNode.getLookup(), doc, caret);
111
                if (sm != null) {
112
                    ActionProvider ap = OutputUtils.getActionProvider(sm.getFile());
113
                    if (ap != null) {
114
                        if(Arrays.asList(ap.getSupportedActions()).contains(command) && ap.isActionEnabled(command, Lookups.singleton(sm))) {
115
                            ap.invokeAction(command, Lookups.singleton(sm));
116
                        }
117
                    }
118
                }
119
            }
120
        },
121
        NbBundle.getMessage(JUnitMethodDebuggerProvider.class, "LBL_Action_RunTestMethod"), new AtomicBoolean(), false);
122
    }
123
    
124
    private SingleMethod getTestMethod(Lookup lkp, Document doc, int cursor){
125
        SingleMethod sm = lkp.lookup(SingleMethod.class);
126
        if (sm == null && doc != null){
127
            JavaSource js = JavaSource.forDocument(doc);
128
            TestClassInfoTask task = new TestClassInfoTask(cursor);
129
            try {
130
                Future<Void> f = js.runWhenScanFinished(task, true);
131
                if (f.isDone() && task.getFileObject() != null && task.getMethodName() != null){
132
                    sm = new SingleMethod(task.getFileObject(), task.getMethodName());
133
                }
134
            } catch (IOException ex) {
135
                LOGGER.log(Level.WARNING, null, ex);
136
            }
137
        }
138
        return sm;
139
    }
140
141
    @Override
142
    public boolean canHandle(Node activatedNode) {
143
        FileObject fileO = CommonTestUtil.getFileObjectFromNode(activatedNode);
144
        if (fileO != null) {
145
            EditorCookie ec = activatedNode.getLookup().lookup(EditorCookie.class);
146
            if (ec != null) {
147
                JEditorPane pane = NbDocument.findRecentEditorPane(ec);
148
                if (pane != null) {
149
                    String text = pane.getText();
150
                    int index = text.indexOf("public");  //NOI18N
151
                    if (index != -1) {
152
                        if (text.substring(0, index).contains("org.junit.")) {  //NOI18N
153
                            return true;
154
                        }
155
                    }
156
                }
157
            }
158
        }
159
        return false;
160
    }
161
    
162
}
(-)a/junit/src/org/netbeans/modules/junit/actions/JUnitMethodRunnerProvider.java (+160 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.junit.actions;
43
44
import java.io.IOException;
45
import java.util.Arrays;
46
import java.util.concurrent.Future;
47
import java.util.concurrent.atomic.AtomicBoolean;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import javax.swing.JEditorPane;
51
import javax.swing.text.Document;
52
import org.netbeans.api.java.source.JavaSource;
53
import org.netbeans.api.progress.ProgressUtils;
54
import org.netbeans.modules.gsf.testrunner.api.CommonTestUtil;
55
import org.netbeans.modules.gsf.testrunner.api.TestMethodRunnerProvider;
56
import org.netbeans.modules.junit.output.OutputUtils;
57
import org.netbeans.spi.project.ActionProvider;
58
import org.netbeans.spi.project.SingleMethod;
59
import org.openide.cookies.EditorCookie;
60
import org.openide.filesystems.FileObject;
61
import org.openide.nodes.Node;
62
import org.openide.text.NbDocument;
63
import org.openide.util.Lookup;
64
import org.openide.util.NbBundle;
65
import org.openide.util.lookup.Lookups;
66
import org.openide.util.lookup.ServiceProvider;
67
68
/**
69
 *
70
 * @author theofanis
71
 */
72
@ServiceProvider(service=TestMethodRunnerProvider.class, position=10)
73
public class JUnitMethodRunnerProvider extends TestMethodRunnerProvider {
74
75
    private static final Logger LOGGER = Logger.getLogger(JUnitMethodRunnerProvider.class.getName());
76
    private final String command = SingleMethod.COMMAND_RUN_SINGLE_METHOD;
77
78
    @Override
79
    public String getProviderName() {
80
        return NbBundle.getMessage(TestMethodRunnerProvider.class, "NAME_JUnitMethodProvider");
81
    }
82
83
    @Override
84
    public void runTestMethod(Node activatedNode) {
85
        final Node activeNode = activatedNode;
86
        final Document doc;
87
        final int caret;
88
89
        EditorCookie ec = activeNode.getLookup().lookup(EditorCookie.class);
90
        if (ec != null) {
91
            JEditorPane pane = NbDocument.findRecentEditorPane(ec);
92
            if (pane != null) {
93
                doc = pane.getDocument();
94
                caret = pane.getCaret().getDot();
95
            } else {
96
                doc = null;
97
                caret = -1;
98
            }
99
        } else {
100
            doc = null;
101
            caret = -1;
102
        }
103
104
        ProgressUtils.runOffEventDispatchThread(new Runnable() {
105
106
            @Override
107
            public void run() {
108
                SingleMethod sm = getTestMethod(activeNode.getLookup(), doc, caret);
109
                if (sm != null) {
110
                    ActionProvider ap = OutputUtils.getActionProvider(sm.getFile());
111
                    if (ap != null) {
112
                        if(Arrays.asList(ap.getSupportedActions()).contains(command) && ap.isActionEnabled(command, Lookups.singleton(sm))) {
113
                            ap.invokeAction(command, Lookups.singleton(sm));
114
                        }
115
                    }
116
                }
117
            }
118
        },
119
        NbBundle.getMessage(JUnitMethodRunnerProvider.class, "LBL_Action_RunTestMethod"), new AtomicBoolean(), false);
120
    }
121
    
122
    private SingleMethod getTestMethod(Lookup lkp, Document doc, int cursor){
123
        SingleMethod sm = lkp.lookup(SingleMethod.class);
124
        if (sm == null && doc != null){
125
            JavaSource js = JavaSource.forDocument(doc);
126
            TestClassInfoTask task = new TestClassInfoTask(cursor);
127
            try {
128
                Future<Void> f = js.runWhenScanFinished(task, true);
129
                if (f.isDone() && task.getFileObject() != null && task.getMethodName() != null){
130
                    sm = new SingleMethod(task.getFileObject(), task.getMethodName());
131
                }
132
            } catch (IOException ex) {
133
                LOGGER.log(Level.WARNING, null, ex);
134
            }
135
        }
136
        return sm;
137
    }
138
139
    @Override
140
    public boolean canHandle(Node activatedNode) {
141
        FileObject fileO = CommonTestUtil.getFileObjectFromNode(activatedNode);
142
        if (fileO != null) {
143
            EditorCookie ec = activatedNode.getLookup().lookup(EditorCookie.class);
144
            if (ec != null) {
145
                JEditorPane pane = NbDocument.findRecentEditorPane(ec);
146
                if (pane != null) {
147
                    String text = pane.getText();
148
                    int index = text.indexOf("public");  //NOI18N
149
                    if (index != -1) {
150
                        if (text.substring(0, index).contains("org.junit.")) {  //NOI18N
151
                            return true;
152
                        }
153
                    }
154
                }
155
            }
156
        }
157
        return false;
158
    }
159
    
160
}

Return to bug 208841