--- a/api.java/apichanges.xml +++ a/api.java/apichanges.xml @@ -76,6 +76,23 @@ + + + The SourceLevelQuery supports JDK 8 profiles + + + + + +

+ The JDK 8 provides three limited profiles (compact1, compact2, compact3) in addition + to the full JDK. Each profile specifies a specific set of Java API packages and + contains all of the APIs of the smaller profile. The new API allows a client of the + SourceLevelQuery to query the required profile. +

+
+ +
The SourceLevelQuery supports source level synonyms --- a/api.java/manifest.mf +++ a/api.java/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.java/1 -OpenIDE-Module-Specification-Version: 1.44 +OpenIDE-Module-Specification-Version: 1.45 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/java/queries/Bundle.properties AutoUpdate-Show-In-Client: false --- a/api.java/src/org/netbeans/api/java/queries/SourceLevelQuery.java +++ a/api.java/src/org/netbeans/api/java/queries/SourceLevelQuery.java @@ -180,6 +180,26 @@ } /** + * Returns the name of the required profile. + * @return a name of the required profile or null if the profile is either unknown + * or unsupported by actual source level. + *
+ * The JDK 8 provides three limited profiles (compact1, compact2, compact3) in addition + * to the full JDK. Each profile specifies a specific set of Java API packages and + * contains all of the APIs of the smaller profile, @see http://openjdk.java.net/jeps/161 + *
+ * @since 1.45 + */ + @CheckForNull + public String getProfile() { + final SourceLevelQueryImplementation2.Result delegate = getDelegate(); + if (!(delegate instanceof SourceLevelQueryImplementation2.Result2)) { + return null; + } + return ((SourceLevelQueryImplementation2.Result2)delegate).getProfile(); + } + + /** * Add a listener to changes of source level. * If {@link #supportsChanges} is false, the listener will never be notified * although {@link #getSourceLevel} may change from call to call. --- a/api.java/src/org/netbeans/spi/java/queries/SourceLevelQueryImplementation2.java +++ a/api.java/src/org/netbeans/spi/java/queries/SourceLevelQueryImplementation2.java @@ -107,4 +107,25 @@ */ void removeChangeListener(@NonNull ChangeListener listener); } + + /** + * Result of finding a source level and profile as well as the ability + * to listen on changes. + * @since 1.45 + */ + interface Result2 extends Result { + + /** + * Returns the name of the required profile. + * @return a name of the required profile or null if the profile is either unknown + * or unsupported by actual source level. + *
+ * The JDK 8 provides three limited profiles (compact1, compact2, compact3) in addition + * to the full JDK. Each profile specifies a specific set of Java API packages and + * contains all of the APIs of the smaller profile, @see http://openjdk.java.net/jeps/161 + *
+ */ + @CheckForNull + String getProfile(); + } } --- a/java.api.common/nbproject/project.xml +++ a/java.api.common/nbproject/project.xml @@ -29,7 +29,7 @@ 1 - 1.30 + 1.45 --- a/java.api.common/src/org/netbeans/modules/java/api/common/queries/SourceLevelQueryImpl.java +++ a/java.api.common/src/org/netbeans/modules/java/api/common/queries/SourceLevelQueryImpl.java @@ -43,10 +43,7 @@ */ package org.netbeans.modules.java.api.common.queries; -import org.netbeans.modules.java.api.common.util.CommonProjectUtils; import org.netbeans.spi.project.support.ant.PropertyEvaluator; -import org.netbeans.spi.project.support.ant.PropertyUtils; -import org.netbeans.spi.project.support.ant.EditableProperties; import org.openide.filesystems.FileObject; /** @@ -66,25 +63,7 @@ @Override public String getSourceLevel(FileObject javaFile) { - return findSourceLevel(evaluator); - } - - static String findSourceLevel (final PropertyEvaluator eval) { - final String activePlatform = eval.getProperty("platform.active"); //NOI18N - if (CommonProjectUtils.getActivePlatform(activePlatform) != null) { - String sl = eval.getProperty("javac.source"); //NOI18N - if (sl != null && sl.length() > 0) { - return sl; - } - return null; - } - - EditableProperties props = PropertyUtils.getGlobalProperties(); - String sl = props.get("default.javac.source"); //NOI18N - if (sl != null && sl.length() > 0) { - return sl; - } - return null; - } + return SourceLevelQueryImpl2.findSourceLevel(evaluator); + } } --- a/java.api.common/src/org/netbeans/modules/java/api/common/queries/SourceLevelQueryImpl2.java +++ a/java.api.common/src/org/netbeans/modules/java/api/common/queries/SourceLevelQueryImpl2.java @@ -44,10 +44,14 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.regex.Pattern; import javax.swing.event.ChangeListener; import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.modules.java.api.common.util.CommonProjectUtils; import org.netbeans.spi.java.queries.SourceLevelQueryImplementation2; +import org.netbeans.spi.project.support.ant.EditableProperties; import org.netbeans.spi.project.support.ant.PropertyEvaluator; +import org.netbeans.spi.project.support.ant.PropertyUtils; import org.openide.filesystems.FileObject; import org.openide.util.ChangeSupport; import org.openide.util.Parameters; @@ -58,6 +62,12 @@ */ class SourceLevelQueryImpl2 implements SourceLevelQueryImplementation2 { + private static final String PLATFORM_ACTIVE = "platform.active"; //NOI18N + private static final String JAVAC_SOURCE = "javac.source"; //NOI18N + private static final String DEFAULT_SOURCE_LEVEL = "default.javac.source"; //NOI18N + private static final String JAVAC_PROFILE = "javac.profile"; //NOI18N + private static final Pattern SUPPORTS_PROFILES = Pattern.compile("(1\\.)?8"); //NOI18N + private final PropertyEvaluator eval; private final Result result; @@ -72,7 +82,42 @@ return this.result; } - private class R implements Result, PropertyChangeListener { + static String findSourceLevel ( + @NonNull final PropertyEvaluator eval) { + final String activePlatform = eval.getProperty(PLATFORM_ACTIVE); + if (CommonProjectUtils.getActivePlatform(activePlatform) != null) { + String sl = eval.getProperty(JAVAC_SOURCE); + if (sl != null && sl.length() > 0) { + return sl; + } + return null; + } + final EditableProperties props = PropertyUtils.getGlobalProperties(); + String sl = props.get(DEFAULT_SOURCE_LEVEL); + if (sl != null && sl.length() > 0) { + return sl; + } + return null; + } + + private static String findProfile( + @NonNull final PropertyEvaluator eval) { + if (supportsProfiles(findSourceLevel(eval))) { + final String profile = eval.getProperty(JAVAC_PROFILE); + if (profile != null && profile.length() > 0) { + return profile; + } + } + return null; + } + + private static boolean supportsProfiles( + @NonNull final String sl) { + return sl != null && + SUPPORTS_PROFILES.matcher(sl).matches(); + } + + private class R implements Result2, PropertyChangeListener { private final ChangeSupport cs = new ChangeSupport(this); @@ -83,7 +128,12 @@ @Override public String getSourceLevel() { - return SourceLevelQueryImpl.findSourceLevel(eval); + return findSourceLevel(eval); + } + + @Override + public String getProfile() { + return findProfile(eval); } @Override @@ -100,8 +150,9 @@ public void propertyChange(PropertyChangeEvent evt) { final String name = evt.getPropertyName(); if (name == null || - "javac.source".equals(name) || //NOI18N - "platform.active".equals(name)) { //NOI18N + JAVAC_SOURCE.equals(name) || + JAVAC_PROFILE.equals(name) || + PLATFORM_ACTIVE.equals(name)) { this.cs.fireChange(); } } --- a/java.api.common/test/unit/src/org/netbeans/modules/java/api/common/queries/SourceLevelQueryImplTest.java +++ a/java.api.common/test/unit/src/org/netbeans/modules/java/api/common/queries/SourceLevelQueryImplTest.java @@ -55,10 +55,11 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.platform.JavaPlatform; import org.netbeans.api.java.platform.Specification; -import org.netbeans.api.java.queries.SourceLevelQuery; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectManager; import org.netbeans.junit.NbTestCase; @@ -76,6 +77,7 @@ import org.netbeans.spi.project.support.ant.PropertyEvaluator; import org.openide.filesystems.FileUtil; import org.openide.modules.SpecificationVersion; +import org.openide.util.Mutex; import org.openide.util.test.MockLookup; /** @@ -100,6 +102,10 @@ }); } + private static final String COMPACT1 = "compact1"; //NOI18N + private static final String COMPACT2 = "compact2"; //NOI18N + private static final String JDK_8 = "8"; //NOI18N + private static final String JDK_8_ALIAS = "1.8"; //NOI18N private static final String JAVAC_SOURCE = "1.2"; private static final String DEFAULT_JAVAC_SOURCE = "17.2"; @@ -136,7 +142,14 @@ } - private void prepareProject(String platformName) throws IOException { + private void prepareProject( + @NonNull final String platformName) throws IOException { + prepareProject(platformName, null, null); + } + private void prepareProject( + @NonNull final String platformName, + @NullAllowed final String sourceLevel, + @NullAllowed final String profile) throws IOException { scratch = TestUtil.makeScratchDir(this); projdir = scratch.createFolder("proj"); helper = ProjectGenerator.createProject(projdir, "test"); @@ -146,7 +159,13 @@ EditableProperties props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); props.setProperty("javac.source", "${def}"); props.setProperty("platform.active", platformName); - props.setProperty("def", JAVAC_SOURCE); + props.setProperty("def", + sourceLevel != null ? + sourceLevel : + JAVAC_SOURCE); + if (profile != null) { + props.setProperty("javac.profile", profile); //NOI18N + } helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props); props = PropertyUtils.getGlobalProperties(); props.put("default.javac.source", DEFAULT_JAVAC_SOURCE); @@ -207,6 +226,95 @@ assertEquals("1.7", result.getSourceLevel().toString()); } + public void testProfilesJDK8ProfileGiven() throws IOException { + this.prepareProject(TEST_PLATFORM, JDK_8, COMPACT2); + final FileObject dummy = projdir.createData("Dummy.java"); //NOI18N + final SourceLevelQueryImplementation2 sourceLevelQuery = QuerySupport.createSourceLevelQuery2(eval); + final SourceLevelQueryImplementation2.Result result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(COMPACT2, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + } + + public void testProfilesJDK8AliasProfileGiven() throws IOException { + this.prepareProject(TEST_PLATFORM, JDK_8_ALIAS, COMPACT2); + final FileObject dummy = projdir.createData("Dummy.java"); //NOI18N + final SourceLevelQueryImplementation2 sourceLevelQuery = QuerySupport.createSourceLevelQuery2(eval); + final SourceLevelQueryImplementation2.Result result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(COMPACT2, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + } + + public void testProfilesJDK8AliasProfileNotGiven() throws IOException { + this.prepareProject(TEST_PLATFORM, JDK_8, null); + final FileObject dummy = projdir.createData("Dummy.java"); //NOI18N + final SourceLevelQueryImplementation2 sourceLevelQuery = QuerySupport.createSourceLevelQuery2(eval); + final SourceLevelQueryImplementation2.Result result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(null, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + } + + public void testProfilesOldJDKAliasProfileGiven() throws IOException { + this.prepareProject(TEST_PLATFORM, JAVAC_SOURCE, COMPACT2); + final FileObject dummy = projdir.createData("Dummy.java"); //NOI18N + final SourceLevelQueryImplementation2 sourceLevelQuery = QuerySupport.createSourceLevelQuery2(eval); + final SourceLevelQueryImplementation2.Result result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(null, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + } + + public void testProfileChanges() throws Exception { + prepareProject(TEST_PLATFORM, JDK_8, COMPACT1); + final FileObject dummy = projdir.createData("Dummy.java"); //NOI18N + final SourceLevelQueryImplementation2 sourceLevelQuery = QuerySupport.createSourceLevelQuery2(eval); + SourceLevelQueryImplementation2.Result result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(COMPACT1, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + @Override + public Void run() throws Exception { + final EditableProperties props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); + props.setProperty("javac.profile", COMPACT2); //NOI18N + helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props); + ProjectManager.getDefault().saveProject(prj); + return null; + } + }); + result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(COMPACT2, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + + } + + public void testProfileListening() throws Exception { + prepareProject(TEST_PLATFORM, JDK_8, COMPACT1); + final FileObject dummy = projdir.createData("Dummy.java"); //NOI18N + final SourceLevelQueryImplementation2 sourceLevelQuery = QuerySupport.createSourceLevelQuery2(eval); + final SourceLevelQueryImplementation2.Result result = sourceLevelQuery.getSourceLevel(dummy); + assertTrue(result instanceof SourceLevelQueryImplementation2.Result2); + assertEquals(COMPACT1, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + final AtomicInteger eventCount = new AtomicInteger(); + final ChangeListener listener = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + eventCount.getAndIncrement(); + } + }; + result.addChangeListener(listener); + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + @Override + public Void run() throws Exception { + final EditableProperties props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); + props.setProperty("javac.profile", COMPACT2); //NOI18N + helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props); + ProjectManager.getDefault().saveProject(prj); + return null; + } + }); + assertEquals(1, eventCount.get()); + assertEquals(COMPACT2, ((SourceLevelQueryImplementation2.Result2)result).getProfile()); + + } + private static class TestPlatformProvider implements JavaPlatformProvider { private JavaPlatform platform;