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

(-)a/java.api.common/apichanges.xml (+15 lines)
Lines 105-110 Link Here
105
105
106
    <!-- ACTUAL CHANGES BEGIN HERE: -->
106
    <!-- ACTUAL CHANGES BEGIN HERE: -->
107
    <changes>
107
    <changes>
108
        <change id="LogicalViewProviders">
109
            <api name="java-api-common"/>
110
            <summary>Added <code>LogicalViewProviders</code> support to create default implementation of the <code>LogicalViewProvider2</code>.</summary>
111
            <version major="1" minor="62"/>
112
            <date day="17" month="10" year="2013"/>
113
            <author login="tzezula"/>
114
            <compatibility addition="yes"/>
115
            <description>
116
                <p>
117
                    Added <code>LogicalViewProviders</code> support to create default implementation of the <code>LogicalViewProvider2</code>
118
                    for Ant Based Project.
119
                </p>
120
            </description>
121
            <class package="org.netbeans.modules.java.api.common.project.ui" name="LogicalViewProviders"/>
122
        </change>
108
        <change id="ProjectHooks">
123
        <change id="ProjectHooks">
109
            <api name="java-api-common"/>
124
            <api name="java-api-common"/>
110
            <summary>Added <code>ProjectHooks</code> factory to create default implementation of the <code>ProjectOpenedHook</code> and the <code>ProjectXmlSavedHook}</code>.</summary>
125
            <summary>Added <code>ProjectHooks</code> factory to create default implementation of the <code>ProjectOpenedHook</code> and the <code>ProjectXmlSavedHook}</code>.</summary>
(-)a/java.api.common/manifest.mf (-1 / +1 lines)
Lines 1-4 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.java.api.common/0
2
OpenIDE-Module: org.netbeans.modules.java.api.common/0
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/api/common/resources/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/api/common/resources/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.61
4
OpenIDE-Module-Specification-Version: 1.62
(-)a/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/Bundle.properties (+4 lines)
Lines 75-77 Link Here
75
LBL_Properties_Action=Properties
75
LBL_Properties_Action=Properties
76
# {0} - folder name
76
# {0} - folder name
77
JavaSourceNodeFactory.gensrc=Generated Sources ({0})
77
JavaSourceNodeFactory.gensrc=Generated Sources ({0})
78
79
#LogicalViewProviders
80
HINT_project_root_node=Java project in {0}
81
TP_CompileOnSaveDisabled=Compile on Save is disabled. It can be enabled in Project Properties.
(-)a/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/LogicalViewProviders.java (+559 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.java.api.common.project.ui;
44
45
import java.awt.Color;
46
import java.awt.Image;
47
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import java.io.CharConversionException;
50
import java.net.URL;
51
import javax.swing.Action;
52
import javax.swing.Icon;
53
import javax.swing.UIManager;
54
import javax.swing.event.ChangeEvent;
55
import javax.swing.event.ChangeListener;
56
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.api.annotations.common.NullAllowed;
58
import org.netbeans.api.java.project.JavaProjectConstants;
59
import org.netbeans.api.project.FileOwnerQuery;
60
import org.netbeans.api.project.Project;
61
import org.netbeans.api.project.ProjectInformation;
62
import org.netbeans.api.project.ProjectManager;
63
import org.netbeans.api.project.ProjectUtils;
64
import org.netbeans.api.project.SourceGroup;
65
import org.netbeans.api.project.ui.ProjectProblems;
66
import org.netbeans.spi.java.project.support.ui.PackageView;
67
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
68
import org.netbeans.spi.project.ui.ProjectProblemsProvider;
69
import org.netbeans.spi.project.ui.support.CommonProjectActions;
70
import org.netbeans.spi.project.ui.support.DefaultProjectOperations;
71
import org.netbeans.spi.project.ui.support.NodeFactorySupport;
72
import org.openide.filesystems.FileObject;
73
import org.openide.filesystems.FileUtil;
74
import org.openide.loaders.DataObject;
75
import org.openide.loaders.DataObjectNotFoundException;
76
import org.openide.nodes.AbstractNode;
77
import org.openide.nodes.Node;
78
import org.openide.util.ChangeSupport;
79
import org.openide.util.HelpCtx;
80
import org.openide.util.ImageUtilities;
81
import org.openide.util.Lookup;
82
import org.openide.util.NbBundle;
83
import org.openide.util.Parameters;
84
import org.openide.util.RequestProcessor;
85
import org.openide.util.WeakListeners;
86
import org.openide.util.lookup.AbstractLookup;
87
import org.openide.util.lookup.InstanceContent;
88
import org.openide.xml.XMLUtil;
89
90
/**
91
 * Support for creating default {@link LogicalViewProvider2} for Ant Based Project.
92
 * @author Tomas Zezula
93
 * @since 1.62
94
 */
95
public final class LogicalViewProviders {
96
97
    private LogicalViewProviders() {
98
        throw new IllegalStateException("No instance allowed"); //NOI18N
99
    }
100
101
102
    /**
103
     * Creates a new {@link LogicalViewProviderBuilder}.
104
     * @param project the project for which the builder should be created
105
     * @param eval the project's {@link PropertyEvaluator}
106
     * @param extensionFolder the extension point name
107
     * @return the new {@link LogicalViewProviderBuilder}
108
     */
109
    @NonNull
110
    public static LogicalViewProviderBuilder createBuilder(
111
        @NonNull final Project project,
112
        @NonNull final PropertyEvaluator eval,
113
        @NonNull final String extensionFolder) {
114
        return new LogicalViewProviderBuilder(
115
            project,
116
            eval,
117
            extensionFolder);
118
    }
119
120
121
    /**
122
     * Builder for creating a new configured {@link LogicalViewProvider2} instance.
123
     */
124
    public static class LogicalViewProviderBuilder {
125
126
        private final Project project;
127
        private final PropertyEvaluator eval;
128
        private final String projectType;
129
        private HelpCtx helpContext;
130
        private CompileOnSaveBadge badgeStatus;
131
        
132
133
        private LogicalViewProviderBuilder(
134
            @NonNull final Project project,
135
            @NonNull final PropertyEvaluator eval,
136
            @NonNull final String projectType) {
137
            Parameters.notNull("project", project); //NOI18N
138
            Parameters.notNull("eval", eval);   //NOI18N
139
            Parameters.notNull("projectType", projectType); //NOI18N
140
            this.project = project;
141
            this.eval = eval;
142
            this.projectType = projectType;
143
        }
144
145
        /**
146
         * Sets a {@link HelpCtx}.
147
         * @param helpContext the root node {@link HelpCtx}
148
         * @return the {@link LogicalViewProviderBuilder}
149
         */
150
        @NonNull
151
        public LogicalViewProviderBuilder setHelpCtx(@NonNull final HelpCtx helpContext) {
152
            Parameters.notNull("helpContext", helpContext); //NOI18N
153
            this.helpContext = helpContext;
154
            return this;
155
        }
156
157
        /**
158
         * Sets a compile on save badge status.
159
         * @param badgeStatus the compile on save badge status
160
         * @return the {@link LogicalViewProviderBuilder}
161
         */
162
        @NonNull
163
        public LogicalViewProviderBuilder setCompileOnSaveBadge(@NonNull final CompileOnSaveBadge badgeStatus) {
164
            Parameters.notNull("badgeStatus", badgeStatus); //NOI18N
165
            this.badgeStatus = badgeStatus;
166
            return this;
167
        }
168
169
        /**
170
         * Creates a new configured {@link LogicalViewProvider2} instance.
171
         * @return the {@link LogicalViewProvider2} instance
172
         */
173
        @NonNull
174
        public LogicalViewProvider2 build() {
175
            return new LogicalViewProviderImpl(
176
                project,
177
                eval,
178
                projectType,
179
                helpContext,
180
                badgeStatus);
181
        }
182
        
183
    }
184
185
186
    /**
187
     * Compile on Save badge status.
188
     * The {@link CompileOnSaveBadge} is used by {@link LogicalViewProvider2}
189
     * to enable or disable the project badge notifying an user about disabled
190
     * compile on save.
191
     */
192
    public static interface CompileOnSaveBadge {
193
        /**
194
         * Badge visibility check.
195
         * @return true if the badge should be visible
196
         */
197
        boolean isBadgeVisible();
198
        /**
199
         * Checks if the changed property affects the compile on save visibility.
200
         * @param propertyName the name of changed property
201
         * @return true if compile on save badge should be recalculated
202
         */
203
        boolean isImportant(@NonNull String propertyName);
204
    }
205
206
207
    private static class LogicalViewProviderImpl implements LogicalViewProvider2 {
208
209
        private static final RequestProcessor RP = new RequestProcessor(LogicalViewProviders.class);
210
        private static final String COMPILE_ON_SAVE_DISABLED_BADGE_PATH = "org/netbeans/modules/java/api/common/project/ui/resources/compileOnSaveDisabledBadge.gif";   //NOI18N
211
        private static final Image compileOnSaveDisabledBadge;
212
        static {
213
            URL errorBadgeIconURL = LogicalViewProviders.class.getClassLoader().getResource(COMPILE_ON_SAVE_DISABLED_BADGE_PATH);
214
            String compileOnSaveDisabledTP = "<img src=\"" + errorBadgeIconURL + "\">&nbsp;" + NbBundle.getMessage(LogicalViewProviders.class, "TP_CompileOnSaveDisabled");
215
            compileOnSaveDisabledBadge = ImageUtilities.assignToolTipToImage(ImageUtilities.loadImage(COMPILE_ON_SAVE_DISABLED_BADGE_PATH), compileOnSaveDisabledTP);
216
        }
217
218
        private final Project project;
219
        private final PropertyEvaluator evaluator;
220
        private final String projectType;
221
        private final HelpCtx helpContext;
222
        private final CompileOnSaveBadge badgeStatus;
223
        private final ChangeSupport changeSupport = new ChangeSupport(this);
224
        private final PropertyChangeListener pcl;
225
        private final RequestProcessor.Task task = RP.create(new Runnable() {
226
            public @Override void run() {
227
                setBroken(ProjectProblems.isBroken(project));
228
                setCompileOnSaveDisabled(isCompileOnSaveDisabled());
229
            }
230
        });
231
232
        private volatile boolean listenersInited;
233
        private volatile boolean broken;         //Represents a state where project has a broken reference repairable by broken reference support
234
        private volatile boolean compileOnSaveDisabled;  //true iff Compile-on-Save is disabled
235
236
237
        public LogicalViewProviderImpl(
238
                @NonNull final Project project,
239
                @NonNull final PropertyEvaluator evaluator,
240
                @NonNull final String projectType,
241
                @NullAllowed final HelpCtx helpContext,
242
                @NullAllowed final CompileOnSaveBadge badgeStatus) {
243
            Parameters.notNull("project", project); //NOI18N
244
            Parameters.notNull("evaluator", evaluator); //NOI18N
245
            Parameters.notNull("projectType", projectType); //NOI18N
246
            this.project = project;
247
            this.evaluator = evaluator;
248
            this.projectType = projectType;
249
            this.helpContext = helpContext;
250
            this.badgeStatus = badgeStatus;
251
            pcl = new PropertyChangeListener() {
252
                @Override
253
                public void propertyChange(PropertyChangeEvent evt) {
254
                    final String propName = evt.getPropertyName();
255
                    if (ProjectProblemsProvider.PROP_PROBLEMS.equals(evt.getPropertyName()) ||
256
                        (badgeStatus != null && (propName == null || badgeStatus.isImportant(propName)))) {
257
                        testBroken();
258
                    }
259
                }
260
            };
261
        }
262
263
        private void initListeners() {
264
            if (listenersInited) {
265
                return;
266
            }
267
            ProjectManager.mutex().readAccess(new Runnable() {
268
                @Override
269
                public void run() {
270
                    synchronized (LogicalViewProviderImpl.class) {
271
                        if (!listenersInited) {
272
                            evaluator.addPropertyChangeListener(pcl);
273
                            final ProjectProblemsProvider ppp = project.getLookup().lookup(ProjectProblemsProvider.class);
274
                            if (ppp != null) {
275
                                ppp.addPropertyChangeListener(pcl);
276
                            }
277
                            listenersInited = true;
278
                        }
279
                    }
280
                }
281
            });
282
        }
283
284
        @Override
285
        public Node createLogicalView() {
286
            initListeners();
287
            final InstanceContent ic = new InstanceContent();
288
            ic.add(project);
289
            ic.add(project, new InstanceContent.Convertor<Project, FileObject>() {
290
                @Override
291
                public FileObject convert(Project obj) {
292
                    return obj.getProjectDirectory();
293
                }
294
                @Override
295
                public Class<? extends FileObject> type(Project obj) {
296
                    return FileObject.class;
297
                }
298
                @Override
299
                public String id(Project obj) {
300
                    final FileObject fo = obj.getProjectDirectory();
301
                    return fo == null ? "" : fo.getPath();  //NOI18N
302
                }
303
                @Override
304
                public String displayName(Project obj) {
305
                    return obj.toString();
306
                }
307
            });
308
            ic.add(project, new InstanceContent.Convertor<Project, DataObject>() {
309
                @Override
310
                public DataObject convert(Project obj) {
311
                    try {
312
                        final FileObject fo = obj.getProjectDirectory();
313
                        return fo == null ? null : DataObject.find(fo);
314
                    } catch (DataObjectNotFoundException ex) {
315
                        return null;
316
                    }
317
                }
318
                @Override
319
                public Class<? extends DataObject> type(Project obj) {
320
                    return DataObject.class;
321
                }
322
                @Override
323
                public String id(Project obj) {
324
                    final FileObject fo = obj.getProjectDirectory();
325
                    return fo == null ? "" : fo.getPath();  //NOI18N
326
                }
327
                @Override
328
                public String displayName(Project obj) {
329
                    return obj.toString();
330
                }
331
            });
332
            return new LogicalViewRootNode(new AbstractLookup(ic));
333
        }    
334
335
        @Override
336
        public Node findPath(Node root, Object target) {
337
            Project prj = root.getLookup().lookup(Project.class);
338
            if (prj == null) {
339
                return null;
340
            }
341
342
            if (target instanceof FileObject) {
343
                FileObject fo = (FileObject) target;
344
                if (isOtherProjectSource(fo, prj)) {
345
                    return null; // Don't waste time if project does not own the fo among sources
346
                }
347
348
                for (Node n : root.getChildren().getNodes(true)) {
349
                    Node result = PackageView.findPath(n, target);
350
                    if (result != null) {
351
                        return result;
352
                    }
353
                }
354
            }
355
356
            return null;
357
        }
358
359
        private static boolean isOtherProjectSource(
360
                @NonNull final FileObject fo,
361
                @NonNull final Project me) {
362
            final Project owner = FileOwnerQuery.getOwner(fo);
363
            if (owner == null) {
364
                return false;
365
            }
366
            if (me.equals(owner)) {
367
                return false;
368
            }
369
            for (SourceGroup sg : ProjectUtils.getSources(owner).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)) {
370
                if (FileUtil.isParentOf(sg.getRootFolder(), fo)) {
371
                    return true;
372
                }
373
            }
374
            return false;
375
        }
376
377
        public void addChangeListener(ChangeListener l) {
378
            changeSupport.addChangeListener(l);
379
        }
380
381
        public void removeChangeListener(ChangeListener l) {
382
            changeSupport.removeChangeListener(l);
383
        }
384
385
        @Override
386
        public void testBroken() {
387
            task.schedule(500);
388
        }
389
390
        private boolean isCompileOnSaveDisabled() {
391
            return badgeStatus != null && badgeStatus.isBadgeVisible();
392
        }
393
394
        private final class LogicalViewRootNode extends AbstractNode implements ChangeListener, PropertyChangeListener {
395
396
            private final ProjectInformation info;
397
398
            @SuppressWarnings("LeakingThisInConstructor")
399
            LogicalViewRootNode(@NonNull final Lookup lkp) {
400
                super(NodeFactorySupport.createCompositeChildren(
401
                  project,
402
                  String.format("Projects/%s/Nodes",projectType)),  //NOI18N
403
                  lkp);
404
                broken = ProjectProblems.isBroken(project);
405
                compileOnSaveDisabled = isCompileOnSaveDisabled();
406
                addChangeListener(WeakListeners.change(this, LogicalViewProviderImpl.this));
407
                final ProjectInformation pi = project.getLookup().lookup(ProjectInformation.class);
408
                info = pi != null ? pi : new SimpleInfo(project);
409
                info.addPropertyChangeListener(WeakListeners.propertyChange(this, info));
410
            }
411
412
            @Override
413
            public String getShortDescription() {
414
                String prjDirDispName = FileUtil.getFileDisplayName(project.getProjectDirectory());
415
                return NbBundle.getMessage(LogicalViewProviderImpl.class, "HINT_project_root_node", prjDirDispName);
416
            }
417
418
            @Override
419
            public String getHtmlDisplayName() {
420
                String dispName = super.getDisplayName();
421
                try {
422
                    dispName = XMLUtil.toElementContent(dispName);
423
                } catch (CharConversionException ex) {
424
                    return dispName;
425
                }
426
                return broken ? "<font color=\"#"+Integer.toHexString(getErrorForeground().getRGB() & 0xffffff) +"\">" + dispName + "</font>" : null; //NOI18N
427
            }
428
429
            @Override
430
            public void stateChanged(ChangeEvent e) {
431
                fireIconChange();
432
                fireOpenedIconChange();
433
                fireDisplayNameChange(null, null);
434
            }
435
436
            @Override
437
            public void propertyChange(PropertyChangeEvent evt) {
438
                RP.post(new Runnable() {
439
                    public @Override void run() {
440
                        fireNameChange(null, null);
441
                        fireDisplayNameChange(null, null);
442
                    }
443
                });
444
            }
445
446
            @Override
447
            public Action[] getActions( boolean context ) {
448
                return CommonProjectActions.forType(projectType);
449
            }
450
451
            @Override
452
            public boolean canRename() {
453
                return true;
454
            }
455
456
            @Override
457
            public String getName() {
458
                return info.getDisplayName();
459
            }
460
461
            @Override
462
            public void setName(String s) {
463
                DefaultProjectOperations.performDefaultRenameOperation(project, s);
464
            }
465
466
            @Override
467
            public Image getIcon(int type) {
468
                final Icon icon = info.getIcon();
469
                final Image img = icon == null ?
470
                    super.getIcon(type) :
471
                    ImageUtilities.icon2Image(icon);
472
                return !broken && compileOnSaveDisabled ?
473
                    ImageUtilities.mergeImages(img, compileOnSaveDisabledBadge, 8, 0) :
474
                    img;
475
            }
476
477
            @Override
478
            public Image getOpenedIcon(int type) {
479
                return getIcon(type);
480
            }
481
482
            @Override
483
            public HelpCtx getHelpCtx() {
484
                return helpContext == null ?
485
                    super.getHelpCtx() :
486
                    helpContext;
487
            }
488
489
        }
490
491
        // Private methods -------------------------------------------------
492
493
        private void setBroken(boolean broken) {
494
            //Weak consistent, only visibility required
495
            if (this.broken != broken) {
496
                this.broken = broken;
497
                changeSupport.fireChange();
498
            }
499
        }
500
501
        private void setCompileOnSaveDisabled (boolean value) {
502
            //Weak consistent, only visibility required
503
            if (this.compileOnSaveDisabled != value) {
504
                this.compileOnSaveDisabled = value;
505
                changeSupport.fireChange();
506
            }
507
        }
508
509
510
        @NonNull
511
        private static Color getErrorForeground() {
512
            Color result = UIManager.getDefaults().getColor("nb.errorForeground");  //NOI18N
513
            if (result == null) {
514
                result = Color.RED;
515
            }
516
            return result;
517
        }
518
    }
519
520
    private static final class SimpleInfo implements ProjectInformation {
521
522
        private final Project project;
523
524
        SimpleInfo(@NonNull final Project project) {
525
            Parameters.notNull("project", project); //NOI18N
526
            this.project = project;
527
        }
528
529
        @Override
530
        public String getName() {
531
            return project.getProjectDirectory().getName();
532
        }
533
534
        @Override
535
        public String getDisplayName() {
536
            return getName();
537
        }
538
539
        @Override
540
        public Icon getIcon() {
541
            return null;
542
        }
543
544
        @Override
545
        public Project getProject() {
546
            return project;
547
        }
548
549
        @Override
550
        public void addPropertyChangeListener(PropertyChangeListener listener) {
551
            //Immutable
552
        }
553
554
        @Override
555
        public void removePropertyChangeListener(PropertyChangeListener listener) {
556
            ////Immutable
557
        }
558
    }
559
}
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java (-4 / +26 lines)
Lines 91-99 Link Here
91
import org.netbeans.modules.java.api.common.classpath.ClassPathProviderImpl;
91
import org.netbeans.modules.java.api.common.classpath.ClassPathProviderImpl;
92
import org.netbeans.modules.java.api.common.project.ProjectHooks;
92
import org.netbeans.modules.java.api.common.project.ProjectHooks;
93
import org.netbeans.modules.java.api.common.project.ProjectProperties;
93
import org.netbeans.modules.java.api.common.project.ProjectProperties;
94
import org.netbeans.modules.java.api.common.project.ui.LogicalViewProviders;
94
import org.netbeans.modules.java.api.common.queries.QuerySupport;
95
import org.netbeans.modules.java.api.common.queries.QuerySupport;
95
import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator;
96
import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator;
96
import org.netbeans.modules.java.j2seproject.ui.J2SELogicalViewProvider;
97
import org.netbeans.modules.java.j2seproject.ui.customizer.CustomizerProviderImpl;
97
import org.netbeans.modules.java.j2seproject.ui.customizer.CustomizerProviderImpl;
98
import org.netbeans.modules.project.ui.spi.TemplateCategorySorter;
98
import org.netbeans.modules.project.ui.spi.TemplateCategorySorter;
99
import org.netbeans.spi.java.project.support.ExtraSourceJavadocSupport;
99
import org.netbeans.spi.java.project.support.ExtraSourceJavadocSupport;
Lines 136-141 Link Here
136
import org.openide.filesystems.URLMapper;
136
import org.openide.filesystems.URLMapper;
137
import org.openide.loaders.DataObject;
137
import org.openide.loaders.DataObject;
138
import org.openide.modules.SpecificationVersion;
138
import org.openide.modules.SpecificationVersion;
139
import org.openide.util.HelpCtx;
139
/**
140
/**
140
 * Represents one plain J2SE project.
141
 * Represents one plain J2SE project.
141
 * @author Jesse Glick, et al.
142
 * @author Jesse Glick, et al.
Lines 344-350 Link Here
344
345
345
    private Lookup createLookup(final AuxiliaryConfiguration aux, final J2SEProjectOperations ops) {
346
    private Lookup createLookup(final AuxiliaryConfiguration aux, final J2SEProjectOperations ops) {
346
        final FileEncodingQueryImplementation encodingQuery = QuerySupport.createFileEncodingQuery(evaluator(), ProjectProperties.SOURCE_ENCODING);
347
        final FileEncodingQueryImplementation encodingQuery = QuerySupport.createFileEncodingQuery(evaluator(), ProjectProperties.SOURCE_ENCODING);
347
        final J2SELogicalViewProvider lvp = new J2SELogicalViewProvider(this, this.updateHelper, evaluator(), refHelper);
348
        final Lookup base = Lookups.fixed(
348
        final Lookup base = Lookups.fixed(
349
            J2SEProject.this,
349
            J2SEProject.this,
350
            QuerySupport.createProjectInformation(updateHelper, this, J2SE_PROJECT_ICON),
350
            QuerySupport.createProjectInformation(updateHelper, this, J2SE_PROJECT_ICON),
Lines 352-358 Link Here
352
            helper.createCacheDirectoryProvider(),
352
            helper.createCacheDirectoryProvider(),
353
            helper.createAuxiliaryProperties(),
353
            helper.createAuxiliaryProperties(),
354
            refHelper.createSubprojectProvider(),
354
            refHelper.createSubprojectProvider(),
355
            lvp,
355
            LogicalViewProviders.createBuilder(
356
                this,
357
                eval,
358
                "org-netbeans-modules-java-j2seproject").   //NOI18N
359
                setHelpCtx(new HelpCtx("org.netbeans.modules.java.j2seproject.ui.J2SELogicalViewProvider.J2SELogicalViewRootNode")).    //NOI18N
360
                setCompileOnSaveBadge(newCoSBadge()).
361
                build(),
356
            // new J2SECustomizerProvider(this, this.updateHelper, evaluator(), refHelper),
362
            // new J2SECustomizerProvider(this, this.updateHelper, evaluator(), refHelper),
357
            new CustomizerProviderImpl(this, this.updateHelper, evaluator(), refHelper, this.genFilesHelper),        
363
            new CustomizerProviderImpl(this, this.updateHelper, evaluator(), refHelper, this.genFilesHelper),        
358
            LookupMergerSupport.createClassPathProviderMerger(cpProvider),
364
            LookupMergerSupport.createClassPathProviderMerger(cpProvider),
Lines 410-416 Link Here
410
            QuerySupport.createAnnotationProcessingQuery(this.helper, this.evaluator(), ProjectProperties.ANNOTATION_PROCESSING_ENABLED, ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR, ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS, ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST, ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT, ProjectProperties.ANNOTATION_PROCESSING_PROCESSOR_OPTIONS),
416
            QuerySupport.createAnnotationProcessingQuery(this.helper, this.evaluator(), ProjectProperties.ANNOTATION_PROCESSING_ENABLED, ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR, ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS, ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST, ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT, ProjectProperties.ANNOTATION_PROCESSING_PROCESSOR_OPTIONS),
411
            LookupProviderSupport.createActionProviderMerger(),
417
            LookupProviderSupport.createActionProviderMerger(),
412
            WhiteListQueryMergerSupport.createWhiteListQueryMerger(),
418
            WhiteListQueryMergerSupport.createWhiteListQueryMerger(),
413
            BrokenReferencesSupport.createReferenceProblemsProvider(helper, refHelper, eval, lvp.getBreakableProperties(), lvp.getPlatformProperties()),
419
            BrokenReferencesSupport.createReferenceProblemsProvider(helper, refHelper, eval, J2SEProjectUtil.getBreakableProperties(this), new String[]{ProjectProperties.PLATFORM_ACTIVE}),
414
            BrokenReferencesSupport.createPlatformVersionProblemProvider(helper, eval, new PlatformChangedHook(), JavaPlatform.getDefault().getSpecification().getName(), ProjectProperties.PLATFORM_ACTIVE, ProjectProperties.JAVAC_SOURCE, ProjectProperties.JAVAC_TARGET),
420
            BrokenReferencesSupport.createPlatformVersionProblemProvider(helper, eval, new PlatformChangedHook(), JavaPlatform.getDefault().getSpecification().getName(), ProjectProperties.PLATFORM_ACTIVE, ProjectProperties.JAVAC_SOURCE, ProjectProperties.JAVAC_TARGET),
415
            BrokenReferencesSupport.createProfileProblemProvider(helper, refHelper, eval, ProjectProperties.JAVAC_PROFILE, ProjectProperties.RUN_CLASSPATH, ProjectProperties.ENDORSED_CLASSPATH),
421
            BrokenReferencesSupport.createProfileProblemProvider(helper, refHelper, eval, ProjectProperties.JAVAC_PROFILE, ProjectProperties.RUN_CLASSPATH, ProjectProperties.ENDORSED_CLASSPATH),
416
            UILookupMergerSupport.createProjectProblemsProviderMerger(),
422
            UILookupMergerSupport.createProjectProblemsProviderMerger(),
Lines 975-978 Link Here
975
            }
981
            }
976
        };
982
        };
977
    }
983
    }
984
985
    @NonNull
986
    private LogicalViewProviders.CompileOnSaveBadge newCoSBadge() {
987
        return new LogicalViewProviders.CompileOnSaveBadge() {
988
            @Override
989
            public boolean isBadgeVisible() {
990
                return !J2SEProjectUtil.isCompileOnSaveEnabled(J2SEProject.this) &&
991
                    J2SEProjectUtil.isCompileOnSaveSupported(J2SEProject.this);
992
            }
993
            @Override
994
            public boolean isImportant(@NonNull final String propertyName) {
995
                return ProjectProperties.COMPILE_ON_SAVE.equals(propertyName) ||
996
                propertyName.startsWith(ProjectProperties.COMPILE_ON_SAVE_UNSUPPORTED_PREFIX);
997
            }
998
        };
999
    }
978
}
1000
}
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProjectUtil.java (+28 lines)
Lines 50-56 Link Here
50
import java.util.Map;
50
import java.util.Map;
51
import java.util.Map.Entry;
51
import java.util.Map.Entry;
52
import java.util.logging.Logger;
52
import java.util.logging.Logger;
53
import org.netbeans.api.annotations.common.NonNull;
53
import org.netbeans.api.project.Project;
54
import org.netbeans.api.project.Project;
55
import org.netbeans.modules.java.api.common.SourceRoots;
54
import org.netbeans.modules.java.api.common.project.ProjectProperties;
56
import org.netbeans.modules.java.api.common.project.ProjectProperties;
55
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
57
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
56
import org.openide.filesystems.FileObject;
58
import org.openide.filesystems.FileObject;
Lines 63-68 Link Here
63
 */
65
 */
64
public class J2SEProjectUtil {
66
public class J2SEProjectUtil {
65
67
68
    private static final String[] BREAKABLE_PROPERTIES = {
69
        ProjectProperties.JAVAC_CLASSPATH,
70
        ProjectProperties.RUN_CLASSPATH,
71
        ProjectProperties.DEBUG_CLASSPATH,
72
        ProjectProperties.RUN_TEST_CLASSPATH,
73
        ProjectProperties.DEBUG_TEST_CLASSPATH,
74
        ProjectProperties.ENDORSED_CLASSPATH,
75
        ProjectProperties.JAVAC_TEST_CLASSPATH,
76
    };
77
66
    private static final Logger LOG = Logger.getLogger(J2SEProjectUtil.class.getName());
78
    private static final Logger LOG = Logger.getLogger(J2SEProjectUtil.class.getName());
67
79
68
    private J2SEProjectUtil () {}
80
    private J2SEProjectUtil () {}
Lines 159-162 Link Here
159
               "on".equalsIgnoreCase(param);        //NOI18N
171
               "on".equalsIgnoreCase(param);        //NOI18N
160
    }
172
    }
161
173
174
    /**
175
     * Returns a list of property names which need to be tested for broken references.
176
     * @param project to return property names for
177
     * @return the list of breakable properties
178
     */
179
    public static String[] getBreakableProperties(@NonNull final J2SEProject project) {
180
        SourceRoots roots = project.getSourceRoots();
181
        String[] srcRootProps = roots.getRootProperties();
182
        roots = project.getTestSourceRoots();
183
        String[] testRootProps = roots.getRootProperties();
184
        String[] result = new String [BREAKABLE_PROPERTIES.length + srcRootProps.length + testRootProps.length];
185
        System.arraycopy(BREAKABLE_PROPERTIES, 0, result, 0, BREAKABLE_PROPERTIES.length);
186
        System.arraycopy(srcRootProps, 0, result, BREAKABLE_PROPERTIES.length, srcRootProps.length);
187
        System.arraycopy(testRootProps, 0, result, BREAKABLE_PROPERTIES.length + srcRootProps.length, testRootProps.length);
188
        return result;
189
    }
162
}
190
}
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/Bundle.properties (-2 lines)
Lines 83-91 Link Here
83
TXT_UnknownProjectName=???
83
TXT_UnknownProjectName=???
84
TXT_ProjectArtifactFormat={0} - {1}
84
TXT_ProjectArtifactFormat={0} - {1}
85
CTL_OpenProject=Open Project
85
CTL_OpenProject=Open Project
86
HINT_project_root_node=Java project in {0}
87
86
88
#RemoveClassPathRootAction
87
#RemoveClassPathRootAction
89
CTL_RemoveProject=Remove
88
CTL_RemoveProject=Remove
90
89
91
TP_CompileOnSaveDisabled=Compile on Save is disabled. It can be enabled in Project Properties.
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java (-438 lines)
Lines 1-438 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.java.j2seproject.ui;
46
47
import java.awt.Color;
48
import java.awt.Image;
49
import java.beans.PropertyChangeEvent;
50
import java.beans.PropertyChangeListener;
51
import java.io.CharConversionException;
52
import java.net.URL;
53
import javax.swing.Action;
54
import javax.swing.UIManager;
55
import javax.swing.event.ChangeEvent;
56
import javax.swing.event.ChangeListener;
57
import org.netbeans.api.annotations.common.NonNull;
58
import org.netbeans.api.java.project.JavaProjectConstants;
59
import org.netbeans.api.project.FileOwnerQuery;
60
import org.netbeans.api.project.Project;
61
import org.netbeans.api.project.ProjectInformation;
62
import org.netbeans.api.project.ProjectManager;
63
import org.netbeans.api.project.ProjectUtils;
64
import org.netbeans.api.project.SourceGroup;
65
import org.netbeans.api.project.ui.ProjectProblems;
66
import org.netbeans.modules.java.api.common.SourceRoots;
67
import org.netbeans.modules.java.api.common.ant.UpdateHelper;
68
import org.netbeans.modules.java.api.common.project.ProjectProperties;
69
import org.netbeans.modules.java.api.common.project.ui.LogicalViewProvider2;
70
import org.netbeans.modules.java.j2seproject.J2SEProjectUtil;
71
import org.netbeans.modules.java.j2seproject.J2SEProject;
72
import org.netbeans.spi.java.project.support.ui.PackageView;
73
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
74
import org.netbeans.spi.project.support.ant.ReferenceHelper;
75
import org.netbeans.spi.project.ui.ProjectProblemsProvider;
76
import org.netbeans.spi.project.ui.support.CommonProjectActions;
77
import org.netbeans.spi.project.ui.support.NodeFactorySupport;
78
import org.netbeans.spi.project.ui.support.DefaultProjectOperations;
79
import org.openide.awt.ActionID;
80
import org.openide.awt.ActionReference;
81
import org.openide.awt.ActionReferences;
82
import org.openide.filesystems.FileObject;
83
import org.openide.filesystems.FileUtil;
84
import org.openide.loaders.DataObject;
85
import org.openide.loaders.DataObjectNotFoundException;
86
import org.openide.nodes.AbstractNode;
87
import org.openide.nodes.Node;
88
import org.openide.util.ChangeSupport;
89
import org.openide.util.HelpCtx;
90
import org.openide.util.ImageUtilities;
91
import org.openide.util.Lookup;
92
import org.openide.util.NbBundle;
93
import org.openide.util.RequestProcessor;
94
import org.openide.util.WeakListeners;
95
import org.openide.util.lookup.AbstractLookup;
96
import org.openide.util.lookup.InstanceContent;
97
import org.openide.xml.XMLUtil;
98
99
/**
100
 * Support for creating logical views.
101
 * @author Petr Hrebejk
102
 */
103
@ActionReferences({
104
    @ActionReference(
105
        id=@ActionID(id="org.netbeans.modules.project.ui.problems.BrokenProjectActionFactory",category="Project"),
106
        position = 2600,
107
        path = "Projects/org-netbeans-modules-java-j2seproject/Actions")
108
})
109
public class J2SELogicalViewProvider implements LogicalViewProvider2 {
110
    
111
    private static final RequestProcessor RP = new RequestProcessor(J2SELogicalViewProvider.class);
112
    private static final String[] BREAKABLE_PROPERTIES = {
113
        ProjectProperties.JAVAC_CLASSPATH,
114
        ProjectProperties.RUN_CLASSPATH,
115
        ProjectProperties.DEBUG_CLASSPATH,
116
        ProjectProperties.RUN_TEST_CLASSPATH,
117
        ProjectProperties.DEBUG_TEST_CLASSPATH,
118
        ProjectProperties.ENDORSED_CLASSPATH,
119
        ProjectProperties.JAVAC_TEST_CLASSPATH,
120
    };
121
    private static final String COMPILE_ON_SAVE_DISABLED_BADGE_PATH = "org/netbeans/modules/java/j2seproject/ui/resources/compileOnSaveDisabledBadge.gif";
122
    private static final Image compileOnSaveDisabledBadge;
123
124
    static {
125
        URL errorBadgeIconURL = J2SELogicalViewProvider.class.getClassLoader().getResource(COMPILE_ON_SAVE_DISABLED_BADGE_PATH);
126
        String compileOnSaveDisabledTP = "<img src=\"" + errorBadgeIconURL + "\">&nbsp;" + NbBundle.getMessage(J2SELogicalViewProvider.class, "TP_CompileOnSaveDisabled");
127
        compileOnSaveDisabledBadge = ImageUtilities.assignToolTipToImage(ImageUtilities.loadImage(COMPILE_ON_SAVE_DISABLED_BADGE_PATH), compileOnSaveDisabledTP); // NOI18N
128
    }
129
    
130
    private final J2SEProject project;
131
    private final UpdateHelper helper;
132
    private final PropertyEvaluator evaluator;
133
    private final ReferenceHelper resolver;
134
    private final ChangeSupport changeSupport = new ChangeSupport(this);
135
    private final PropertyChangeListener pcl;
136
    private final RequestProcessor.Task task = RP.create(new Runnable() {
137
        public @Override void run() {
138
            setBroken(ProjectProblems.isBroken(project));
139
            setCompileOnSaveDisabled(isCompileOnSaveDisabled());
140
        }
141
    });
142
143
    private volatile boolean listenersInited;
144
    private volatile boolean broken;         //Represents a state where project has a broken reference repairable by broken reference support
145
    private volatile boolean compileOnSaveDisabled;  //true iff Compile-on-Save is disabled
146
    
147
    public J2SELogicalViewProvider(J2SEProject project, UpdateHelper helper, PropertyEvaluator evaluator, ReferenceHelper resolver) {
148
        this.project = project;
149
        assert project != null;
150
        this.helper = helper;
151
        assert helper != null;
152
        this.evaluator = evaluator;
153
        assert evaluator != null;
154
        this.resolver = resolver;
155
        assert resolver != null;
156
        pcl = new PropertyChangeListener() {
157
            public @Override void propertyChange(PropertyChangeEvent evt) {
158
                final String propName = evt.getPropertyName();
159
                if (propName == null ||
160
                    ProjectProblemsProvider.PROP_PROBLEMS.equals(evt.getPropertyName()) ||
161
                    ProjectProperties.COMPILE_ON_SAVE.equals(evt.getPropertyName()) ||
162
                    propName.startsWith(ProjectProperties.COMPILE_ON_SAVE_UNSUPPORTED_PREFIX)) {
163
                    testBroken();
164
                }
165
            }
166
        };
167
    }
168
169
    private void initListeners() {
170
        if (listenersInited) {
171
            return;
172
        }
173
        ProjectManager.mutex().readAccess(new Runnable() {
174
            @Override
175
            public void run() {
176
                synchronized (J2SELogicalViewProvider.class) {
177
                    if (!listenersInited) {
178
                        evaluator.addPropertyChangeListener(pcl);
179
                        final ProjectProblemsProvider ppp = project.getLookup().lookup(ProjectProblemsProvider.class);
180
                        if (ppp != null) {
181
                            ppp.addPropertyChangeListener(pcl);
182
                        }
183
                        listenersInited = true;
184
                    }
185
                }
186
            }
187
        });
188
    }
189
    
190
    @Override
191
    public Node createLogicalView() {
192
        initListeners();
193
        final InstanceContent ic = new InstanceContent();
194
        ic.add(project);
195
        ic.add(project, new InstanceContent.Convertor<J2SEProject, FileObject>() {
196
            @Override
197
            public FileObject convert(J2SEProject obj) {
198
                return obj.getProjectDirectory();
199
            }
200
            @Override
201
            public Class<? extends FileObject> type(J2SEProject obj) {
202
                return FileObject.class;
203
            }
204
            @Override
205
            public String id(J2SEProject obj) {
206
                final FileObject fo = obj.getProjectDirectory();
207
                return fo == null ? "" : fo.getPath();  //NOI18N
208
            }
209
            @Override
210
            public String displayName(J2SEProject obj) {
211
                return obj.toString();
212
            }
213
        });
214
        ic.add(project, new InstanceContent.Convertor<J2SEProject, DataObject>() {
215
            @Override
216
            public DataObject convert(J2SEProject obj) {
217
                try {
218
                    final FileObject fo = obj.getProjectDirectory();
219
                    return fo == null ? null : DataObject.find(fo);
220
                } catch (DataObjectNotFoundException ex) {
221
                    return null;
222
                }
223
            }
224
            @Override
225
            public Class<? extends DataObject> type(J2SEProject obj) {
226
                return DataObject.class;
227
            }
228
            @Override
229
            public String id(J2SEProject obj) {
230
                final FileObject fo = obj.getProjectDirectory();
231
                return fo == null ? "" : fo.getPath();  //NOI18N
232
            }
233
            @Override
234
            public String displayName(J2SEProject obj) {
235
                return obj.toString();
236
            }
237
        });
238
        return new J2SELogicalViewRootNode(new AbstractLookup(ic));
239
    }
240
    
241
    public PropertyEvaluator getEvaluator() {
242
        return evaluator;
243
    }
244
    
245
    public ReferenceHelper getRefHelper() {
246
        return resolver;
247
    }
248
    
249
    public UpdateHelper getUpdateHelper() {
250
        return helper;
251
    }
252
    
253
    @Override
254
    public Node findPath(Node root, Object target) {
255
        Project prj = root.getLookup().lookup(Project.class);
256
        if (prj == null) {
257
            return null;
258
        }
259
        
260
        if (target instanceof FileObject) {
261
            FileObject fo = (FileObject) target;
262
            if (isOtherProjectSource(fo, prj)) {
263
                return null; // Don't waste time if project does not own the fo among sources
264
            }
265
            
266
            for (Node n : root.getChildren().getNodes(true)) {
267
                Node result = PackageView.findPath(n, target);
268
                if (result != null) {
269
                    return result;
270
                }
271
            }
272
        }
273
        
274
        return null;
275
    }
276
277
    private static boolean isOtherProjectSource(
278
            @NonNull final FileObject fo,
279
            @NonNull final Project me) {
280
        final Project owner = FileOwnerQuery.getOwner(fo);
281
        if (owner == null) {
282
            return false;
283
        }
284
        if (me.equals(owner)) {
285
            return false;
286
        }
287
        for (SourceGroup sg : ProjectUtils.getSources(owner).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)) {
288
            if (FileUtil.isParentOf(sg.getRootFolder(), fo)) {
289
                return true;
290
            }
291
        }
292
        return false;
293
    }
294
            
295
    public void addChangeListener(ChangeListener l) {
296
        changeSupport.addChangeListener(l);
297
    }
298
    
299
    public void removeChangeListener(ChangeListener l) {
300
        changeSupport.removeChangeListener(l);
301
    }
302
303
    @Override
304
    public void testBroken() {
305
        task.schedule(500);
306
    }
307
308
    public String[] getBreakableProperties() {
309
        SourceRoots roots = this.project.getSourceRoots();
310
        String[] srcRootProps = roots.getRootProperties();
311
        roots = this.project.getTestSourceRoots();
312
        String[] testRootProps = roots.getRootProperties();
313
        String[] result = new String [BREAKABLE_PROPERTIES.length + srcRootProps.length + testRootProps.length];
314
        System.arraycopy(BREAKABLE_PROPERTIES, 0, result, 0, BREAKABLE_PROPERTIES.length);
315
        System.arraycopy(srcRootProps, 0, result, BREAKABLE_PROPERTIES.length, srcRootProps.length);
316
        System.arraycopy(testRootProps, 0, result, BREAKABLE_PROPERTIES.length + srcRootProps.length, testRootProps.length);
317
        return result;
318
    }
319
320
    public String[] getPlatformProperties() {
321
        return new String[] {ProjectProperties.PLATFORM_ACTIVE};
322
    }
323
    
324
    private boolean isCompileOnSaveDisabled() {
325
         return !J2SEProjectUtil.isCompileOnSaveEnabled(project) && J2SEProjectUtil.isCompileOnSaveSupported(project);
326
    }                
327
328
    private final class J2SELogicalViewRootNode extends AbstractNode implements ChangeListener, PropertyChangeListener {
329
330
        private final ProjectInformation info = ProjectUtils.getInformation(project);        
331
        
332
        @SuppressWarnings("LeakingThisInConstructor")
333
        J2SELogicalViewRootNode(@NonNull final Lookup lkp) {
334
            super(NodeFactorySupport.createCompositeChildren(project, "Projects/org-netbeans-modules-java-j2seproject/Nodes"), 
335
                  lkp);
336
            setIconBaseWithExtension("org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png");
337
            broken = ProjectProblems.isBroken(project);
338
            compileOnSaveDisabled = isCompileOnSaveDisabled();
339
            addChangeListener(WeakListeners.change(this, J2SELogicalViewProvider.this));
340
            info.addPropertyChangeListener(WeakListeners.propertyChange(this, info));
341
        }
342
343
        @Override
344
        public String getShortDescription() {
345
            String prjDirDispName = FileUtil.getFileDisplayName(project.getProjectDirectory());
346
            return NbBundle.getMessage(J2SELogicalViewProvider.class, "HINT_project_root_node", prjDirDispName);
347
        }
348
        
349
        @Override
350
        public String getHtmlDisplayName() {
351
            String dispName = super.getDisplayName();
352
            try {
353
                dispName = XMLUtil.toElementContent(dispName);
354
            } catch (CharConversionException ex) {
355
                return dispName;
356
            }            
357
            return broken ? "<font color=\"#"+Integer.toHexString(getErrorForeground().getRGB() & 0xffffff) +"\">" + dispName + "</font>" : null; //NOI18N
358
        }
359
        
360
        @Override
361
        public Image getIcon(int type) {
362
            final Image original = super.getIcon(type);
363
            return !broken && compileOnSaveDisabled ? ImageUtilities.mergeImages(original, compileOnSaveDisabledBadge, 8, 0) : original;
364
        }
365
        
366
        @Override
367
        public Image getOpenedIcon(int type) {
368
            final Image original = super.getOpenedIcon(type);
369
            return !broken && compileOnSaveDisabled ? ImageUtilities.mergeImages(original, compileOnSaveDisabledBadge, 8, 0) : original;
370
        }
371
        
372
        public @Override void stateChanged(ChangeEvent e) {
373
            fireIconChange();
374
            fireOpenedIconChange();
375
            fireDisplayNameChange(null, null);
376
        }
377
378
        public @Override void propertyChange(PropertyChangeEvent evt) {
379
            RP.post(new Runnable() {
380
                public @Override void run() {
381
                    fireNameChange(null, null);
382
                    fireDisplayNameChange(null, null);
383
                }
384
            });
385
        }
386
387
        @Override
388
        public Action[] getActions( boolean context ) {
389
            return CommonProjectActions.forType("org-netbeans-modules-java-j2seproject"); // NOI18N
390
        }
391
        
392
        @Override
393
        public boolean canRename() {
394
            return true;
395
        }
396
        
397
        public @Override String getName() {
398
            return info.getDisplayName();
399
        }
400
401
        @Override
402
        public void setName(String s) {
403
            DefaultProjectOperations.performDefaultRenameOperation(project, s);
404
        }
405
        
406
        @Override
407
        public HelpCtx getHelpCtx() {
408
            return new HelpCtx(J2SELogicalViewRootNode.class);
409
        }
410
411
    }    
412
413
    // Private methods -------------------------------------------------
414
415
    private void setBroken(boolean broken) {
416
        //Weak consistent, only visibility required
417
        if (this.broken != broken) {
418
            this.broken = broken;
419
            changeSupport.fireChange();
420
        }
421
    }    
422
423
    private void setCompileOnSaveDisabled (boolean value) {
424
        //Weak consistent, only visibility required
425
        if (this.compileOnSaveDisabled != value) {
426
            this.compileOnSaveDisabled = value;
427
            changeSupport.fireChange();
428
        }
429
    }
430
431
    private static @NonNull Color getErrorForeground() {
432
        Color result = UIManager.getDefaults().getColor("nb.errorForeground");  //NOI18N
433
        if (result == null) {
434
            result = Color.RED;
435
        }
436
        return result;
437
    }    
438
}
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/LibrariesNodeFactory.java (-8 / +9 lines)
Lines 54-59 Link Here
54
import javax.swing.Action;
54
import javax.swing.Action;
55
import javax.swing.SwingUtilities;
55
import javax.swing.SwingUtilities;
56
import javax.swing.event.ChangeListener;
56
import javax.swing.event.ChangeListener;
57
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.api.project.Project;
58
import org.netbeans.api.project.Project;
58
import org.netbeans.modules.java.api.common.SourceRoots;
59
import org.netbeans.modules.java.api.common.SourceRoots;
59
import org.netbeans.modules.java.api.common.ant.UpdateHelper;
60
import org.netbeans.modules.java.api.common.ant.UpdateHelper;
Lines 70-75 Link Here
70
import org.openide.nodes.Node;
71
import org.openide.nodes.Node;
71
import org.openide.util.ChangeSupport;
72
import org.openide.util.ChangeSupport;
72
import org.openide.util.NbBundle;
73
import org.openide.util.NbBundle;
74
import org.openide.util.Parameters;
73
import org.openide.util.Utilities;
75
import org.openide.util.Utilities;
74
76
75
/**
77
/**
Lines 102-115 Link Here
102
        private ReferenceHelper resolver;
104
        private ReferenceHelper resolver;
103
        private final ClassPathSupport cs;
105
        private final ClassPathSupport cs;
104
        
106
        
105
        LibrariesNodeList(J2SEProject proj) {
107
        LibrariesNodeList(@NonNull final J2SEProject proj) {
108
            Parameters.notNull("proj", proj);   //NOI18N
106
            project = proj;
109
            project = proj;
107
            testSources = project.getTestSourceRoots();
110
            testSources = project.getTestSourceRoots();
108
            J2SELogicalViewProvider logView = project.getLookup().lookup(J2SELogicalViewProvider.class);
111
            evaluator = project.evaluator();
109
            assert logView != null;
112
            helper = project.getUpdateHelper();
110
            evaluator = logView.getEvaluator();
113
            resolver = project.getReferenceHelper();
111
            helper = logView.getUpdateHelper();
112
            resolver = logView.getRefHelper();
113
            cs = new ClassPathSupport(evaluator, resolver, helper.getAntProjectHelper(), helper, null);
114
            cs = new ClassPathSupport(evaluator, resolver, helper.getAntProjectHelper(), helper, null);
114
        }
115
        }
115
        
116
        
Lines 143-149 Link Here
143
            if (key == LIBRARIES) {
144
            if (key == LIBRARIES) {
144
                //Libraries Node
145
                //Libraries Node
145
                return  
146
                return  
146
                    new LibrariesNode(NbBundle.getMessage(J2SELogicalViewProvider.class,"CTL_LibrariesNode"),
147
                    new LibrariesNode(NbBundle.getMessage(LibrariesNodeFactory.class,"CTL_LibrariesNode"),
147
                        project, evaluator, helper, resolver, ProjectProperties.RUN_CLASSPATH,
148
                        project, evaluator, helper, resolver, ProjectProperties.RUN_CLASSPATH,
148
                        new String[] {ProjectProperties.BUILD_CLASSES_DIR},
149
                        new String[] {ProjectProperties.BUILD_CLASSES_DIR},
149
                        "platform.active", // NOI18N
150
                        "platform.active", // NOI18N
Lines 160-166 Link Here
160
                    );
161
                    );
161
            } else if (key == TEST_LIBRARIES) {
162
            } else if (key == TEST_LIBRARIES) {
162
                return  
163
                return  
163
                    new LibrariesNode(NbBundle.getMessage(J2SELogicalViewProvider.class,"CTL_TestLibrariesNode"),
164
                    new LibrariesNode(NbBundle.getMessage(LibrariesNodeFactory.class,"CTL_TestLibrariesNode"),
164
                        project, evaluator, helper, resolver, ProjectProperties.RUN_TEST_CLASSPATH,
165
                        project, evaluator, helper, resolver, ProjectProperties.RUN_TEST_CLASSPATH,
165
                        new String[] {
166
                        new String[] {
166
                            ProjectProperties.BUILD_TEST_CLASSES_DIR,
167
                            ProjectProperties.BUILD_TEST_CLASSES_DIR,
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerLibraries.java (-2 / +2 lines)
Lines 58-66 Link Here
58
import org.netbeans.api.project.libraries.LibraryManager;
58
import org.netbeans.api.project.libraries.LibraryManager;
59
import org.netbeans.modules.java.api.common.classpath.ClassPathSupport;
59
import org.netbeans.modules.java.api.common.classpath.ClassPathSupport;
60
import org.netbeans.modules.java.api.common.project.ui.ClassPathUiSupport;
60
import org.netbeans.modules.java.api.common.project.ui.ClassPathUiSupport;
61
import org.netbeans.modules.java.api.common.project.ui.LogicalViewProvider2;
61
import org.netbeans.modules.java.api.common.project.ui.customizer.EditMediator;
62
import org.netbeans.modules.java.api.common.project.ui.customizer.EditMediator;
62
import org.netbeans.modules.java.api.common.ui.PlatformUiSupport;
63
import org.netbeans.modules.java.api.common.ui.PlatformUiSupport;
63
import org.netbeans.modules.java.j2seproject.ui.J2SELogicalViewProvider;
64
import org.netbeans.spi.java.project.support.ui.SharableLibrariesUtils;
64
import org.netbeans.spi.java.project.support.ui.SharableLibrariesUtils;
65
import org.netbeans.spi.project.support.ant.PropertyUtils;
65
import org.netbeans.spi.project.support.ant.PropertyUtils;
66
import org.netbeans.spi.project.ui.support.ProjectCustomizer;
66
import org.netbeans.spi.project.ui.support.ProjectCustomizer;
Lines 298-304 Link Here
298
        else {
298
        else {
299
            category.setErrorMessage(null);
299
            category.setErrorMessage(null);
300
        }
300
        }
301
        J2SELogicalViewProvider viewProvider = uiProperties.getProject().getLookup().lookup(J2SELogicalViewProvider.class);
301
        LogicalViewProvider2 viewProvider = uiProperties.getProject().getLookup().lookup(LogicalViewProvider2.class);
302
        //Update the state of project's node if needed
302
        //Update the state of project's node if needed
303
        viewProvider.testBroken();
303
        viewProvider.testBroken();
304
    }
304
    }
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/package-info.java (+54 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
43
@ActionReferences({
44
    @ActionReference(
45
        id=@ActionID(id="org.netbeans.modules.project.ui.problems.BrokenProjectActionFactory",category="Project"),
46
        position = 2600,
47
        path = "Projects/org-netbeans-modules-java-j2seproject/Actions")
48
})
49
package org.netbeans.modules.java.j2seproject.ui;
50
51
import org.openide.awt.ActionID;
52
import org.openide.awt.ActionReference;
53
import org.openide.awt.ActionReferences;
54

Return to bug 237256