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

(-)a/java.j2seproject/nbproject/project.xml (-1 / +1 lines)
Lines 159-165 Link Here
159
                    <compile-dependency/>
159
                    <compile-dependency/>
160
                    <run-dependency>
160
                    <run-dependency>
161
                        <release-version>1</release-version>
161
                        <release-version>1</release-version>
162
                        <specification-version>1.48</specification-version>
162
                        <specification-version>1.53</specification-version>
163
                    </run-dependency>
163
                    </run-dependency>
164
                </dependency>
164
                </dependency>
165
                <dependency>
165
                <dependency>
(-)a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java (+1 lines)
Lines 406-411 Link Here
406
            WhiteListQueryMergerSupport.createWhiteListQueryMerger(),
406
            WhiteListQueryMergerSupport.createWhiteListQueryMerger(),
407
            BrokenReferencesSupport.createReferenceProblemsProvider(helper, refHelper, eval, lvp.getBreakableProperties(), lvp.getPlatformProperties()),
407
            BrokenReferencesSupport.createReferenceProblemsProvider(helper, refHelper, eval, lvp.getBreakableProperties(), lvp.getPlatformProperties()),
408
            BrokenReferencesSupport.createPlatformVersionProblemProvider(helper, eval, new PlatformChangedHook(), JavaPlatform.getDefault().getSpecification().getName(), J2SEProjectProperties.JAVA_PLATFORM, J2SEProjectProperties.JAVAC_SOURCE, J2SEProjectProperties.JAVAC_TARGET),
408
            BrokenReferencesSupport.createPlatformVersionProblemProvider(helper, eval, new PlatformChangedHook(), JavaPlatform.getDefault().getSpecification().getName(), J2SEProjectProperties.JAVA_PLATFORM, J2SEProjectProperties.JAVAC_SOURCE, J2SEProjectProperties.JAVAC_TARGET),
409
            BrokenReferencesSupport.createProfileProblemProvider(helper, refHelper, eval, J2SEProjectProperties.JAVAC_PROFILE, ProjectProperties.JAVAC_CLASSPATH, ProjectProperties.RUN_CLASSPATH, ProjectProperties.ENDORSED_CLASSPATH),
409
            UILookupMergerSupport.createProjectProblemsProviderMerger()
410
            UILookupMergerSupport.createProjectProblemsProviderMerger()
410
        );
411
        );
411
        lookup = base; // in case LookupProvider's call Project.getLookup
412
        lookup = base; // in case LookupProvider's call Project.getLookup
(-)a/java.project/apichanges.xml (+16 lines)
Lines 109-114 Link Here
109
    <!-- ACTUAL CHANGES BEGIN HERE: -->
109
    <!-- ACTUAL CHANGES BEGIN HERE: -->
110
110
111
    <changes>
111
    <changes>
112
        <change id="BrokenReferencesSupport-Profiles">
113
            <api name="general"/>
114
            <summary>Added <code>ProjectProblemsProvider</code> to resolve JDK 8 Profile problems</summary>
115
            <version major="1" minor="53"/>
116
            <date day="28" month="3" year="2013"/>
117
            <author login="tzezula"/>
118
            <compatibility addition="yes" deprecation="yes"/>
119
            <description>
120
                <p>
121
                    Added a factory method <code>createProfileProblemProvider</code> into <code>BrokenReferencesSupport</code>
122
                    creating a <code>ProjectProblemsProvider</code> resolving dependencies on libraries with higher or invalid profile.
123
                </p>
124
            </description>
125
            <class package="org.netbeans.spi.java.project.support.ui" name="BrokenReferencesSupport"/>
126
            <issue number="227831"/>
127
        </change>
112
        <change id="ProjectProblems">
128
        <change id="ProjectProblems">
113
            <api name="general"/>
129
            <api name="general"/>
114
            <summary>Changed <code>BrokenReferencesSupport</code> to delegate to <code>ProjectProblems</code></summary>
130
            <summary>Changed <code>BrokenReferencesSupport</code> to delegate to <code>ProjectProblems</code></summary>
(-)a/java.project/manifest.mf (-1 / +1 lines)
Lines 3-9 Link Here
3
OpenIDE-Module-Layer: org/netbeans/modules/java/project/layer.xml
3
OpenIDE-Module-Layer: org/netbeans/modules/java/project/layer.xml
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/project/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/project/Bundle.properties
5
OpenIDE-Module-Needs: javax.script.ScriptEngine.freemarker
5
OpenIDE-Module-Needs: javax.script.ScriptEngine.freemarker
6
OpenIDE-Module-Specification-Version: 1.52
6
OpenIDE-Module-Specification-Version: 1.53
7
OpenIDE-Module-Recommends: org.netbeans.spi.java.project.runner.JavaRunnerImplementation
7
OpenIDE-Module-Recommends: org.netbeans.spi.java.project.runner.JavaRunnerImplementation
8
AutoUpdate-Show-In-Client: false
8
AutoUpdate-Show-In-Client: false
9
9
(-)a/java.project/src/org/netbeans/modules/java/project/Bundle.properties (+9 lines)
Lines 107-109 Link Here
107
FixProjectSourceLevel.useOtherPlatform.text=Use Other Java &Platform
107
FixProjectSourceLevel.useOtherPlatform.text=Use Other Java &Platform
108
FixProjectSourceLevel.managePlatforms.text=&Manage Platforms...
108
FixProjectSourceLevel.managePlatforms.text=&Manage Platforms...
109
FixProjectSourceLevel.jLabel2.text=The project source/binary format requires a newer java platform ({0}).
109
FixProjectSourceLevel.jLabel2.text=The project source/binary format requires a newer java platform ({0}).
110
LBL_FixProfile_BrokenLibs=&The following project libraries have invalid value of profile:
111
LBL_FixProfile_remove=&Remove
112
TIP_FixProfile_Remove=Remove library from project
113
LBL_FixProfile_changeProfile=Change &Project Profile To:
114
AD_FixProfile_BrokenLibs=The libraries with higher or invalid value of JRE profile.
115
AD_FixProfile_changeProfile=Update project profile.
116
FixProfile.jLabel1.AccessibleContext.accessibleName=&The following project libraries have invalid value of profile:
117
AN_FixProfile_Profiles=Profiles
118
AD_FixProfile_Profiles=Profiles
(-)a/java.project/src/org/netbeans/modules/java/project/FixProfile.form (+141 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8" ?>
2
3
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
4
  <AuxValues>
5
    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
6
    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
7
    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
8
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
9
    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
10
    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
11
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
12
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
13
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
14
  </AuxValues>
15
16
  <Layout>
17
    <DimensionLayout dim="0">
18
      <Group type="103" groupAlignment="0" attributes="0">
19
          <Group type="102" attributes="0">
20
              <EmptySpace min="-2" max="-2" attributes="0"/>
21
              <Group type="103" groupAlignment="0" attributes="0">
22
                  <Group type="102" attributes="0">
23
                      <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
24
                      <EmptySpace pref="154" max="32767" attributes="0"/>
25
                  </Group>
26
                  <Group type="102" alignment="1" attributes="0">
27
                      <Group type="103" groupAlignment="1" attributes="0">
28
                          <Group type="102" alignment="0" attributes="0">
29
                              <Component id="changeProfile" min="-2" max="-2" attributes="0"/>
30
                              <EmptySpace max="-2" attributes="0"/>
31
                              <Component id="profiles" max="32767" attributes="0"/>
32
                          </Group>
33
                          <Component id="jScrollPane1" max="32767" attributes="0"/>
34
                      </Group>
35
                      <EmptySpace min="-2" max="-2" attributes="0"/>
36
                      <Component id="remove" min="-2" max="-2" attributes="0"/>
37
                      <EmptySpace max="-2" attributes="0"/>
38
                  </Group>
39
              </Group>
40
          </Group>
41
      </Group>
42
    </DimensionLayout>
43
    <DimensionLayout dim="1">
44
      <Group type="103" groupAlignment="0" attributes="0">
45
          <Group type="102" alignment="0" attributes="0">
46
              <EmptySpace max="-2" attributes="0"/>
47
              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
48
              <EmptySpace max="-2" attributes="0"/>
49
              <Group type="103" groupAlignment="0" attributes="0">
50
                  <Group type="102" attributes="0">
51
                      <Component id="remove" min="-2" max="-2" attributes="0"/>
52
                      <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
53
                  </Group>
54
                  <Component id="jScrollPane1" pref="212" max="32767" attributes="0"/>
55
              </Group>
56
              <EmptySpace max="-2" attributes="0"/>
57
              <Group type="103" groupAlignment="3" attributes="0">
58
                  <Component id="changeProfile" alignment="3" min="-2" max="-2" attributes="0"/>
59
                  <Component id="profiles" alignment="3" min="-2" max="-2" attributes="0"/>
60
              </Group>
61
              <EmptySpace max="-2" attributes="0"/>
62
          </Group>
63
      </Group>
64
    </DimensionLayout>
65
  </Layout>
66
  <SubComponents>
67
    <Component class="javax.swing.JLabel" name="jLabel1">
68
      <Properties>
69
        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
70
          <ComponentRef name="brokenLibs"/>
71
        </Property>
72
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
73
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="LBL_FixProfile_BrokenLibs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
74
        </Property>
75
      </Properties>
76
      <AccessibilityProperties>
77
        <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
78
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="FixProfile.jLabel1.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
79
        </Property>
80
      </AccessibilityProperties>
81
    </Component>
82
    <Component class="javax.swing.JButton" name="remove">
83
      <Properties>
84
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
85
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="LBL_FixProfile_remove" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
86
        </Property>
87
        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
88
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="TIP_FixProfile_Remove" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
89
        </Property>
90
      </Properties>
91
      <Events>
92
        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeLibrary"/>
93
      </Events>
94
    </Component>
95
    <Component class="javax.swing.JCheckBox" name="changeProfile">
96
      <Properties>
97
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
98
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="LBL_FixProfile_changeProfile" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
99
        </Property>
100
      </Properties>
101
      <AccessibilityProperties>
102
        <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
103
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="AD_FixProfile_changeProfile" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
104
        </Property>
105
      </AccessibilityProperties>
106
    </Component>
107
    <Component class="javax.swing.JComboBox" name="profiles">
108
      <Properties>
109
        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
110
          <StringArray count="0"/>
111
        </Property>
112
      </Properties>
113
      <AccessibilityProperties>
114
        <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
115
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="AN_FixProfile_Profiles" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
116
        </Property>
117
        <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
118
          <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="AD_FixProfile_Profiles" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
119
        </Property>
120
      </AccessibilityProperties>
121
    </Component>
122
    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
123
124
      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
125
      <SubComponents>
126
        <Component class="javax.swing.JList" name="brokenLibs">
127
          <Properties>
128
            <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
129
              <StringArray count="0"/>
130
            </Property>
131
          </Properties>
132
          <AccessibilityProperties>
133
            <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
134
              <ResourceString bundle="org/netbeans/modules/java/project/Bundle.properties" key="AD_FixProfile_BrokenLibs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
135
            </Property>
136
          </AccessibilityProperties>
137
        </Component>
138
      </SubComponents>
139
    </Container>
140
  </SubComponents>
141
</Form>
(-)a/java.project/src/org/netbeans/modules/java/project/FixProfile.java (+492 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
package org.netbeans.modules.java.project;
43
44
import java.awt.Component;
45
import java.awt.event.ActionEvent;
46
import java.awt.event.ActionListener;
47
import java.io.File;
48
import java.net.MalformedURLException;
49
import java.net.URI;
50
import java.net.URISyntaxException;
51
import java.net.URL;
52
import java.util.ArrayList;
53
import java.util.Collection;
54
import java.util.Collections;
55
import java.util.HashSet;
56
import java.util.List;
57
import java.util.Map;
58
import java.util.Set;
59
import java.util.regex.Matcher;
60
import java.util.regex.Pattern;
61
import javax.swing.AbstractListModel;
62
import javax.swing.DefaultListCellRenderer;
63
import javax.swing.JButton;
64
import javax.swing.JList;
65
import javax.swing.ListSelectionModel;
66
import javax.swing.event.ListDataEvent;
67
import javax.swing.event.ListDataListener;
68
import javax.swing.event.ListSelectionEvent;
69
import javax.swing.event.ListSelectionListener;
70
import org.netbeans.api.annotations.common.CheckForNull;
71
import org.netbeans.api.annotations.common.NonNull;
72
import org.netbeans.api.annotations.common.NullAllowed;
73
import org.openide.filesystems.FileUtil;
74
import org.openide.util.NbBundle;
75
import org.openide.util.Utilities;
76
77
/**
78
 *
79
 * @author Tomas Zezula
80
 */
81
public class FixProfile extends javax.swing.JPanel {
82
83
    private static final Pattern PROFILE_PATTERN = Pattern.compile("compact([123])"); //NOI18N
84
    private static final String PROFILE_FORMAT = "compact%d";   //NOI18N
85
    private static final int FULL_JRE = 4;
86
87
    private final JButton okOption;
88
    private final LibsModel libsModel;
89
    private String reqProfile;
90
91
    /**
92
     * Creates new form FixProfile
93
     */
94
    FixProfile(
95
            @NonNull final JButton okOption,
96
            @NonNull final String currentProfile,
97
            @NonNull final Map<String,Map<URI,String>> state) {
98
        assert okOption != null;
99
        assert currentProfile != null;
100
        assert state != null;
101
        this.okOption = okOption;
102
        this.libsModel = new LibsModel (currentProfile, state);
103
        libsModel.addListDataListener(new ListDataListener() {
104
            @Override
105
            public void intervalAdded(ListDataEvent lde) {
106
                checkOkOption();
107
            }
108
109
            @Override
110
            public void intervalRemoved(ListDataEvent lde) {
111
                checkOkOption();
112
            }
113
114
            @Override
115
            public void contentsChanged(ListDataEvent lde) {
116
                checkOkOption();
117
            }
118
        });
119
        this.reqProfile = requiredProfile(state);
120
        initComponents();
121
        remove.setEnabled(false);
122
        brokenLibs.setModel(libsModel);
123
        brokenLibs.setCellRenderer(new LibsRenderer());
124
        brokenLibs.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
125
        brokenLibs.addListSelectionListener(new ListSelectionListener() {
126
            @Override
127
            public void valueChanged(ListSelectionEvent lse) {
128
                remove.setEnabled(brokenLibs.getSelectedIndex() != -1);
129
            }
130
        });
131
        brokenLibs.setSelectedIndex(0);
132
        profiles.setRenderer(new ProfilesRenderer());
133
        changeProfile.addActionListener(new ActionListener() {
134
            @Override
135
            public void actionPerformed(ActionEvent ae) {
136
                libsModel.updateProfile(changeProfile.isSelected());
137
                checkOkOption();
138
            }
139
        });
140
        updateProfiles();
141
        checkOkOption();
142
    }
143
144
    boolean shouldUpdateProfile() {
145
        return changeProfile.isSelected();
146
    }
147
148
    @CheckForNull
149
    String getProfile() {
150
        final Object selObj = profiles.getSelectedItem();
151
        if (selObj instanceof Integer) {
152
            return getProfileName((Integer)selObj);
153
        } else {
154
            return null;
155
        }
156
    }
157
158
    @NonNull
159
    Collection<? extends URI> getRootsToRemove() {
160
        return libsModel.getRemovedRooots();
161
    }
162
163
    @CheckForNull
164
    static String normalize(@NullAllowed String profile) {
165
        return profile != null && PROFILE_PATTERN.matcher(profile).matches() ?
166
            profile :
167
            null;
168
    }
169
170
    @CheckForNull
171
    static String requiredProfile(@NonNull final Map<String,Map<URI,String>> state) {
172
        String current = null;
173
        for (Map.Entry<String,Map<URI,String>> cpe : state.entrySet()) {
174
            current = requiredProfile(cpe.getValue().entrySet(), current);
175
        }
176
        return current;
177
    }
178
    
179
    @CheckForNull
180
    private static String requiredProfile(
181
            @NonNull final Collection<? extends Map.Entry<URI,String>> state,
182
            @NullAllowed String current) {
183
        for (Map.Entry<URI,String> re : state) {
184
            current = max(current, re.getValue());
185
        }
186
        return current;
187
    }
188
189
    @CheckForNull
190
    private static String max(
191
        @NullAllowed String profileA,
192
        @NullAllowed String profileB) {
193
        profileA = normalize(profileA);
194
        profileB = normalize(profileB);
195
        if (profileA == null) {
196
            return profileB;
197
        }
198
        if (profileB == null) {
199
            return profileA;
200
        }
201
        return profileA.compareTo(profileB) < 0 ?
202
            profileB :
203
            profileA;
204
    }
205
206
    private static int getProfileIndex(@NullAllowed final String profileName) {
207
        if (profileName != null) {
208
            final Matcher m = PROFILE_PATTERN.matcher(profileName);
209
            if (m.matches()) {
210
                return Integer.parseInt(m.group(1));
211
            }
212
        }
213
        return FULL_JRE;
214
    }
215
216
    @CheckForNull
217
    private static String getProfileName(final int index) {
218
        if (index <= 0 || index > FULL_JRE) {
219
            throw new IndexOutOfBoundsException(
220
                String.format(
221
                    "Index: %d",    //NOI18N
222
                    index));
223
        }
224
        if (index == FULL_JRE) {
225
            return null;
226
        }
227
        return String.format(PROFILE_FORMAT,index);
228
    }
229
230
    private void updateProfiles() {
231
        profiles.removeAllItems();
232
        final int required = getProfileIndex(reqProfile);
233
        for (int i = required; i<= FULL_JRE; i++) {
234
            profiles.addItem(i);
235
        }
236
        profiles.setSelectedItem(required);
237
    }
238
239
    private void checkOkOption() {
240
        okOption.setEnabled(libsModel.getSize() == 0);
241
    }
242
243
    private static final class ProfilesRenderer extends DefaultListCellRenderer {
244
        @Override
245
        @NbBundle.Messages({
246
            "NAME_Compact1=Compact 1",
247
            "NAME_Compact2=Compact 2",
248
            "NAME_Compact3=Compact 3",
249
            "NAME_FullJRE=Full JRE"
250
        })
251
        public Component getListCellRendererComponent(
252
                @NonNull final JList jlist,
253
                @NullAllowed Object o,
254
                final int i,
255
                final boolean bln,
256
                final boolean bln1) {
257
            if (o instanceof Integer) {
258
                switch ((Integer)o) {
259
                    case 1:
260
                        o = Bundle.NAME_Compact1();
261
                        break;
262
                    case 2:
263
                        o = Bundle.NAME_Compact2();
264
                        break;
265
                    case 3:
266
                        o = Bundle.NAME_Compact3();
267
                        break;
268
                    case FULL_JRE:
269
                        o = Bundle.NAME_FullJRE();
270
                        break;
271
                    default:
272
                        throw new IllegalArgumentException(o.toString());
273
                }
274
            }
275
            return super.getListCellRendererComponent(jlist, o, i, bln, bln1); //To change body of generated methods, choose Tools | Templates.
276
        }
277
    }
278
279
    @NbBundle.Messages({
280
        "FMT_RootWithProfile={0} ({1})"
281
    })
282
    private static final class LibsRenderer extends DefaultListCellRenderer {
283
        @Override
284
        public Component getListCellRendererComponent(
285
                @NonNull final JList jlist,
286
                @NullAllowed Object o,
287
                final int i,
288
                final boolean bln,
289
                final boolean bln1) {
290
            String toolTip = null;
291
            if (o instanceof Map.Entry) {
292
                final Map.Entry<URI,String> e = (Map.Entry<URI, String>) o;
293
                final String profile = e.getValue();
294
                String simpleName;
295
                try {
296
                    final URL root = e.getKey().toURL();
297
                    URL fileURL = FileUtil.getArchiveFile(root);
298
                    if (fileURL == null) {
299
                        fileURL = root;
300
                    }
301
                    final File f = Utilities.toFile(fileURL.toURI());
302
                    simpleName = f.getName();
303
                    toolTip = f.getAbsolutePath();
304
                } catch (URISyntaxException ex) {
305
                    simpleName = e.getKey().toString();
306
                } catch (MalformedURLException ex) {
307
                    simpleName = e.getKey().toString();
308
                }
309
                o = Bundle.FMT_RootWithProfile(simpleName, profile);
310
            }
311
            final Component res = super.getListCellRendererComponent(jlist, o, i, bln, bln1); //To change body of generated methods, choose Tools | Templates.
312
            setToolTipText(toolTip);
313
            return res;
314
        }
315
    }
316
317
    private static final class LibsModel extends AbstractListModel {
318
319
        private final String currentProfile;
320
        private final Map<String,Map<URI,String>> state;
321
        private final Set<URI> toRemove;
322
        private final List<Map.Entry<URI,String>> data;
323
        private boolean updated;
324
325
        LibsModel(
326
                @NonNull final String currentProfile,
327
                @NonNull final Map<String,Map<URI,String>> state) {
328
            this.currentProfile = currentProfile;
329
            this.state = state;
330
            this.toRemove = new HashSet<URI>();
331
            this.data = new ArrayList<Map.Entry<URI, String>>();
332
            refresh();
333
        }
334
335
        @Override
336
        public int getSize() {
337
            return data.size();
338
        }
339
340
        @Override
341
        public Object getElementAt(int i) {
342
            if (i<0 || i>=data.size()) {
343
                throw new IndexOutOfBoundsException(
344
                    String.format(
345
                        "Index: %d, Size: %d",  //NOI18N
346
                        i,
347
                        data.size()));
348
            }
349
            return data.get(i);
350
        }
351
352
        void removeRoots(@NonNull final Collection<? extends URI> root) {
353
            final int oldSize = getSize();
354
            toRemove.addAll(root);
355
            refresh();
356
            final int newSize = getSize();
357
            fireContentsChanged(this, 0, Math.max(oldSize, newSize));
358
        };
359
360
        @CheckForNull
361
        String requiredProfile() {
362
            return FixProfile.requiredProfile(data, currentProfile);
363
        }
364
365
        void updateProfile(final boolean  update) {
366
            final int oldSize = getSize();
367
            updated = update;
368
            refresh();
369
            final int newSize = getSize();
370
            fireContentsChanged(this, 0, Math.max(oldSize, newSize));
371
        }
372
373
        @NonNull
374
        Collection<? extends URI> getRemovedRooots() {
375
            return Collections.unmodifiableCollection(toRemove);
376
        }
377
378
        private void refresh() {
379
            final Set<Map.Entry<URI,String>> newData = new HashSet<Map.Entry<URI,String>>();
380
            for (Map.Entry<String,Map<URI,String>> cpe : state.entrySet()) {
381
                for (Map.Entry<URI,String> re : cpe.getValue().entrySet()) {
382
                    if (!toRemove.contains(re.getKey()) &&
383
                        !(updated && PROFILE_PATTERN.matcher(re.getValue()).matches())) {
384
                        newData.add(re);
385
                    }
386
                }
387
            }
388
            data.clear();
389
            data.addAll(newData);
390
        }
391
    }
392
393
    /**
394
     * This method is called from within the constructor to initialize the form.
395
     * WARNING: Do NOT modify this code. The content of this method is always
396
     * regenerated by the Form Editor.
397
     */
398
    @SuppressWarnings("unchecked")
399
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
400
    private void initComponents() {
401
402
        jLabel1 = new javax.swing.JLabel();
403
        remove = new javax.swing.JButton();
404
        changeProfile = new javax.swing.JCheckBox();
405
        profiles = new javax.swing.JComboBox();
406
        jScrollPane1 = new javax.swing.JScrollPane();
407
        brokenLibs = new javax.swing.JList();
408
409
        jLabel1.setLabelFor(brokenLibs);
410
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FixProfile.class, "LBL_FixProfile_BrokenLibs")); // NOI18N
411
412
        org.openide.awt.Mnemonics.setLocalizedText(remove, org.openide.util.NbBundle.getMessage(FixProfile.class, "LBL_FixProfile_remove")); // NOI18N
413
        remove.setToolTipText(org.openide.util.NbBundle.getMessage(FixProfile.class, "TIP_FixProfile_Remove")); // NOI18N
414
        remove.addActionListener(new java.awt.event.ActionListener() {
415
            public void actionPerformed(java.awt.event.ActionEvent evt) {
416
                removeLibrary(evt);
417
            }
418
        });
419
420
        org.openide.awt.Mnemonics.setLocalizedText(changeProfile, org.openide.util.NbBundle.getMessage(FixProfile.class, "LBL_FixProfile_changeProfile")); // NOI18N
421
422
        jScrollPane1.setViewportView(brokenLibs);
423
        brokenLibs.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FixProfile.class, "AD_FixProfile_BrokenLibs")); // NOI18N
424
425
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
426
        this.setLayout(layout);
427
        layout.setHorizontalGroup(
428
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
429
            .add(layout.createSequentialGroup()
430
                .addContainerGap()
431
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
432
                    .add(layout.createSequentialGroup()
433
                        .add(jLabel1)
434
                        .addContainerGap(154, Short.MAX_VALUE))
435
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
436
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
437
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
438
                                .add(changeProfile)
439
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
440
                                .add(profiles, 0, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
441
                            .add(jScrollPane1))
442
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
443
                        .add(remove)
444
                        .addContainerGap())))
445
        );
446
        layout.setVerticalGroup(
447
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
448
            .add(layout.createSequentialGroup()
449
                .addContainerGap()
450
                .add(jLabel1)
451
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
452
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
453
                    .add(layout.createSequentialGroup()
454
                        .add(remove)
455
                        .add(0, 0, Short.MAX_VALUE))
456
                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 212, Short.MAX_VALUE))
457
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
458
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
459
                    .add(changeProfile)
460
                    .add(profiles, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
461
                .addContainerGap())
462
        );
463
464
        jLabel1.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(FixProfile.class, "FixProfile.jLabel1.AccessibleContext.accessibleName")); // NOI18N
465
        changeProfile.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FixProfile.class, "AD_FixProfile_changeProfile")); // NOI18N
466
        profiles.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(FixProfile.class, "AN_FixProfile_Profiles")); // NOI18N
467
        profiles.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FixProfile.class, "AD_FixProfile_Profiles")); // NOI18N
468
    }// </editor-fold>//GEN-END:initComponents
469
470
    private void removeLibrary(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeLibrary
471
        final Object[] selection =  brokenLibs.getSelectedValues();
472
        final Set<URI> rootsToRemove = new HashSet<URI>();
473
        for (Object e : selection) {
474
            rootsToRemove.add(((Map.Entry<URI,String>)e).getKey());
475
        }
476
        libsModel.removeRoots(rootsToRemove);
477
        if (libsModel.getSize() > 0) {
478
            brokenLibs.setSelectedIndex(0);
479
        }
480
        reqProfile = libsModel.requiredProfile();
481
        updateProfiles();
482
    }//GEN-LAST:event_removeLibrary
483
484
    // Variables declaration - do not modify//GEN-BEGIN:variables
485
    private javax.swing.JList brokenLibs;
486
    private javax.swing.JCheckBox changeProfile;
487
    private javax.swing.JLabel jLabel1;
488
    private javax.swing.JScrollPane jScrollPane1;
489
    private javax.swing.JComboBox profiles;
490
    private javax.swing.JButton remove;
491
    // End of variables declaration//GEN-END:variables
492
}
(-)a/java.project/src/org/netbeans/modules/java/project/ProjectProblemsProviders.java (-1 / +281 lines)
Lines 45-50 Link Here
45
import java.beans.PropertyChangeListener;
45
import java.beans.PropertyChangeListener;
46
import java.io.File;
46
import java.io.File;
47
import java.io.IOException;
47
import java.io.IOException;
48
import java.io.InputStream;
48
import java.lang.ref.Reference;
49
import java.lang.ref.Reference;
49
import java.lang.ref.WeakReference;
50
import java.lang.ref.WeakReference;
50
import java.net.URI;
51
import java.net.URI;
Lines 68-85 Link Here
68
import java.util.concurrent.TimeUnit;
69
import java.util.concurrent.TimeUnit;
69
import java.util.concurrent.TimeoutException;
70
import java.util.concurrent.TimeoutException;
70
import java.util.concurrent.atomic.AtomicBoolean;
71
import java.util.concurrent.atomic.AtomicBoolean;
72
import java.util.jar.Attributes;
73
import java.util.jar.Manifest;
71
import java.util.logging.Level;
74
import java.util.logging.Level;
72
import java.util.logging.Logger;
75
import java.util.logging.Logger;
73
import java.util.regex.Matcher;
76
import java.util.regex.Matcher;
74
import java.util.regex.Pattern;
77
import java.util.regex.Pattern;
78
import javax.swing.JButton;
75
import javax.swing.JFileChooser;
79
import javax.swing.JFileChooser;
80
import javax.swing.event.ChangeEvent;
81
import javax.swing.event.ChangeListener;
76
import org.netbeans.api.annotations.common.CheckForNull;
82
import org.netbeans.api.annotations.common.CheckForNull;
77
import org.netbeans.api.annotations.common.NonNull;
83
import org.netbeans.api.annotations.common.NonNull;
78
import org.netbeans.api.annotations.common.NullAllowed;
84
import org.netbeans.api.annotations.common.NullAllowed;
85
import org.netbeans.api.java.classpath.ClassPath;
79
import org.netbeans.api.java.platform.JavaPlatform;
86
import org.netbeans.api.java.platform.JavaPlatform;
80
import org.netbeans.api.java.platform.JavaPlatformManager;
87
import org.netbeans.api.java.platform.JavaPlatformManager;
81
import org.netbeans.api.java.platform.PlatformsCustomizer;
88
import org.netbeans.api.java.platform.PlatformsCustomizer;
82
import org.netbeans.api.java.platform.Specification;
89
import org.netbeans.api.java.platform.Specification;
90
import org.netbeans.api.java.queries.SourceLevelQuery;
83
import org.netbeans.api.project.FileOwnerQuery;
91
import org.netbeans.api.project.FileOwnerQuery;
84
import org.netbeans.api.project.Project;
92
import org.netbeans.api.project.Project;
85
import org.netbeans.api.project.ProjectManager;
93
import org.netbeans.api.project.ProjectManager;
Lines 99-104 Link Here
99
import org.openide.util.Parameters;
107
import org.openide.util.Parameters;
100
108
101
import static org.netbeans.modules.java.project.Bundle.*;
109
import static org.netbeans.modules.java.project.Bundle.*;
110
import org.netbeans.spi.java.classpath.ClassPathFactory;
111
import org.netbeans.spi.java.project.classpath.support.ProjectClassPathSupport;
102
import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport;
112
import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport;
103
import org.netbeans.spi.project.support.ant.ui.VariablesSupport;
113
import org.netbeans.spi.project.support.ant.ui.VariablesSupport;
104
import org.netbeans.spi.project.ui.ProjectProblemResolver;
114
import org.netbeans.spi.project.ui.ProjectProblemResolver;
Lines 107-116 Link Here
107
import org.netbeans.spi.project.ui.support.ProjectProblemsProviderSupport;
117
import org.netbeans.spi.project.ui.support.ProjectProblemsProviderSupport;
108
import org.openide.DialogDescriptor;
118
import org.openide.DialogDescriptor;
109
import org.openide.DialogDisplayer;
119
import org.openide.DialogDisplayer;
120
import org.openide.filesystems.FileUtil;
110
import org.openide.modules.SpecificationVersion;
121
import org.openide.modules.SpecificationVersion;
111
import org.openide.util.Exceptions;
122
import org.openide.util.Exceptions;
112
import org.openide.util.Lookup;
123
import org.openide.util.Lookup;
113
import org.openide.util.Mutex;
124
import org.openide.util.Mutex;
125
import org.openide.util.MutexException;
114
import org.openide.util.RequestProcessor;
126
import org.openide.util.RequestProcessor;
115
import org.openide.util.Utilities;
127
import org.openide.util.Utilities;
116
import org.openide.util.WeakListeners;
128
import org.openide.util.WeakListeners;
Lines 129-135 Link Here
129
    }
141
    }
130
142
131
143
132
144
    @NonNull
133
    public static ProjectProblemsProvider createReferenceProblemProvider(
145
    public static ProjectProblemsProvider createReferenceProblemProvider(
134
            @NonNull final AntProjectHelper projectHelper,
146
            @NonNull final AntProjectHelper projectHelper,
135
            @NonNull final ReferenceHelper referenceHelper,
147
            @NonNull final ReferenceHelper referenceHelper,
Lines 141-146 Link Here
141
        return pp;
153
        return pp;
142
    }
154
    }
143
155
156
    @NonNull
144
    public static ProjectProblemsProvider createPlatformVersionProblemProvider(
157
    public static ProjectProblemsProvider createPlatformVersionProblemProvider(
145
            @NonNull final AntProjectHelper helper,
158
            @NonNull final AntProjectHelper helper,
146
            @NonNull final PropertyEvaluator evaluator,
159
            @NonNull final PropertyEvaluator evaluator,
Lines 159-164 Link Here
159
        return pp;
172
        return pp;
160
    }
173
    }
161
174
175
    @NonNull
176
    public static ProjectProblemsProvider createProfileProblemProvider(
177
            @NonNull final AntProjectHelper antProjectHelper,
178
            @NonNull final ReferenceHelper refHelper,
179
            @NonNull final PropertyEvaluator evaluator,
180
            @NonNull final String profileProperty,
181
            @NonNull final String... classPathProperties) {
182
        final ProfileProjectProviderImpl pp = new ProfileProjectProviderImpl(
183
                antProjectHelper,
184
                refHelper,
185
                evaluator,
186
                profileProperty,
187
                classPathProperties);
188
        return pp;
189
    }
190
162
    //<editor-fold defaultstate="collapsed" desc="Helper Methods & Types">
191
    //<editor-fold defaultstate="collapsed" desc="Helper Methods & Types">
163
    @NonNull
192
    @NonNull
164
    private static Set<? extends ProjectProblemsProvider.ProjectProblem> getReferenceProblems(
193
    private static Set<? extends ProjectProblemsProvider.ProjectProblem> getReferenceProblems(
Lines 955-960 Link Here
955
984
956
985
957
    }
986
    }
987
    
988
    static final class ProfileResolver implements ProjectProblemResolver {
989
990
        private final AntProjectHelper antProjectHelper;
991
        private final String profileProperty;
992
        private final String currentProfile;
993
        private final Map<String,Map<URI,String>> state;
994
995
        private ProfileResolver(
996
                @NonNull final AntProjectHelper antProjectHelper,
997
                @NonNull final String profileProperty,
998
                @NonNull final String currentProfile,
999
                @NonNull final Map<String,Map<URI,String>> state) {
1000
            assert antProjectHelper != null;
1001
            assert profileProperty != null;
1002
            assert currentProfile != null;
1003
            assert state != null;
1004
            this.antProjectHelper = antProjectHelper;
1005
            this.profileProperty = profileProperty;
1006
            this.currentProfile = currentProfile;
1007
            this.state = state;
1008
        }        
1009
1010
1011
        @Override
1012
        @NbBundle.Messages({
1013
            "LBL_ResolveProfile=Resolve Invalid Project Profile",
1014
            "LBL_ResolveButton=OK",
1015
            "AN_ResolveButton=Resolve",
1016
            "AD_ResolveButton=Resovle the profile problems"
1017
        })
1018
        public Future<Result> resolve() {
1019
            final JButton ok = new JButton(LBL_ResolveButton());
1020
            ok.getAccessibleContext().setAccessibleName(AN_ResolveButton());
1021
            ok.getAccessibleContext().setAccessibleDescription(AD_ResolveButton());
1022
            final FixProfile panel = new FixProfile(ok, currentProfile, state);
1023
            final DialogDescriptor dd = new DialogDescriptor(
1024
                    panel,
1025
                    LBL_ResolveProfile(),
1026
                    true,
1027
                    new Object[] {
1028
                        ok,
1029
                        DialogDescriptor.CANCEL_OPTION
1030
                    },
1031
                    ok,
1032
                    DialogDescriptor.DEFAULT_ALIGN,
1033
                    null,
1034
                    null);
1035
            if (DialogDisplayer.getDefault().notify(dd) == ok) {
1036
                return RP.submit(new Callable<ProjectProblemsProvider.Result>() {
1037
                    @Override
1038
                    public ProjectProblemsProvider.Result call() throws Exception {
1039
                        ProjectProblemsProvider.Status status = ProjectProblemsProvider.Status.UNRESOLVED;
1040
                        try {
1041
                            ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
1042
                                @Override
1043
                                public Void run() throws IOException {
1044
                                    final boolean shouldUpdate = panel.shouldUpdateProfile();
1045
                                    if (shouldUpdate) {
1046
                                        final String newProfile = panel.getProfile();
1047
                                        final EditableProperties props = antProjectHelper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
1048
                                        if (newProfile == null) {
1049
                                            props.remove(profileProperty);
1050
                                        } else {
1051
                                            props.put(profileProperty, newProfile);
1052
                                        }
1053
                                        antProjectHelper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
1054
                                    }
1055
                                    ProjectManager.getDefault().saveProject(
1056
                                        FileOwnerQuery.getOwner(antProjectHelper.getProjectDirectory()));
1057
                                    return null;
1058
                                }
1059
                            });
1060
                            status = ProjectProblemsProvider.Status.RESOLVED;
1061
                        } catch (MutexException e) {
1062
                            Exceptions.printStackTrace(e);
1063
                        }
1064
                        return ProjectProblemsProvider.Result.create(status);
1065
                    }
1066
                });
1067
            }
1068
            return new Done(ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED));
1069
        }                              
1070
    }
958
1071
959
    private static final class Done implements Future<ProjectProblemsProvider.Result> {
1072
    private static final class Done implements Future<ProjectProblemsProvider.Result> {
960
1073
Lines 1292-1297 Link Here
1292
        }
1405
        }
1293
    }
1406
    }
1294
1407
1408
    private static final class ProfileProjectProviderImpl implements ProjectProblemsProvider, PropertyChangeListener, ChangeListener {
1409
1410
        private static final String RES_MANIFEST = "META-INF/MANIFEST.MF";              //NOI18N
1411
        private static final String ATTR_PROFILE = "Profile";                           //NOI18N
1412
1413
        private final AntProjectHelper antProjectHelper;
1414
        private final ReferenceHelper referenceHelper;
1415
        private final PropertyEvaluator evaluator;
1416
        private final String profileProperty;
1417
        private final Set<String> classPathProperties;        
1418
        private final ProjectProblemsProviderSupport problemsProviderSupport;
1419
        private final AtomicBoolean listenersInitialized;
1420
        private volatile SourceLevelQuery.Result slRes;
1421
1422
        ProfileProjectProviderImpl(
1423
                @NonNull final AntProjectHelper antProjectHelper,
1424
                @NonNull final ReferenceHelper referenceHelper,
1425
                @NonNull final PropertyEvaluator evaluator,
1426
                @NonNull final String profileProperty,
1427
                @NonNull final String... classPathProperties) {
1428
            assert antProjectHelper != null;
1429
            assert referenceHelper != null;
1430
            assert evaluator != null;
1431
            assert profileProperty != null;
1432
            assert classPathProperties != null;
1433
            this.antProjectHelper = antProjectHelper;
1434
            this.referenceHelper = referenceHelper;
1435
            this.evaluator = evaluator;
1436
            this.profileProperty = profileProperty;
1437
            this.classPathProperties = new HashSet<String>(
1438
                Arrays.asList(classPathProperties));            
1439
            this.problemsProviderSupport = new ProjectProblemsProviderSupport(this);
1440
            this.listenersInitialized = new AtomicBoolean();
1441
        }        
1442
1443
        @Override
1444
        public void addPropertyChangeListener(@NonNull final PropertyChangeListener listener) {
1445
            Parameters.notNull("listener", listener);   //NOI18N
1446
            problemsProviderSupport.addPropertyChangeListener(listener);
1447
        }
1448
1449
        @Override
1450
        public void removePropertyChangeListener(@NonNull final PropertyChangeListener listener) {
1451
            Parameters.notNull("listener", listener);   //NOI18N
1452
            problemsProviderSupport.removePropertyChangeListener(listener);
1453
        }
1454
1455
        @Override
1456
        @NbBundle.Messages({
1457
            "LBL_InvalidProfile=Invalid Profile",
1458
            "DESC_InvalidProfile=The project profile ({0}) is lower than the profile of used libraries ({1}).",
1459
            "DESC_IllegalProfile=The project libraries have illegal value of profile."
1460
        })
1461
        public Collection<? extends ProjectProblem> getProblems() {
1462
            listenen();
1463
            return problemsProviderSupport.getProblems(new ProjectProblemsProviderSupport.ProblemsCollector() {
1464
                @Override
1465
                public Collection<? extends ProjectProblem> collectProblems() {
1466
                    return ProjectManager.mutex().readAccess(new Mutex.Action<Collection<? extends ProjectProblem>>(){
1467
                        @Override
1468
                        public Collection<? extends ProjectProblem> run() {
1469
                            final String profile = slRes.getProfile();
1470
                            if (profile == null) {
1471
                                return Collections.<ProjectProblem>emptySet();
1472
                            }
1473
                            Map<String,Map<URI,String>> problems = collectJarsWithWrongProfile(profile);
1474
                            if (problems.isEmpty()) {
1475
                                return Collections.<ProjectProblem>emptySet();
1476
                            }
1477
                            final String minProfile = FixProfile.requiredProfile(problems);
1478
                            return Collections.<ProjectProblem>singleton(
1479
                                    ProjectProblem.createError(
1480
                                        LBL_InvalidProfile(),
1481
                                        minProfile != null ?
1482
                                            DESC_InvalidProfile(profile, minProfile) :
1483
                                            DESC_IllegalProfile(),
1484
                                        new ProfileResolver(
1485
                                            antProjectHelper,
1486
                                            profileProperty,
1487
                                            profile,
1488
                                            problems)));
1489
                        }
1490
                    });
1491
                }
1492
            });
1493
        }
1494
1495
        @Override
1496
        public void propertyChange(@NonNull final PropertyChangeEvent event) {
1497
            final String propertyName = event.getPropertyName();
1498
            if (propertyName == null || classPathProperties.contains(propertyName)) {
1499
                problemsProviderSupport.fireProblemsChange();
1500
            }
1501
        }
1502
1503
        @Override
1504
        public void stateChanged(ChangeEvent ce) {
1505
            problemsProviderSupport.fireProblemsChange();
1506
        }
1507
1508
        private void listenen() {
1509
            if (listenersInitialized.compareAndSet(false, true)) {
1510
                evaluator.addPropertyChangeListener(this);
1511
                slRes = SourceLevelQuery.getSourceLevel2(antProjectHelper.getProjectDirectory());
1512
                slRes.addChangeListener(this);
1513
            }
1514
        }
1515
1516
        @NonNull
1517
        private Map<String,Map<URI,String>> collectJarsWithWrongProfile(@NonNull final String currentProfile) {
1518
            assert ProjectManager.mutex().isReadAccess() || ProjectManager.mutex().isWriteAccess();
1519
            final Map<String,Map<URI,String>> res = new HashMap<String, Map<URI, String>>();
1520
            final File base = FileUtil.toFile(antProjectHelper.getProjectDirectory());
1521
            if (base != null) {
1522
                for (String cpId : classPathProperties) {
1523
                    final ClassPath cp = ClassPathFactory.createClassPath(
1524
                        ProjectClassPathSupport.createPropertyBasedClassPathImplementation(
1525
                            base,
1526
                            evaluator,
1527
                            new String[] {cpId}));
1528
                    for (FileObject root : cp.getRoots()) {
1529
                        final FileObject manifestFile = root.getFileObject(RES_MANIFEST);
1530
                        if (manifestFile != null) {
1531
                            try {
1532
                                final InputStream in = manifestFile.getInputStream();
1533
                                try {
1534
                                    Manifest manifest = new Manifest(in);
1535
                                    final Attributes attrs = manifest.getMainAttributes();
1536
                                    final String profile = attrs.getValue(ATTR_PROFILE);
1537
                                    if (profile != null) {
1538
                                        final String normalizedProfile = FixProfile.normalize(profile);
1539
                                        if (normalizedProfile != null) {
1540
                                            if (currentProfile.compareTo(normalizedProfile) < 0) {
1541
                                                Map<URI,String> errInCp = res.get(cpId);
1542
                                                if (errInCp == null) {
1543
                                                    errInCp = new HashMap<URI, String>();
1544
                                                    res.put(cpId, errInCp);
1545
                                                }
1546
                                                errInCp.put(root.toURI(), profile);
1547
                                            }
1548
                                        } else {
1549
                                            Map<URI,String> errInCp = res.get(cpId);
1550
                                            if (errInCp == null) {
1551
                                                errInCp = new HashMap<URI, String>();
1552
                                                res.put(cpId, errInCp);
1553
                                            }
1554
                                            errInCp.put(root.toURI(), profile);
1555
                                        }
1556
                                    }
1557
                                } finally {
1558
                                    in.close();
1559
                                }
1560
                            } catch (IOException ioe) {
1561
                                LOG.log(
1562
                                    Level.INFO,
1563
                                    "Cannot read Profile attribute from: {0}",  //NOI18N
1564
                                    FileUtil.getFileDisplayName(manifestFile));
1565
                            }
1566
                        }
1567
                    }
1568
1569
                }
1570
            }
1571
            return res;
1572
        }
1573
    }
1574
1295
    private static class OpenManagersWeakListener extends WeakReference<PropertyChangeListener> implements Runnable, PropertyChangeListener {
1575
    private static class OpenManagersWeakListener extends WeakReference<PropertyChangeListener> implements Runnable, PropertyChangeListener {
1296
1576
1297
        public OpenManagersWeakListener(final PropertyChangeListener listener) {
1577
        public OpenManagersWeakListener(final PropertyChangeListener listener) {
(-)a/java.project/src/org/netbeans/spi/java/project/support/ui/BrokenReferencesSupport.java (+43 lines)
Lines 44-49 Link Here
44
44
45
package org.netbeans.spi.java.project.support.ui;
45
package org.netbeans.spi.java.project.support.ui;
46
46
47
import java.util.Arrays;
47
import java.util.concurrent.Callable;
48
import java.util.concurrent.Callable;
48
import org.netbeans.api.annotations.common.CheckForNull;
49
import org.netbeans.api.annotations.common.CheckForNull;
49
import org.netbeans.api.annotations.common.NonNull;
50
import org.netbeans.api.annotations.common.NonNull;
Lines 232-237 Link Here
232
     * @see ProjectProblemsProvider
233
     * @see ProjectProblemsProvider
233
     * @since 1.48
234
     * @since 1.48
234
     */
235
     */
236
    @NonNull
235
    public static ProjectProblemsProvider createReferenceProblemsProvider(
237
    public static ProjectProblemsProvider createReferenceProblemsProvider(
236
            @NonNull final AntProjectHelper projectHelper,
238
            @NonNull final AntProjectHelper projectHelper,
237
            @NonNull final ReferenceHelper referenceHelper,
239
            @NonNull final ReferenceHelper referenceHelper,
Lines 268-273 Link Here
268
     * @see ProjectProblemsProvider
270
     * @see ProjectProblemsProvider
269
     * @since 1.48
271
     * @since 1.48
270
     */
272
     */
273
    @NonNull
271
    public static ProjectProblemsProvider createPlatformVersionProblemProvider(
274
    public static ProjectProblemsProvider createPlatformVersionProblemProvider(
272
            @NonNull final AntProjectHelper projectHelper,
275
            @NonNull final AntProjectHelper projectHelper,
273
            @NonNull final PropertyEvaluator evaluator,
276
            @NonNull final PropertyEvaluator evaluator,
Lines 287-292 Link Here
287
                platformProperty,
290
                platformProperty,
288
                versionProperties);
291
                versionProperties);
289
    }
292
    }
293
294
    /**
295
     * Creates a {@link ProjectProblemsProvider} creating wrong JDK 8 Profile
296
     * problems.
297
     * @param projectHelper AntProjectHelper associated with the project
298
     * @param referenceHelper ReferenceHelper associated with the project
299
     * @param evaluator the {@link PropertyEvaluator} used to resolve broken references
300
     * @param profileProperty  the property holding the actual project profile
301
     * @param classPathProperties an array of property names which values hold the
302
     * classpaths to be checked.
303
     * @return {@link ProjectProblemsProvider} to be placed into project lookup.
304
     *
305
     * @see ProjectProblemsProvider
306
     * @since 1.53
307
     */
308
    @NonNull
309
    public static ProjectProblemsProvider createProfileProblemProvider(
310
            @NonNull final AntProjectHelper projectHelper,
311
            @NonNull final ReferenceHelper referenceHelper,
312
            @NonNull final PropertyEvaluator evaluator,
313
            @NonNull final String profileProperty,
314
            @NonNull final String... classPathProperties) {
315
        Parameters.notNull("projectHelper", projectHelper); //NOI18N
316
        Parameters.notNull("referenceHelper", referenceHelper); //NOI18N
317
        Parameters.notNull("evaluator", evaluator);     //NOI18N
318
        Parameters.notNull("profileProperty", profileProperty); //NOI18N
319
        Parameters.notNull("classPathProperties", classPathProperties); //NOI18N
320
        final String[] safeClassPathProperties = Arrays.copyOf(
321
                classPathProperties,
322
                classPathProperties.length);
323
        for (String safeClassPathProperty : safeClassPathProperties) {
324
            Parameters.notNull("classPathProperties[]", safeClassPathProperty); //NOI18N
325
        }
326
        return ProjectProblemsProviders.createProfileProblemProvider(
327
                projectHelper,
328
                referenceHelper,
329
                evaluator,
330
                profileProperty,
331
                safeClassPathProperties);
332
    }
290
        
333
        
291
    /**
334
    /**
292
     * Service which may be {@linkplain ServiceProvider registered} to download remote libraries or otherwise define them.
335
     * Service which may be {@linkplain ServiceProvider registered} to download remote libraries or otherwise define them.

Return to bug 227831