| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.apisupport.project; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.net.URI; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.atomic.AtomicReference; |
| import java.util.jar.Manifest; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.swing.Icon; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import org.netbeans.api.annotations.common.CheckForNull; |
| import org.netbeans.api.annotations.common.NonNull; |
| import org.netbeans.api.java.classpath.ClassPath; |
| import org.netbeans.api.java.classpath.GlobalPathRegistry; |
| import org.netbeans.api.java.project.JavaProjectConstants; |
| import org.netbeans.api.project.FileOwnerQuery; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ProjectInformation; |
| import org.netbeans.api.project.ProjectManager; |
| import org.netbeans.api.project.ProjectUtils; |
| import org.netbeans.api.project.Sources; |
| import static org.netbeans.modules.apisupport.project.Bundle.*; |
| import org.netbeans.modules.apisupport.project.api.ManifestManager; |
| import org.netbeans.modules.apisupport.project.api.UIUtil; |
| import org.netbeans.modules.apisupport.project.api.Util; |
| import org.netbeans.modules.apisupport.project.queries.AccessibilityQueryImpl; |
| import org.netbeans.modules.apisupport.project.queries.AnnotationProcessingQueryImpl; |
| import org.netbeans.modules.apisupport.project.queries.AntArtifactProviderImpl; |
| import org.netbeans.modules.apisupport.project.queries.BinaryForSourceImpl; |
| import org.netbeans.modules.apisupport.project.queries.ClassPathProviderImpl; |
| import org.netbeans.modules.apisupport.project.queries.FileEncodingQueryImpl; |
| import org.netbeans.modules.apisupport.project.queries.JavadocForBinaryImpl; |
| import org.netbeans.modules.apisupport.project.queries.ModuleProjectClassPathExtender; |
| import org.netbeans.modules.apisupport.project.queries.ProjectWhiteListQueryImplementation; |
| import org.netbeans.modules.apisupport.project.queries.SourceForBinaryImpl; |
| import org.netbeans.modules.apisupport.project.queries.SourceLevelQueryImpl; |
| import org.netbeans.modules.apisupport.project.queries.SubprojectProviderImpl; |
| import org.netbeans.modules.apisupport.project.queries.TemplateAttributesProvider; |
| import org.netbeans.modules.apisupport.project.queries.UnitTestForSourceQueryImpl; |
| import org.netbeans.modules.apisupport.project.spi.PlatformJarProvider; |
| import org.netbeans.modules.apisupport.project.ui.ModuleActions; |
| import org.netbeans.modules.apisupport.project.ui.ModuleLogicalView; |
| import org.netbeans.modules.apisupport.project.ui.ModuleOperations; |
| import org.netbeans.modules.apisupport.project.ui.customizer.CustomizerProviderImpl; |
| import org.netbeans.modules.apisupport.project.ui.customizer.NbModulePackageModifierImplementation; |
| import org.netbeans.modules.apisupport.project.ui.customizer.SingleModuleProperties; |
| import org.netbeans.modules.apisupport.project.ui.customizer.SuiteProperties; |
| import org.netbeans.modules.apisupport.project.universe.HarnessVersion; |
| import org.netbeans.modules.apisupport.project.universe.LocalizedBundleInfo; |
| import org.netbeans.modules.apisupport.project.universe.ModuleEntry; |
| import org.netbeans.modules.apisupport.project.universe.ModuleList; |
| import org.netbeans.modules.apisupport.project.universe.NbPlatform; |
| import org.netbeans.spi.java.project.support.ExtraSourceJavadocSupport; |
| import org.netbeans.spi.java.project.support.LookupMergerSupport; |
| import org.netbeans.spi.java.queries.JavadocForBinaryQueryImplementation; |
| import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation; |
| import org.netbeans.spi.project.AuxiliaryConfiguration; |
| import org.netbeans.spi.project.support.LookupProviderSupport; |
| import org.netbeans.spi.project.support.ant.AntBasedProjectRegistration; |
| import org.netbeans.spi.project.support.ant.AntProjectHelper; |
| import org.netbeans.spi.project.support.ant.EditableProperties; |
| import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; |
| import org.netbeans.spi.project.support.ant.ProjectXmlSavedHook; |
| import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
| import org.netbeans.spi.project.support.ant.PropertyUtils; |
| import org.netbeans.spi.project.support.ant.SourcesHelper; |
| import org.netbeans.spi.project.ui.PrivilegedTemplates; |
| import org.netbeans.spi.project.ui.ProjectOpenedHook; |
| import org.netbeans.spi.project.ui.RecommendedTemplates; |
| import org.netbeans.spi.project.ui.support.UILookupMergerSupport; |
| import org.netbeans.spi.queries.FileBuiltQueryImplementation; |
| import org.openide.ErrorManager; |
| import org.openide.filesystems.FileChangeAdapter; |
| import org.openide.filesystems.FileChangeListener; |
| import org.openide.filesystems.FileEvent; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileUtil; |
| import org.openide.util.Exceptions; |
| import org.openide.util.ImageUtilities; |
| import org.openide.util.Lookup; |
| import org.openide.util.Mutex; |
| import org.openide.util.NbBundle.Messages; |
| import org.openide.util.Utilities; |
| import org.openide.util.lookup.AbstractLookup; |
| import org.openide.util.lookup.InstanceContent; |
| import org.openide.xml.XMLUtil; |
| import org.w3c.dom.Element; |
| |
| /** |
| * A NetBeans module project. |
| * @author Jesse Glick |
| */ |
| @AntBasedProjectRegistration( |
| type=NbModuleProject.TYPE, |
| iconResource=NbModuleProject.NB_PROJECT_ICON_PATH, |
| sharedName=NbModuleProject.NAME_SHARED, |
| sharedNamespace= NbModuleProject.NAMESPACE_SHARED, |
| privateName="data", // NOI18N |
| privateNamespace= "http://www.netbeans.org/ns/nb-module-project-private/1" // NOI18N |
| ) |
| public final class NbModuleProject implements Project { |
| |
| static final String TYPE = "org.netbeans.modules.apisupport.project"; // NOI18N |
| static final String NAME_SHARED = "data"; // NOI18N |
| public static final String NAMESPACE_SHARED = "http://www.netbeans.org/ns/nb-module-project/3"; // NOI18N |
| public static final String NAMESPACE_SHARED_2 = "http://www.netbeans.org/ns/nb-module-project/2"; // NOI18N |
| public static final String NB_PROJECT_ICON_PATH = |
| "org/netbeans/modules/apisupport/project/resources/module.png"; // NOI18N |
| public static final String NB_PROJECT_OSGI_ICON_PATH = |
| "org/netbeans/modules/apisupport/project/resources/bundle.png"; // NOI18N |
| |
| private static final Icon NB_PROJECT_ICON = ImageUtilities.loadImageIcon(NB_PROJECT_ICON_PATH, false); |
| |
| public static final String SOURCES_TYPE_JAVAHELP = "javahelp"; // NOI18N |
| static final String[] COMMON_TEST_TYPES = {"unit", "qa-functional"}; // NOI18N |
| |
| public static final String OPENIDE_MODULE_NAME = "OpenIDE-Module-Name"; // NOI18N |
| |
| private final AntProjectHelper helper; |
| private final Evaluator eval; |
| private final Lookup lookup; |
| private final InstanceContent ic; |
| private Map<FileObject,Element> extraCompilationUnits; |
| private final GeneratedFilesHelper genFilesHelper; |
| |
| @Messages({ |
| "# {0} - project directory", "NbModuleProject.too_new=This version of the IDE is too old to read metadata in {0}.", |
| "LBL_source_packages=Source Packages", |
| "LBL_qa-functional_test_packages=Functional Test Packages", |
| "LBL_unit_test_packages=Unit Test Packages", |
| "LBL_javahelp_packages=JavaHelp" |
| }) |
| public NbModuleProject(AntProjectHelper helper) throws IOException { |
| AuxiliaryConfiguration aux = helper.createAuxiliaryConfiguration(); |
| for (int v = 4; v < 10; v++) { |
| if (aux.getConfigurationFragment("data", "http://www.netbeans.org/ns/nb-module-project/" + v, true) != null) { // NOI18N |
| throw Exceptions.attachLocalizedMessage(new IOException("too new"), // NOI18N |
| NbModuleProject_too_new(FileUtil.getFileDisplayName(helper.getProjectDirectory()))); |
| } |
| } |
| this.helper = helper; |
| genFilesHelper = new GeneratedFilesHelper(helper); |
| Util.err.log("Loading project in " + getProjectDirectory()); |
| if (getCodeNameBase() == null) { |
| throw new IOException("Misconfigured project in " + FileUtil.getFileDisplayName(getProjectDirectory()) + " has no defined <code-name-base>"); // NOI18N |
| } |
| if (getModuleType() == NbModuleType.NETBEANS_ORG && ModuleList.findNetBeansOrg(getProjectDirectoryFile()) == null) { |
| // #69097: preferable to throwing an assertion error later... |
| throw new IOException("netbeans.org-type module requires at least nbbuild: " + FileUtil.getFileDisplayName(helper.getProjectDirectory())); // NOI18N |
| } |
| eval = new Evaluator(this); |
| // XXX could add globs for other package roots too |
| List<String> from = new ArrayList<String>(); |
| List<String> to = new ArrayList<String>(); |
| from.add("${src.dir}/*.java"); // NOI18N |
| to.add("${build.classes.dir}/*.class"); // NOI18N |
| for (String type : supportedTestTypes(false)) { |
| from.add("${test." + type + ".src.dir}/*.java"); // NOI18N |
| to.add("${build.test." + type + ".classes.dir}/*.class"); // NOI18N |
| } |
| FileBuiltQueryImplementation fileBuilt = helper.createGlobFileBuiltQuery( |
| eval,from.toArray(new String[0]), to.toArray(new String[0])); |
| SourcesHelper sourcesHelper = new SourcesHelper(this, helper, eval); |
| // Temp build dir is always internal; NBM build products go elsewhere, but |
| // difficult to predict statically exactly what they are! |
| // XXX would be good to mark at least the module JAR as owned by this project |
| // (currently FOQ/SH do not support that) |
| sourcesHelper.sourceRoot("${src.dir}")// NOI18N |
| .hint(JavaProjectConstants.SOURCES_HINT_MAIN) |
| .displayName(LBL_source_packages()).add() // as principal root |
| .type(JavaProjectConstants.SOURCES_TYPE_JAVA).add(); // as typed root |
| for (String type : supportedTestTypes(false)) { |
| sourcesHelper.sourceRoot("${test." + type + ".src.dir}")// NOI18N |
| .hint(JavaProjectConstants.SOURCES_HINT_TEST) |
| .displayName(type.equals("qa-functional") ? LBL_qa_functional_test_packages() : LBL_unit_test_packages()).add() // as principal root |
| .type(JavaProjectConstants.SOURCES_TYPE_JAVA).add(); // as typed root |
| } |
| // XXX other principal source roots, as needed... |
| if (helper.resolveFileObject("javahelp/manifest.mf") == null) { // NOI18N |
| // Special hack for core - ignore core/javahelp |
| sourcesHelper.sourceRoot("javahelp").type(SOURCES_TYPE_JAVAHELP) |
| .displayName(LBL_javahelp_packages()).add(); |
| } |
| for (Map.Entry<FileObject,Element> entry : getExtraCompilationUnits().entrySet()) { |
| Element pkgrootEl = XMLUtil.findElement(entry.getValue(), "package-root", NbModuleProject.NAMESPACE_SHARED); // NOI18N |
| String pkgrootS = XMLUtil.findText(pkgrootEl); |
| FileObject root = entry.getKey(); |
| // #192773: try to make a unique display name; a schema addition might be better |
| String displayName = FileUtil.getRelativePath(getProjectDirectory(), root); |
| if (displayName == null) { |
| displayName = root.getNameExt(); |
| } |
| sourcesHelper.sourceRoot(pkgrootS).type(JavaProjectConstants.SOURCES_TYPE_JAVA).displayName(displayName).add(); |
| } |
| // #56457: support external source roots too. |
| sourcesHelper.registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT); |
| ic = new InstanceContent(); |
| lookup = createLookup(new Info(), aux, helper, fileBuilt, sourcesHelper); |
| } |
| |
| public @Override String toString() { |
| return "NbModuleProject[" + getProjectDirectory() + "]"; // NOI18N |
| } |
| |
| @Override public Lookup getLookup() { |
| return lookup; |
| } |
| |
| public void refreshLookup() { |
| if (getModuleType() == NbModuleType.SUITE_COMPONENT) { |
| if (lookup.lookup(SuiteProvider.class) == null) { |
| ic.add(new SuiteProviderImpl()); |
| } |
| } else { |
| SuiteProvider sp = lookup.lookup(SuiteProvider.class); |
| if (sp != null) { |
| ic.remove(sp); |
| } |
| } |
| } |
| |
| private Lookup createLookup(ProjectInformation info, AuxiliaryConfiguration aux, AntProjectHelper helper, FileBuiltQueryImplementation fileBuilt, final SourcesHelper sourcesHelper) { |
| Sources srcs = sourcesHelper.createSources(); |
| srcs.addChangeListener(new ChangeListener() { |
| @Override public void stateChanged(ChangeEvent e) { |
| // added source root, probably via SourceGroupModifiedImplementation |
| getLookup().lookup(ModuleActions.class).refresh(); |
| } |
| }); |
| ExtraSJQEvaluator eJSQEval = new ExtraSJQEvaluator(); |
| |
| ic.add(this); |
| ic.add(info); |
| ic.add(aux); |
| ic.add(helper.createCacheDirectoryProvider()); |
| ic.add(helper.createAuxiliaryProperties()); |
| ic.add(new SavedHook()); |
| ic.add(UILookupMergerSupport.createProjectOpenHookMerger(new OpenedHook())); |
| ic.add(new ModuleActions(this)); |
| ic.add(new ClassPathProviderImpl(this)); |
| ic.add(new SourceForBinaryImpl(this)); |
| ic.add(new BinaryForSourceImpl(this)); |
| ic.add(LookupMergerSupport.createSFBLookupMerger()); |
| ic.add(createESQI(eJSQEval)); |
| ic.add(new JavadocForBinaryImpl(this)); |
| ic.add(LookupMergerSupport.createJFBLookupMerger()); |
| ic.add(createEJQI(eJSQEval)); |
| ic.add(new UnitTestForSourceQueryImpl(this)); |
| ic.add(new ModuleLogicalView(this)); |
| ic.add(new SubprojectProviderImpl(this)); |
| ic.add(fileBuilt); |
| ic.add(new AccessibilityQueryImpl(this)); |
| ic.add(new SourceLevelQueryImpl(this)); |
| //ic.add(new ProjectWhiteListQueryImplementation(this)); |
| ic.add(new ProjectWhiteListQueryImplementation(this)); |
| ic.add(new NbModulePackageModifierImplementation(this)); |
| ic.add(helper.createSharabilityQuery2(evaluator(), new String[0], new String[]{ |
| "${build.dir}", // NOI18N |
| })); |
| ic.add(srcs); |
| ic.add(sourcesHelper.createSourceGroupModifierImplementation()); // XXX only for unit tests, will need custom impl for qa-functional |
| ic.add(new AntArtifactProviderImpl(this, helper, evaluator())); |
| ic.add(new CustomizerProviderImpl(this, getHelper(), evaluator())); |
| ic.add(new NbModuleProviderImpl(this)); |
| ic.add(new NbRefactoringProviderImpl(this)); |
| ic.add(new NbProjectProviderImpl(this)); |
| ic.add(new PrivilegedTemplatesImpl()); |
| ic.add(new ModuleProjectClassPathExtender(this)); |
| ic.add(new LocalizedBundleInfoProvider()); |
| ic.add(new ModuleOperations(this)); |
| ic.add(LookupProviderSupport.createSourcesMerger()); |
| ic.add(UILookupMergerSupport.createPrivilegedTemplatesMerger()); |
| ic.add(UILookupMergerSupport.createRecommendedTemplatesMerger()); |
| ic.add(new TemplateAttributesProvider(this, getHelper(), getModuleType() == NbModuleType.NETBEANS_ORG)); |
| ic.add(new FileEncodingQueryImpl()); |
| ic.add(new AnnotationProcessingQueryImpl(this)); |
| ic.add(new PlatformJarProviderImpl()); |
| |
| if (getModuleType() == NbModuleType.SUITE_COMPONENT) { |
| ic.add(new SuiteProviderImpl()); |
| } |
| Lookup baseLookup = new AbstractLookup(ic); |
| return LookupProviderSupport.createCompositeLookup(baseLookup, "Projects/org-netbeans-modules-apisupport-project/Lookup"); //NOI18N |
| } |
| |
| |
| |
| @Override public FileObject getProjectDirectory() { |
| return helper.getProjectDirectory(); |
| } |
| |
| public File getProjectDirectoryFile() { |
| return FileUtil.toFile(getProjectDirectory()); |
| } |
| |
| /** |
| * Get the minimum harness version required to work with this module. |
| */ |
| public HarnessVersion getMinimumHarnessVersion() { |
| if (helper.createAuxiliaryConfiguration().getConfigurationFragment(NbModuleProject.NAME_SHARED, NbModuleProject.NAMESPACE_SHARED_2, true) != null) { |
| return HarnessVersion.V50; |
| } else { |
| return HarnessVersion.V55u1; |
| } |
| } |
| |
| /** |
| * Replacement for {@link AntProjectHelper#getPrimaryConfigurationData} |
| * taking into account the /2 -> /3 upgrade. |
| */ |
| public Element getPrimaryConfigurationData() { |
| return ProjectManager.mutex().readAccess(new Mutex.Action<Element>() { |
| @Override public Element run() { |
| AuxiliaryConfiguration ac = helper.createAuxiliaryConfiguration(); |
| Element data = ac.getConfigurationFragment(NbModuleProject.NAME_SHARED, NbModuleProject.NAMESPACE_SHARED_2, true); |
| if (data != null) { |
| return XMLUtil.translateXML(data, NbModuleProject.NAMESPACE_SHARED); |
| } else { |
| return helper.getPrimaryConfigurationData(true); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Replacement for {@link AntProjectHelper#putPrimaryConfigurationData} |
| * taking into account the /2 -> /3 upgrade. |
| */ |
| public void putPrimaryConfigurationData(final Element data) { |
| ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() { |
| @Override public Void run() { |
| AuxiliaryConfiguration ac = helper.createAuxiliaryConfiguration(); |
| if (ac.getConfigurationFragment(NbModuleProject.NAME_SHARED, NbModuleProject.NAMESPACE_SHARED_2, true) != null) { |
| ac.putConfigurationFragment(XMLUtil.translateXML(data, NbModuleProject.NAMESPACE_SHARED_2), true); |
| } else { |
| helper.putPrimaryConfigurationData(data, true); |
| } |
| return null; |
| } |
| }); |
| } |
| |
| /** Returns a relative path to a project's source directory. */ |
| public String getSourceDirectoryPath() { |
| return evaluator().getProperty("src.dir"); // NOI18N |
| } |
| |
| public NbModuleType getModuleType() { |
| Element data = getPrimaryConfigurationData(); |
| if (XMLUtil.findElement(data, "suite-component", NbModuleProject.NAMESPACE_SHARED) != null) { // NOI18N |
| return NbModuleType.SUITE_COMPONENT; |
| } else if (XMLUtil.findElement(data, "standalone", NbModuleProject.NAMESPACE_SHARED) != null) { // NOI18N |
| return NbModuleType.STANDALONE; |
| } else { |
| return NbModuleType.NETBEANS_ORG; |
| } |
| } |
| |
| public @CheckForNull FileObject getManifestFile() { |
| String v = evaluator().getProperty("manifest.mf"); |
| return v != null ? helper.resolveFileObject(v) : null; |
| } |
| |
| public @CheckForNull Manifest getManifest() { |
| return Util.getManifest(getManifestFile()); |
| } |
| |
| public AntProjectHelper getHelper() { |
| return helper; |
| } |
| |
| public PropertyEvaluator evaluator() { |
| return eval; |
| } |
| |
| private FileObject getDir(String prop) { |
| String v = evaluator().getProperty(prop); |
| if (v == null) { |
| Logger.getLogger(NbModuleProject.class.getName()).log(Level.WARNING, |
| "#150612: property {0} was undefined in {1}", new Object[] {prop, this}); |
| return null; |
| } |
| return helper.resolveFileObject(v); |
| } |
| |
| public FileObject getSourceDirectory() { |
| return getDir("src.dir"); // NOI18N |
| } |
| |
| public FileObject getTestSourceDirectory(String type) { |
| return getDir("test." + type + ".src.dir"); // NOI18N |
| } |
| |
| private File getTestSourceDirectoryFile(String type) { |
| String dir = evaluator().getProperty("test." + type + ".src.dir"); // NOI18N |
| return dir != null ? helper.resolveFile(dir) : null; |
| } |
| |
| public @NonNull File getClassesDirectory() { |
| String classesDir = evaluator().getProperty("build.classes.dir"); // NOI18N |
| return helper.resolveFile(classesDir != null ? classesDir : "unknown"); |
| } |
| |
| public @NonNull File getTestClassesDirectory(String type) { |
| String testClassesDir = evaluator().getProperty("build.test." + type + ".classes.dir"); // NOI18N |
| return helper.resolveFile(testClassesDir != null ? testClassesDir : "unknown"); |
| } |
| |
| public File getGeneratedClassesDirectory() { |
| return gensrc(getClassesDirectory()); |
| } |
| |
| public File getTestGeneratedClassesDirectory(String type) { |
| return gensrc(getTestClassesDirectory(type)); |
| } |
| |
| private File gensrc(File clazz) { |
| return new File(clazz.getParentFile(), clazz.getName() + "-generated"); // NOI18N |
| } |
| |
| public FileObject getJavaHelpDirectory() { |
| if (helper.resolveFileObject("javahelp/manifest.mf") != null) { // NOI18N |
| // Special hack for core. |
| return null; |
| } |
| return helper.resolveFileObject("javahelp"); // NOI18N |
| } |
| |
| public @NonNull File getModuleJarLocation() { |
| String v = evaluator().evaluate("${cluster}/${module.jar}"); |
| // XXX could use ModuleList here instead |
| return helper.resolveFile(v != null ? v : "unknown"); |
| } |
| |
| public @NonNull File getTestUserDirLockFile() { |
| String v = evaluator().evaluate("${test.user.dir}/lock"); |
| return getHelper().resolveFile(v != null ? v : "unknown"); |
| } |
| |
| public String getCodeNameBase() { |
| Element config = getPrimaryConfigurationData(); |
| Element cnb = XMLUtil.findElement(config, "code-name-base", NbModuleProject.NAMESPACE_SHARED); // NOI18N |
| if (cnb != null) { |
| return XMLUtil.findText(cnb); |
| } else { |
| return null; |
| } |
| } |
| |
| private String getModuleName() { |
| Manifest m = getManifest(); |
| if (m != null) { |
| String moduleName = m.getMainAttributes().getValue(OPENIDE_MODULE_NAME); |
| if (moduleName != null) { |
| return moduleName; |
| } |
| } |
| return null; |
| } |
| |
| public @CheckForNull String getSpecVersion() { |
| //TODO shall we check for illegal cases like "none-defined" or "both-defined" here? |
| Manifest m = getManifest(); |
| if (m != null) { |
| String manVersion = ManifestManager.getInstance(m, false).getSpecificationVersion(); |
| if (manVersion != null) { |
| return manVersion; |
| } |
| } |
| String svb = evaluator().getProperty(SingleModuleProperties.SPEC_VERSION_BASE); |
| if (svb != null) { |
| return svb/* #72826 */.replaceAll("(\\.[0-9]+)\\.0$", "$1"); // NOI18N |
| } |
| return null; |
| } |
| |
| /** |
| * Slash-separated path inside netbeans.org sources, or null for external modules. |
| */ |
| public String getPathWithinNetBeansOrg() { |
| FileObject nbroot = getNbrootFileObject(null); |
| if (nbroot != null) { |
| return FileUtil.getRelativePath(nbroot, getProjectDirectory()); |
| } else { |
| return null; |
| } |
| } |
| |
| private File getNbroot() { |
| File dir = getProjectDirectoryFile(); |
| File nbroot = ModuleList.findNetBeansOrg(dir); |
| if (nbroot != null) { |
| return nbroot; |
| } else { |
| // OK, not it. |
| NbPlatform platform = getPlatform(); |
| if (platform != null) { |
| URL[] roots = platform.getSourceRoots(); |
| for (int i = 0; i < roots.length; i++) { |
| if (roots[i].getProtocol().equals("file")) { // NOI18N |
| File f = Utilities.toFile(URI.create(roots[i].toExternalForm())); |
| if (ModuleList.isNetBeansOrg(f)) { |
| return f; |
| } |
| } |
| } |
| } |
| // Did not find it. |
| return null; |
| } |
| } |
| |
| public File getNbrootFile(String path) { |
| File nbroot = getNbroot(); |
| if (nbroot != null) { |
| return new File(nbroot, path.replace('/', File.separatorChar)); |
| } else { |
| return null; |
| } |
| } |
| |
| public FileObject getNbrootFileObject(String path) { |
| File f = path != null ? getNbrootFile(path) : getNbroot(); |
| if (f != null) { |
| return FileUtil.toFileObject(f); |
| } else { |
| return null; |
| } |
| } |
| |
| public ModuleList getModuleList() throws IOException { |
| NbPlatform p = getPlatform(false); |
| if (p == null || ! p.isValid()) { |
| // #67148: have to use something... (and getEntry(codeNameBase) will certainly fail!) |
| if (getModuleType() == NbModuleType.NETBEANS_ORG) { |
| // #174689: NB.org modules scan sources, not binary platform |
| return ModuleList.getModuleList(getProjectDirectoryFile(), null); |
| } |
| // TODO dealing with nonexistent platforms probably not complete / 100% correct yet, |
| // see #61227; but project with unresolved platform may also load as result |
| // of suite-chaining; perhaps resolve already in loadProject |
| Util.err.log(ErrorManager.WARNING, "Project in " + FileUtil.getFileDisplayName(getProjectDirectory()) // NOI18N |
| + " is missing its platform '" + evaluator().getProperty("nbplatform.active") + "', switching to default platform"); // NOI18N |
| NbPlatform p2 = NbPlatform.getDefaultPlatform(); |
| return ModuleList.getModuleList(getProjectDirectoryFile(), p2 != null ? p2.getDestDir() : null); |
| } |
| ModuleList ml; |
| try { |
| ml = ModuleList.getModuleList(getProjectDirectoryFile(), p.getDestDir()); |
| } catch (IOException x) { |
| // #69029: maybe invalidated platform? Try the default platform instead. |
| Logger.getLogger(NbModuleProject.class.getName()).log(Level.FINE, null, x); |
| NbPlatform p2 = NbPlatform.getDefaultPlatform(); |
| return ModuleList.getModuleList(getProjectDirectoryFile(), p2 != null ? p2.getDestDir() : null); |
| } |
| if (ml.getEntry(getCodeNameBase()) == null) { |
| ModuleList.refresh(); |
| ml = ModuleList.getModuleList(getProjectDirectoryFile()); |
| if (ml.getEntry(getCodeNameBase()) == null) { |
| // XXX try to give better diagnostics - as examples are discovered |
| Util.err.log(ErrorManager.WARNING, "Project in " + FileUtil.getFileDisplayName(getProjectDirectory()) + " does not appear to be listed in its own module list; some sort of misconfiguration (e.g. not listed in its own suite)"); // NOI18N |
| } |
| } |
| return ml; |
| } |
| |
| /** |
| * Get the platform which this project is currently associated with. |
| * @param fallback if true, fall back to the default platform if necessary |
| * @return the current platform; or null if fallback is false and there is no |
| * platform specified, or an invalid platform is specified, or even if |
| * fallback is true but even the default platform is not available |
| */ |
| public NbPlatform getPlatform(boolean fallback) { |
| NbPlatform p = getPlatform(); |
| if (fallback && (p == null || !p.isValid())) { |
| p = NbPlatform.getDefaultPlatform(); |
| } |
| return p; |
| } |
| |
| private NbPlatform getPlatform() { |
| File file = getPlatformFile(); |
| if (file == null) { |
| return null; |
| } |
| String harnessDir = evaluator().getProperty("harness.dir"); |
| return NbPlatform.getPlatformByDestDir(file, harnessDir != null ? getHelper().resolveFile(harnessDir) : null); |
| } |
| |
| File getPlatformFile() { |
| String prop = evaluator().getProperty(ModuleList.NETBEANS_DEST_DIR); |
| if (prop == null) { |
| return null; |
| } |
| return getHelper().resolveFile(prop); |
| } |
| |
| /** |
| * Check whether Javadoc generation is possible. |
| */ |
| public boolean supportsJavadoc() { |
| if (evaluator().getProperty("module.javadoc.packages") != null) { |
| return true; |
| } |
| Element config = getPrimaryConfigurationData(); |
| Element pubPkgs = XMLUtil.findElement(config, "public-packages", NbModuleProject.NAMESPACE_SHARED); // NOI18N |
| if (pubPkgs == null) { |
| // Try <friend-packages> too. |
| pubPkgs = XMLUtil.findElement(config, "friend-packages", NbModuleProject.NAMESPACE_SHARED); // NOI18N |
| } |
| return pubPkgs != null && !XMLUtil.findSubElements(pubPkgs).isEmpty(); |
| } |
| |
| public List<String> supportedTestTypes() { |
| return supportedTestTypes(true); |
| } |
| |
| public List<String> supportedTestTypes(boolean mustExist) { |
| List<String> types = new ArrayList<String>(); |
| for (String type : COMMON_TEST_TYPES) { |
| if (((mustExist && getTestSourceDirectory(type) != null) |
| || (! mustExist && getTestSourceDirectoryFile(type) != null)) |
| && !Boolean.parseBoolean(evaluator().getProperty("disable." + type + ".tests"))) { |
| types.add(type); |
| } |
| } |
| // XXX could look for others in project.xml, in which case fix Evaluator to use that |
| return types; |
| } |
| |
| /** |
| * Find marked extra compilation units. |
| * Gives a map from the package root to the defining XML element. |
| */ |
| public Map<FileObject,Element> getExtraCompilationUnits() { |
| if (extraCompilationUnits == null) { |
| extraCompilationUnits = new HashMap<FileObject,Element>(); |
| for (Element ecu : XMLUtil.findSubElements(getPrimaryConfigurationData())) { |
| if (ecu.getLocalName().equals("extra-compilation-unit")) { // NOI18N |
| Element pkgrootEl = XMLUtil.findElement(ecu, "package-root", NbModuleProject.NAMESPACE_SHARED); // NOI18N |
| String pkgrootS = XMLUtil.findText(pkgrootEl); |
| String pkgrootEval = evaluator().evaluate(pkgrootS); |
| FileObject pkgroot = pkgrootEval != null ? getHelper().resolveFileObject(pkgrootEval) : null; |
| if (pkgroot == null) { |
| Util.err.log(ErrorManager.WARNING, "Could not find package-root " + pkgrootEval + " for " + getCodeNameBase()); |
| continue; |
| } |
| extraCompilationUnits.put(pkgroot, ecu); |
| } |
| } |
| } |
| return extraCompilationUnits; |
| } |
| |
| /** Get the Java source level used for this module. Default is 1.4. */ |
| public String getJavacSource() { |
| String javacSource = evaluator().getProperty(SingleModuleProperties.JAVAC_SOURCE); |
| assert javacSource != null; |
| return javacSource; |
| } |
| |
| private ClassPath[] boot, source, compile; |
| private final class OpenedHook extends ProjectOpenedHook { |
| OpenedHook() {} |
| @Override protected void projectOpened() { |
| open(); |
| } |
| @Override protected void projectClosed() { |
| try { |
| ProjectManager.getDefault().saveProject(NbModuleProject.this); |
| } catch (IOException e) { |
| Util.err.notify(e); |
| } |
| // XXX could discard caches, etc. |
| // unregister project's classpaths to GlobalClassPathRegistry |
| if (boot != null) { |
| assert source != null && compile != null : "#46802 / #201230"; |
| GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, boot); |
| GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, source); |
| GlobalPathRegistry.getDefault().unregister(ClassPath.COMPILE, compile); |
| boot = null; |
| source = null; |
| compile = null; |
| } |
| } |
| } |
| /** |
| * Run the open hook. |
| * For use from unit tests. |
| */ |
| public void open() { |
| // write user.properties.file=$userdir/build.properties to platform-private.properties |
| if (getModuleType() == NbModuleType.STANDALONE) { |
| // XXX skip this in case nbplatform.active is not defined |
| final Project p = this; // XXX workaround for NB editor bug |
| ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() { |
| @Override public Void run() { |
| String path = "nbproject/private/platform-private.properties"; // NOI18N |
| EditableProperties ep = getHelper().getProperties(path); |
| File buildProperties = new File(System.getProperty("netbeans.user"), "build.properties"); // NOI18N |
| ep.setProperty("user.properties.file", buildProperties.getAbsolutePath()); //NOI18N |
| getHelper().putProperties(path, ep); |
| try { |
| ProjectManager.getDefault().saveProject(p); |
| } catch (IOException e) { |
| ErrorManager.getDefault().notify(e); |
| } |
| return null; |
| } |
| }); |
| } |
| // register project's classpaths to GlobalClassPathRegistry |
| ClassPathProviderImpl cpProvider = lookup.lookup(ClassPathProviderImpl.class); |
| ClassPath[] _boot = cpProvider.getProjectClassPaths(ClassPath.BOOT); |
| assert _boot != null : "No BOOT path"; |
| ClassPath[] _source = cpProvider.getProjectClassPaths(ClassPath.SOURCE); |
| assert _source != null : "No SOURCE path"; |
| ClassPath[] _compile = cpProvider.getProjectClassPaths(ClassPath.COMPILE); |
| assert _compile != null : "No COMPILE path"; |
| // Possible cause of #68414: do not change instance vars until after the dangerous stuff has been computed. |
| GlobalPathRegistry.getDefault().register(ClassPath.BOOT, _boot); |
| GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, _source); |
| GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, _compile); |
| boot = _boot; |
| source = _source; |
| compile = _compile; |
| // refresh build.xml and build-impl.xml for external modules |
| if (getModuleType() != NbModuleType.NETBEANS_ORG) { |
| try { |
| refreshBuildScripts(true); |
| } catch (IOException e) { |
| ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); |
| } |
| } |
| } |
| |
| /** |
| * <strong>For use from unit tests only.</strong> Returns {@link |
| * LocalizedBundleInfo} for this project. |
| */ |
| public @CheckForNull LocalizedBundleInfo getBundleInfo() { |
| return getLookup().lookup(LocalizedBundleInfo.Provider.class).getLocalizedBundleInfo(); |
| } |
| |
| private int atomicActionCounter = 0; |
| |
| /** See issue #69440 for more details. */ |
| public synchronized void setRunInAtomicAction(boolean runInAtomicAction) { |
| if (atomicActionCounter == 0 && ! runInAtomicAction) { |
| throw new IllegalArgumentException("Not in atomic action"); |
| } // NOI18N |
| atomicActionCounter += runInAtomicAction ? 1 : -1; |
| if (runInAtomicAction && atomicActionCounter == 1) { |
| eval.setRunInAtomicAction(true); |
| } else if (! runInAtomicAction && atomicActionCounter == 0) { |
| eval.setRunInAtomicAction(false); |
| } |
| } |
| |
| /** See issue #69440 for more details. */ |
| public synchronized boolean isRunInAtomicAction() { |
| return eval.isRunInAtomicAction(); |
| } |
| |
| private final class Info implements ProjectInformation, PropertyChangeListener { |
| |
| private final PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); |
| |
| private final String name; |
| private final String openideModuleName; |
| private String displayName; |
| |
| Info() { |
| String cnb = getCodeNameBase(); |
| name = cnb != null ? cnb : /* #70490 */getProjectDirectory().toString(); |
| String omn = getModuleName(); |
| openideModuleName = omn; |
| } |
| |
| @Override public String getName() { |
| return name; |
| } |
| |
| private String getOpenideModuleName() { |
| return openideModuleName; |
| } |
| |
| @Override public String getDisplayName() { |
| if (displayName == null) { |
| LocalizedBundleInfo bundleInfo = getBundleInfo(); |
| if (bundleInfo != null) { |
| displayName = bundleInfo.getDisplayName(); |
| } |
| } |
| if (displayName == null) { |
| displayName = getOpenideModuleName(); |
| } |
| if (/* #70490 */displayName == null) { |
| displayName = getName(); |
| } |
| assert displayName != null : NbModuleProject.this; |
| return displayName; |
| } |
| |
| private void setDisplayName(String newDisplayName) { |
| String oldDisplayName = getDisplayName(); |
| displayName = newDisplayName == null ? getName() : newDisplayName; |
| firePropertyChange(ProjectInformation.PROP_DISPLAY_NAME, oldDisplayName, displayName); |
| } |
| |
| @Override public Icon getIcon() { |
| return NB_PROJECT_ICON; |
| } |
| |
| @Override public Project getProject() { |
| return NbModuleProject.this; |
| } |
| |
| @Override public void addPropertyChangeListener(PropertyChangeListener pchl) { |
| changeSupport.addPropertyChangeListener(pchl); |
| } |
| |
| @Override public void removePropertyChangeListener(PropertyChangeListener pchl) { |
| changeSupport.removePropertyChangeListener(pchl); |
| } |
| |
| private void firePropertyChange(String propName, Object oldValue, Object newValue) { |
| changeSupport.firePropertyChange(propName, oldValue, newValue); |
| } |
| |
| @Override public void propertyChange(PropertyChangeEvent evt) { |
| if (ProjectInformation.PROP_DISPLAY_NAME.equals(evt.getPropertyName())) { |
| setDisplayName((String) evt.getNewValue()); |
| } |
| } |
| |
| } |
| |
| public void notifyDeleting() { |
| eval.removeListeners(); |
| } |
| |
| private final class SavedHook extends ProjectXmlSavedHook { |
| |
| SavedHook() {} |
| |
| @Override protected void projectXmlSaved() throws IOException { |
| // refresh build.xml and build-impl.xml for external modules |
| if (getModuleType() != NbModuleType.NETBEANS_ORG) { |
| refreshBuildScripts(false); |
| } |
| } |
| |
| } |
| |
| public void refreshBuildScripts(boolean checkForProjectXmlModified) throws IOException { |
| refreshBuildScripts(checkForProjectXmlModified, getPlatform(true)); |
| } |
| |
| public void refreshBuildScripts(boolean checkForProjectXmlModified, NbPlatform customPlatform) throws IOException { |
| if (customPlatform == null) { // #181798 |
| return; |
| } |
| String buildImplPath = |
| customPlatform.getHarnessVersion().compareTo(HarnessVersion.V65) <= 0 |
| || eval.getProperty(SuiteProperties.CLUSTER_PATH_PROPERTY) == null |
| ? "build-impl-65.xsl" : "build-impl.xsl"; // NOI18N |
| genFilesHelper.refreshBuildScript( |
| GeneratedFilesHelper.BUILD_IMPL_XML_PATH, |
| NbModuleProject.class.getResource("resources/" + buildImplPath), // NOI18N |
| checkForProjectXmlModified); |
| genFilesHelper.refreshBuildScript( |
| GeneratedFilesHelper.BUILD_XML_PATH, |
| NbModuleProject.class.getResource("resources/build.xsl"), // NOI18N |
| checkForProjectXmlModified); |
| } |
| |
| private final class SuiteProviderImpl implements SuiteProvider { |
| |
| @Override public File getSuiteDirectory() { |
| String suiteDir = evaluator().getProperty("suite.dir"); // NOI18N |
| return suiteDir == null ? null : helper.resolveFile(suiteDir); |
| } |
| |
| @Override public File getClusterDirectory() { |
| return getModuleJarLocation().getParentFile().getParentFile().getAbsoluteFile(); |
| } |
| |
| } |
| |
| private static final class PrivilegedTemplatesImpl implements PrivilegedTemplates, RecommendedTemplates { |
| |
| private static final String[] PRIVILEGED_NAMES = { |
| "Templates/Classes/Class.java", // NOI18N |
| "Templates/Classes/Package", // NOI18N |
| "Templates/Classes/Interface.java", // NOI18N |
| //"Templates/GUIForms/JPanel.java", // NOI18N |
| "Templates/JUnit/SimpleJUnitTest.java", // NOI18N |
| "Templates/" + UIUtil.TEMPLATE_FOLDER + "/" + UIUtil.TEMPLATE_ACTION_ID, |
| "Templates/" + UIUtil.TEMPLATE_FOLDER + "/newHTML", |
| "Templates/" + UIUtil.TEMPLATE_FOLDER + "/" + UIUtil.TEMPLATE_WINDOW_ID, |
| //"Templates/Other/properties.properties", // NOI18N |
| }; |
| static { |
| assert PRIVILEGED_NAMES.length <= 10 : "Too many privileged templates to fit! extras will be ignored: " + |
| Arrays.asList(PRIVILEGED_NAMES).subList(10, PRIVILEGED_NAMES.length); |
| } |
| |
| private static final String[] RECOMMENDED_TYPES = { |
| "java-classes", // NOI18N |
| "java-main-class", // NOI18N |
| "java-forms", // NOI18N |
| "java-beans", // NOI18N |
| "oasis-XML-catalogs", // NOI18N |
| "REST-clients", // NOI18N |
| "XML", // NOI18N |
| "ant-script", // NOI18N |
| "ant-task", // NOI18N |
| "junit", // NOI18N |
| "simple-files", // NOI18N |
| UIUtil.TEMPLATE_CATEGORY, |
| }; |
| |
| @Override public String[] getPrivilegedTemplates() { |
| return PRIVILEGED_NAMES; |
| } |
| |
| @Override public String[] getRecommendedTypes() { |
| return RECOMMENDED_TYPES; |
| } |
| } |
| |
| private final class LocalizedBundleInfoProvider extends FileChangeAdapter implements LocalizedBundleInfo.Provider { |
| |
| private LocalizedBundleInfo bundleInfo; |
| private FileObject manifestFO; |
| private final FileChangeListener listener = FileUtil.weakFileChangeListener(this, null); |
| |
| @Override public LocalizedBundleInfo getLocalizedBundleInfo() { |
| if (bundleInfo == null) { |
| Manifest mf = getManifest(); |
| FileObject srcFO = getSourceDirectory(); |
| if (mf != null && srcFO != null) { |
| bundleInfo = ApisupportAntUtils.findLocalizedBundleInfo(srcFO, mf); |
| } |
| if (bundleInfo != null) { |
| bundleInfo.addPropertyChangeListener(getLookup().lookup(Info.class)); |
| } |
| if (mf != null) { |
| manifestFO = getManifestFile(); |
| if (manifestFO != null) { |
| manifestFO.addFileChangeListener(listener); |
| } |
| } |
| } |
| return bundleInfo; |
| } |
| |
| @Override public void fileChanged(FileEvent fe) { |
| // cannot reload manifest-dependent things immediately (see 67961 for more details) |
| bundleInfo = null; |
| } |
| |
| @Override public void fileDeleted(FileEvent fe) { |
| manifestFO = null; |
| } |
| |
| } |
| |
| private SourceForBinaryQueryImplementation createESQI(ExtraSJQEvaluator eJSQEval) { |
| SourceForBinaryQueryImplementation sfbqi = ExtraSourceJavadocSupport.createExtraSourceQueryImplementation(this, getHelper(), eJSQEval); |
| registerListener(sfbqi, eJSQEval); |
| return sfbqi; |
| } |
| |
| private JavadocForBinaryQueryImplementation createEJQI(ExtraSJQEvaluator eJSQEval) { |
| JavadocForBinaryQueryImplementation jfbqi = ExtraSourceJavadocSupport.createExtraJavadocQueryImplementation(this, getHelper(), eJSQEval); |
| registerListener(jfbqi, eJSQEval); |
| return jfbqi; |
| } |
| |
| private void registerListener(Object qimpl, ExtraSJQEvaluator eJSQEval) { |
| try { |
| // XXX #66275: ugly hack until proper API change; |
| // we need ESJQI to work when project is loaded - not opened - to resolve deps on lib wrapper modules correctly |
| Field listenerF = qimpl.getClass().getDeclaredField("listener"); // NOI18N |
| listenerF.setAccessible(true); |
| eJSQEval.addPropertyChangeListener((PropertyChangeListener) listenerF.get(qimpl)); |
| } catch (Exception ex) { |
| Logger.getLogger(NbModuleProject.class.getName()).log(Level.FINE, "Turning off source query support for loaded project '" + ProjectUtils.getInformation(this).getDisplayName() + "'", ex); |
| } |
| } |
| |
| /** Matches ExtraProjectSourceForBinaryQueryImpl*/ |
| public static final String SOURCE_START = "source.reference."; //NOI18N |
| /** |
| * <tt><class-path-extension></tt> to <tt>file/source/javadoc.reference....</tt> properties adapter |
| * for {@link ExtraSourceJavadocSupport} query implementations. |
| */ |
| private final class ExtraSJQEvaluator implements PropertyEvaluator { |
| |
| private static final String REF_START = "file.reference."; //NOI18N |
| private static final String JAVADOC_START = "javadoc.reference."; //NOI18N |
| |
| ExtraSJQEvaluator() { |
| evaluator().addPropertyChangeListener(new PropertyChangeListener() { |
| @Override public void propertyChange(PropertyChangeEvent evt) { |
| final String prop = evt.getPropertyName(); |
| if (prop == null || prop.startsWith(SOURCE_START) || prop.startsWith(JAVADOC_START)) { |
| cache.set(null); |
| pcs.firePropertyChange(evt); |
| } |
| } |
| }); |
| } |
| |
| private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); |
| private final AtomicReference<Map<String, String>> cache = new AtomicReference<Map<String, String>>(); |
| |
| @Override public String getProperty(String prop) { |
| return getProperties().get(prop); |
| } |
| |
| @Override public String evaluate(String text) { |
| throw new UnsupportedOperationException(); // currently not needed |
| } |
| |
| @Override @NonNull public Map<String, String> getProperties() { |
| Map<String,String> ce = cache.get(); |
| if (ce == null) { |
| ce = new HashMap<String, String>(); |
| ProjectXMLManager pxm = new ProjectXMLManager(NbModuleProject.this); |
| String[] cpExts = pxm.getBinaryOrigins(); |
| for (String cpe : cpExts) { |
| addFileRef(ce, cpe); |
| } |
| Map<String, String> prjProps = evaluator().getProperties(); |
| if (prjProps != null) { |
| for (Map.Entry<String, String> entry : prjProps.entrySet()) { |
| if (entry.getKey().startsWith(SOURCE_START) || entry.getKey().startsWith(JAVADOC_START)) { |
| ce.put(entry.getKey(), entry.getValue()); |
| } |
| } |
| } |
| if (!cache.compareAndSet(null, ce)) { |
| Map<String,String> tmp = cache.get(); |
| if (tmp != null) { |
| ce = tmp; |
| } |
| } |
| } |
| return ce; |
| } |
| |
| private void addFileRef(Map<String, String> props, String path) { |
| // #66275: |
| // XXX parts of code copied from o.n.spi.project.ant.ReferenceHelper; |
| // will do proper API change later with issue #70894, will also simplify impl of isssue #66188 |
| final File normalizedFile = FileUtil.normalizeFile(PropertyUtils.resolveFile(getProjectDirectoryFile(), path)); |
| String fileID = normalizedFile.getName(); |
| // if the file is folder then add to ID string also parent folder name, |
| // i.e. if external source folder name is "src" the ID will |
| // be a bit more selfdescribing, e.g. project-src in case |
| // of ID for ant/project/src directory. |
| if (normalizedFile.isDirectory() && normalizedFile.getParentFile() != null) { |
| fileID = normalizedFile.getParentFile().getName()+"-"+normalizedFile.getName(); |
| } |
| fileID = PropertyUtils.getUsablePropertyName(fileID); |
| // we don't need to resolve duplicate file names here, all <c-p-e>-s reside in release/modules/ext |
| props.put(REF_START + fileID, path); |
| } |
| |
| @Override public void addPropertyChangeListener(PropertyChangeListener listener) { |
| pcs.addPropertyChangeListener(listener); |
| } |
| |
| @Override public void removePropertyChangeListener(PropertyChangeListener listener) { |
| pcs.removePropertyChangeListener(listener); |
| } |
| |
| } |
| |
| private class PlatformJarProviderImpl implements PlatformJarProvider { |
| |
| @Override public Set<File> getPlatformJars() throws IOException { |
| NbPlatform platform = getPlatform(true); |
| if (platform == null) { |
| return Collections.emptySet(); |
| } |
| Set<ModuleEntry> entries = platform.getModules(); |
| Set<File> jars = new HashSet<File>(entries.size()); |
| for (ModuleEntry entry : entries) { |
| jars.add(entry.getJarLocation()); |
| } |
| return jars; |
| } |
| |
| } |
| |
| } |