blob: e8ce529dc6e7b85e6f02469f2af0c726884b1c0b [file] [log] [blame]
/*
* 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.java.j2semodule;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.classpath.JavaClassPathConstants;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.api.project.ant.AntBuildExtender;
import org.netbeans.modules.java.api.common.ModuleRoots;
import org.netbeans.modules.java.api.common.Roots;
import org.netbeans.modules.java.api.common.SourceRoots;
import org.netbeans.modules.java.api.common.ant.UpdateHelper;
import org.netbeans.modules.java.api.common.classpath.ClassPathModifier;
import org.netbeans.modules.java.api.common.classpath.MultiModuleClassPathProvider;
import org.netbeans.modules.java.api.common.project.JavaActionProvider;
import org.netbeans.modules.java.api.common.project.MultiModuleActionProviderBuilder;
import org.netbeans.modules.java.api.common.project.ProjectConfigurations;
import org.netbeans.modules.java.api.common.project.ProjectHooks;
import org.netbeans.modules.java.api.common.project.ProjectOperations;
import org.netbeans.modules.java.api.common.project.ProjectProperties;
import org.netbeans.modules.java.api.common.project.PropertyEvaluatorProvider;
import org.netbeans.modules.java.api.common.project.ui.LogicalViewProviders;
import org.netbeans.modules.java.api.common.queries.QuerySupport;
import org.netbeans.modules.java.api.common.util.CommonProjectUtils;
import org.netbeans.modules.java.j2semodule.ui.customizer.CustomizerProviderImpl;
import org.netbeans.modules.java.j2semodule.ui.customizer.J2SECompositePanelProvider;
import org.netbeans.modules.java.j2semodule.ui.customizer.J2SEModularProjectProperties;
import org.netbeans.spi.java.project.support.ExtraSourceJavadocSupport;
import org.netbeans.spi.java.project.support.LookupMergerSupport;
import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.AuxiliaryConfiguration;
import org.netbeans.spi.project.ant.AntBuildExtenderFactory;
import org.netbeans.spi.project.support.LookupProviderSupport;
import org.netbeans.spi.project.ant.AntBuildExtenderImplementation;
import org.netbeans.spi.project.support.ant.AntBasedProjectRegistration;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
import org.netbeans.spi.project.support.ant.ReferenceHelper;
import org.netbeans.spi.project.ui.PrivilegedTemplates;
import org.netbeans.spi.project.ui.RecommendedTemplates;
import org.netbeans.spi.project.ui.support.UILookupMergerSupport;
import org.netbeans.spi.queries.FileEncodingQueryImplementation;
import org.netbeans.spi.whitelist.support.WhiteListQueryMergerSupport;
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;
import org.openide.util.lookup.Lookups;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.openide.util.HelpCtx;
import org.openide.util.Pair;
import org.openide.util.Parameters;
import org.openide.util.Utilities;
/**
* Represents one plain J2SE modular project.
* @author Jesse Glick, et al.
*/
@AntBasedProjectRegistration(
type=J2SEModularProject.TYPE,
iconResource="org/netbeans/modules/java/j2semodule/ui/resources/j2seModuleProject.png", // NOI18N
sharedName=J2SEModularProject.PROJECT_CONFIGURATION_NAME,
sharedNamespace= J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE,
privateName=J2SEModularProject.PRIVATE_CONFIGURATION_NAME,
privateNamespace= J2SEModularProject.PRIVATE_CONFIGURATION_NAMESPACE
)
public final class J2SEModularProject implements Project {
public static final String TYPE = "org.netbeans.modules.java.j2semodule"; // NOI18N
static final String PROJECT_CONFIGURATION_NAME = "data"; // NOI18N
public static final String PROJECT_CONFIGURATION_NAMESPACE = "http://www.netbeans.org/ns/j2se-modular-project/1"; // NOI18N
static final String PRIVATE_CONFIGURATION_NAME = "data"; // NOI18N
static final String PRIVATE_CONFIGURATION_NAMESPACE = "http://www.netbeans.org/ns/j2se-modular-project-private/1"; // NOI18N
private static final String[] EXTENSIBLE_TARGETS = new String[] {
"-do-init", //NOI18N
"-init-check", //NOI18N
"-post-clean", //NOI18N
"-pre-pre-compile", //NOI18N
"-do-compile", //NOI18N
"-do-compile-single", //NOI18N
"jar", //NOI18N
"-post-jar", //NOI18N
"run", //NOI18N
"debug", //NOI18N
"profile", //NOI18N
};
private static final Icon J2SE_MODULE_PROJECT_ICON = ImageUtilities.loadImageIcon("org/netbeans/modules/java/j2semodule/ui/resources/j2seModuleProject.png", false); // NOI18N
private static final Logger LOG = Logger.getLogger(J2SEModularProject.class.getName());
private final AuxiliaryConfiguration aux;
private final AntProjectHelper helper;
private final PropertyEvaluator eval;
private final ReferenceHelper refHelper;
private final GeneratedFilesHelper genFilesHelper;
private Lookup lookup;
private final UpdateHelper updateHelper;
private SourceRoots sourceRoots;
private SourceRoots testRoots;
private ModuleRoots moduleRoots;
private ModuleRoots testModuleRoots;
private final MultiModuleClassPathProvider cpProvider;
private final ClassPathModifier cpMod;
private MainClassUpdater mainClassUpdater;
private AntBuildExtender buildExtender;
/**
* @see J2SEProject.ProjectXmlSavedHookImpl#projectXmlSaved()
*/
private final ThreadLocal<Boolean> projectPropertiesSave;
@SuppressWarnings("LeakingThisInConstructor")
public J2SEModularProject(AntProjectHelper helper) throws IOException {
this.projectPropertiesSave = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return Boolean.FALSE;
}
};
this.helper = helper;
aux = helper.createAuxiliaryConfiguration();
UpdateProjectImpl updateProject = new UpdateProjectImpl(this, helper, aux);
this.updateHelper = new UpdateHelper(updateProject, helper);
eval = ProjectConfigurations.createPropertyEvaluator(this, helper);
for (int v = 2; v < 10; v++) {
if (aux.getConfigurationFragment("data", "http://www.netbeans.org/ns/j2se-modular-project/" + v, true) != null) { // NOI18N
throw Exceptions.attachLocalizedMessage(new IOException("too new"), // NOI18N
NbBundle.getMessage(J2SEModularProject.class, "J2SEModularProject.too_new", FileUtil.getFileDisplayName(helper.getProjectDirectory())));
}
}
refHelper = new ReferenceHelper(helper, aux, evaluator());
buildExtender = AntBuildExtenderFactory.createAntExtender(new J2SEModularExtenderImplementation(), refHelper);
genFilesHelper = new GeneratedFilesHelper(helper, buildExtender);
this.cpProvider = MultiModuleClassPathProvider.Builder.newInstance(
helper,
evaluator(),
getModuleRoots(),
getSourceRoots(),
getTestModuleRoots(),
getTestSourceRoots())
.build();
this.cpMod = new ClassPathModifier(this, this.updateHelper, evaluator(), refHelper, null, createClassPathModifierCallback(), null);
lookup = createLookup(aux, newProjectOperationsCallback(this, updateProject));
}
private ClassPathModifier.Callback createClassPathModifierCallback() {
return new ClassPathModifier.Callback() {
@Override
public String getClassPathProperty(SourceGroup sg, String type) {
assert sg != null : "SourceGroup cannot be null"; //NOI18N
assert type != null : "Type cannot be null"; //NOI18N
final String[] classPathProperty = getClassPathProvider().getPropertyName (sg, type);
if (classPathProperty == null || classPathProperty.length == 0) {
throw new UnsupportedOperationException ("Modification of [" + sg.getRootFolder().getPath() +", " + type + "] is not supported"); //NOI18N
}
return classPathProperty[0];
}
@Override
public String getElementName(String classpathProperty) {
return null;
}
};
}
/**
* Returns the project directory
* @return the directory the project is located in
*/
@Override
public FileObject getProjectDirectory() {
return helper.getProjectDirectory();
}
@Override
public String toString() {
return "J2SEModularProject[" + FileUtil.getFileDisplayName(getProjectDirectory()) + "]"; // NOI18N
}
public PropertyEvaluator evaluator() {
assert eval != null;
return eval;
}
public ReferenceHelper getReferenceHelper () {
return this.refHelper;
}
public UpdateHelper getUpdateHelper() {
return this.updateHelper;
}
@Override
public Lookup getLookup() {
return lookup;
}
public AntProjectHelper getAntProjectHelper() {
return helper;
}
private Lookup createLookup(final AuxiliaryConfiguration aux, final ProjectOperations.Callback opsCallback) {
final PlatformChangedHook platformChangedHook = new PlatformChangedHook();
final FileEncodingQueryImplementation encodingQuery = QuerySupport.createFileEncodingQuery(evaluator(), ProjectProperties.SOURCE_ENCODING);
Sources src;
final Lookup base = Lookups.fixed(J2SEModularProject.this,
//REVIEWED FOR MODULAR PROJECT
QuerySupport.createProjectInformation(updateHelper, this, J2SE_MODULE_PROJECT_ICON),
aux,
helper.createCacheDirectoryProvider(),
helper.createAuxiliaryProperties(),
LookupMergerSupport.createClassPathProviderMerger(cpProvider),
QuerySupport.createMultiModuleSourceForBinaryQuery(helper, evaluator(), getModuleRoots(), getSourceRoots(), getTestModuleRoots(), getTestSourceRoots()),
QuerySupport.createMultiModuleBinaryForSourceQuery(helper, evaluator(), getModuleRoots(), getSourceRoots(), getTestModuleRoots(), getTestSourceRoots()),
QuerySupport.createMultiModuleJavadocForBinaryQuery(helper, evaluator(), getModuleRoots(), getSourceRoots()),
ProjectHooks.createProjectXmlSavedHookBuilder(eval, updateHelper, genFilesHelper).
setBuildImplTemplate(J2SEModularProject.class.getResource("resources/build-impl.xsl")). //NOI18N
setBuildTemplate(J2SEModularProject.class.getResource("resources/build.xsl")). //NOI18N
setOverrideModifiedBuildImplPredicate(new Callable<Boolean>(){
@Override
public Boolean call() throws Exception {
return projectPropertiesSave.get();
}
}).
build(),
UILookupMergerSupport.createProjectOpenHookMerger(ProjectHooks.createProjectOpenedHookBuilder(this, eval, updateHelper, genFilesHelper, cpProvider).
addClassPathType(ClassPath.BOOT).
addClassPathType(ClassPath.COMPILE).
addClassPathType(ClassPath.SOURCE).
addClassPathType(JavaClassPathConstants.MODULE_COMPILE_PATH). //For DefaultClassPathProvider
setBuildImplTemplate(J2SEModularProject.class.getResource("resources/build-impl.xsl")). //NOI18N
setBuildTemplate(J2SEModularProject.class.getResource("resources/build.xsl")). //NOI18N
addOpenPostAction(newStartMainUpdaterAction()).
// addOpenPostAction(newWebServicesAction()).
// addOpenPostAction(newMissingPropertiesAction()).
// addOpenPostAction(newUpdateCopyLibsAction()).
addClosePostAction(newStopMainUpdaterAction()).
build()),
QuerySupport.createSourceLevelQuery2(evaluator()),
src = QuerySupport.createSources(this, helper, evaluator(),
getSourceRoots(),
getTestSourceRoots(),
getModuleRoots(),
getTestModuleRoots(),
Roots.nonSourceRoots(ProjectProperties.BUILD_DIR, ProjectProperties.DIST_DIR)),
QuerySupport.createMultiModuleGroupQuery(helper, eval, src,
getSourceRoots(),
getTestSourceRoots(),
getModuleRoots(),
getTestModuleRoots()),
new RecommendedTemplatesImpl(getProjectDirectory()),
UILookupMergerSupport.createPrivilegedTemplatesMerger(),
UILookupMergerSupport.createRecommendedTemplatesMerger(),
LookupProviderSupport.createSourcesMerger(),
encodingQuery,
QuerySupport.createTemplateAttributesProvider(helper, encodingQuery),
QuerySupport.createCompilerOptionsQuery(eval, ProjectProperties.JAVAC_COMPILERARGS),
LookupMergerSupport.createCompilerOptionsQueryMerger(),
ExtraSourceJavadocSupport.createExtraSourceQueryImplementation(this, helper, evaluator()),
LookupMergerSupport.createSFBLookupMerger(),
ExtraSourceJavadocSupport.createExtraJavadocQueryImplementation(this, helper, evaluator()),
LookupMergerSupport.createJFBLookupMerger(),
QuerySupport.createAnnotationProcessingQuery(this.helper, this.evaluator(), ProjectProperties.ANNOTATION_PROCESSING_ENABLED, ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR, ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS, ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST, ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT, ProjectProperties.ANNOTATION_PROCESSING_PROCESSOR_OPTIONS),
LookupProviderSupport.createActionProviderMerger(),
LogicalViewProviders.createBuilder(
this,
eval,
"org-netbeans-modules-java-j2semodule"). //NOI18N
setHelpCtx(new HelpCtx("org.netbeans.modules.java.j2semodule.ui.J2SEModularLogicalViewProvider.J2SEModularLogicalViewRootNode")). //NOI18N
setCompileOnSaveBadge(newCoSBadge()).
build(),
QuerySupport.createModuleInfoAccessibilityQuery(
getModuleRoots(),
getSourceRoots(),
getTestModuleRoots(),
getTestSourceRoots()),
QuerySupport.createMultiModuleAntArtifactProvider(
helper,
evaluator(),
getModuleRoots(),
getSourceRoots()),
QuerySupport.createSharabilityQuery2(
helper,
evaluator(),
getModuleRoots(),
getTestModuleRoots()),
refHelper.createSubprojectProvider(),
new CustomizerProviderImpl(this, this.updateHelper, evaluator(), refHelper, this.genFilesHelper),
newActionProvider(),
ProjectOperations.createBuilder(this, evaluator(), updateHelper, refHelper, getModuleRoots(), getTestModuleRoots()).
addDataFiles("manifest.mf","master-application.jnlp","master-applet.jnlp","master-component.jnlp","preview-application.html","preview-applet.html"). //NOI18N
addMetadataFiles("xml-resources","catalog.xml"). //NOI18N
addPreservedPrivateProperties(ProjectProperties.APPLICATION_ARGS, ProjectProperties.RUN_WORK_DIR, ProjectProperties.COMPILE_ON_SAVE, ProjectProperties.DO_JLINK, ProjectProperties.JLINK_STRIP).
addUpdatedNameProperty(J2SEModularProjectProperties.APPLICATION_TITLE, "{0}", false). //NOI18N
addUpdatedNameProperty(ProjectProperties.DIST_JLINK_OUTPUT, "$'{'"+ProjectProperties.DIST_JLINK_DIR+"'}'/{0}", true). //NOI18N
addUpdatedNameProperty(ProjectProperties.JLINK_LAUNCHER_NAME, "{0}", true). //NOI18N
setCallback(opsCallback).
build(),
new CoSAwareFileBuiltQueryImpl(QuerySupport.createMultiModuleFileBuiltQuery(
helper,
evaluator(),
getModuleRoots(),
getSourceRoots(),
getTestModuleRoots(),
getTestSourceRoots()), this),
QuerySupport.createMultiModuleUnitTestForSourceQuery(
getModuleRoots(),
getSourceRoots(),
getTestModuleRoots(),
getTestSourceRoots()),
ProjectConfigurations.createConfigurationProviderBuilder(this, evaluator(), updateHelper).
addConfigurationsAffectActions(ActionProvider.COMMAND_RUN, ActionProvider.COMMAND_DEBUG).
setCustomizerAction(newConfigCustomizerAction()).
build(),
WhiteListQueryMergerSupport.createWhiteListQueryMerger(),
UILookupMergerSupport.createProjectProblemsProviderMerger(),
new PropertyEvaluatorProviderImpl(evaluator()),
QuerySupport.createMultiModuleUnitTestsCompilerOptionsQuery(
this,
getModuleRoots(),
getSourceRoots(),
getTestModuleRoots(),
getTestSourceRoots()),
BrokenReferencesSupport.createReferenceProblemsProvider(
helper,
refHelper,
evaluator(),
platformChangedHook,
J2SEModularProjectUtil.getBreakableProperties(
getSourceRoots(),
getTestSourceRoots()),
new String[] {
ProjectProperties.PLATFORM_ACTIVE
}),
BrokenReferencesSupport.createPlatformVersionProblemProvider(
helper,
evaluator(),
platformChangedHook,
CommonProjectUtils.J2SE_PLATFORM_TYPE,
J2SEModularProjectUtil.MIN_SOURCE_LEVEL,
ProjectProperties.PLATFORM_ACTIVE,
ProjectProperties.JAVAC_SOURCE,
ProjectProperties.JAVAC_TARGET),
new ProjectPlatformProviderImpl(this),
ProjectClassPathModifier.extenderForModifier(cpMod),
buildExtender,
cpMod,
new J2SEModularPersistenceProvider(this, cpProvider)
//UNKNOWN FOR MODULAR PROJECT
// J2SEFileWizardIterator.create()
);
lookup = base; // in case LookupProvider's call Project.getLookup
return LookupProviderSupport.createCompositeLookup(base, "Projects/org-netbeans-modules-java-j2semodule/Lookup"); //NOI18N
}
private MultiModuleClassPathProvider getClassPathProvider () {
return this.cpProvider;
}
public ClassPathModifier getProjectClassPathModifier () {
return this.cpMod;
}
// Package private methods -------------------------------------------------
/**
* Returns the source roots of this project
* @return project's source roots
*/
public synchronized SourceRoots getSourceRoots() {
if (this.sourceRoots == null) { //Local caching, no project metadata access
this.sourceRoots = SourceRoots.create(updateHelper, evaluator(), getReferenceHelper(),
J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE, "source-roots", false, "src.{0}{1}.dir"); //NOI18N
}
return this.sourceRoots;
}
public synchronized SourceRoots getTestSourceRoots() {
if (this.testRoots == null) { //Local caching, no project metadata access
this.testRoots = SourceRoots.create(updateHelper, evaluator(), getReferenceHelper(),
J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE, "test-roots", true, "test.{0}{1}.dir"); //NOI18N
}
return this.testRoots;
}
public synchronized ModuleRoots getModuleRoots() {
if (this.moduleRoots == null) { //Local caching, no project metadata access
this.moduleRoots = ModuleRoots.create(updateHelper, evaluator(), getReferenceHelper(),
J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE, "source-roots", false, "src.{0}{1}.dir"); //NOI18N
}
return this.moduleRoots;
}
public synchronized ModuleRoots getTestModuleRoots() {
if (this.testModuleRoots == null) { //Local caching, no project metadata access
this.testModuleRoots = ModuleRoots.create(updateHelper, evaluator(), getReferenceHelper(),
J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE, "test-roots", true, "test.{0}{1}.dir"); //NOI18N
}
return this.testModuleRoots;
}
File getTestClassesDirectory() {
String testClassesDir = evaluator().getProperty(ProjectProperties.BUILD_TEST_CLASSES_DIR);
if (testClassesDir == null) {
return null;
}
return helper.resolveFile(testClassesDir);
}
// Currently unused (but see #47230):
/** Store configured project name. */
public void setName(final String name) {
ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
@Override
public Void run() {
Element data = updateHelper.getPrimaryConfigurationData(true);
// XXX replace by XMLUtil when that has findElement, findText, etc.
NodeList nl = data.getElementsByTagNameNS(J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE, "name");
Element nameEl;
if (nl.getLength() == 1) {
nameEl = (Element) nl.item(0);
NodeList deadKids = nameEl.getChildNodes();
while (deadKids.getLength() > 0) {
nameEl.removeChild(deadKids.item(0));
}
} else {
nameEl = data.getOwnerDocument().createElementNS(J2SEModularProject.PROJECT_CONFIGURATION_NAMESPACE, "name");
data.insertBefore(nameEl, /* OK if null */data.getChildNodes().item(0));
}
nameEl.appendChild(data.getOwnerDocument().createTextNode(name));
updateHelper.putPrimaryConfigurationData(data, true);
return null;
}
});
}
/**
* J2SEProjectProperties helper method to notify ProjectXmlSavedHookImpl about customizer save
* @see J2SEProject.ProjectXmlSavedHookImpl#projectXmlSaved()
* @param value true = active
*/
public void setProjectPropertiesSave(boolean value) {
this.projectPropertiesSave.set(value);
}
@NonNull
private ActionProvider newActionProvider() {
return MultiModuleActionProviderBuilder.newInstance(
this, getUpdateHelper(), evaluator(),
getSourceRoots(), getTestSourceRoots(), cpProvider)
.setCompileOnSaveOperationsProvider(() -> {
return J2SEModularProjectUtil.isCompileOnSaveEnabled(this) ?
EnumSet.of(JavaActionProvider.CompileOnSaveOperation.UPDATE, JavaActionProvider.CompileOnSaveOperation.EXECUTE) :
Collections.emptySet();
})
.build();
}
private static final class RecommendedTemplatesImpl implements RecommendedTemplates, PrivilegedTemplates {
// List of primarily supported templates
private static final String[] PROJECT_TEMPLATES = new String[] {
"java-modules", // NOI18N
"simple-files" // NOI18N
};
private static final String[] MODULE_TEMPLATES = new String[] {
"java-classes", // NOI18N
"java-main-class", // NOI18N
"java-forms", // NOI18N
"gui-java-application", // NOI18N
"java-beans", // NOI18N
"persistence", // NOI18N
"oasis-XML-catalogs", // NOI18N
"XML", // NOI18N
"ant-script", // NOI18N
"ant-task", // NOI18N
"web-service-clients", // NOI18N
"REST-clients", // NOI18N
"wsdl", // NOI18N
// "servlet-types", // NOI18N
// "web-types", // NOI18N
"junit", // NOI18N
// "MIDP", // NOI18N
"simple-files" // NOI18N
};
private static final String[] PRIVILEGED_PROJECT_NAMES = new String[] {
"Templates/J2SEModule/module-info.java" // NOI18N
};
private static final String[] PRIVILEGED_MODULE_NAMES = new String[] {
"Templates/Classes/Class.java", // NOI18N
"Templates/Classes/Package", // NOI18N
"Templates/Classes/Interface.java", // NOI18N
"Templates/GUIForms/JPanel.java", // NOI18N
"Templates/GUIForms/JFrame.java", // NOI18N
"Templates/Persistence/Entity.java", // NOI18N
"Templates/Persistence/RelatedCMP", // NOI18N
"Templates/WebServices/WebServiceClient" // NOI18N
};
private final FileObject projectDir;
private RecommendedTemplatesImpl(FileObject projectDir) {
this.projectDir = projectDir;
}
@Override
public String[] getRecommendedTypes() {
return isProject() ? PROJECT_TEMPLATES : MODULE_TEMPLATES;
}
@Override
public String[] getPrivilegedTemplates() {
return isProject() ? PRIVILEGED_PROJECT_NAMES : PRIVILEGED_MODULE_NAMES;
}
private boolean isProject() {
return projectDir == Utilities.actionsGlobalContext().lookup(FileObject.class);
}
}
private class J2SEModularExtenderImplementation implements AntBuildExtenderImplementation {
//add targets here as required by the external plugins..
@Override
public List<String> getExtensibleTargets() {
return Arrays.asList(EXTENSIBLE_TARGETS);
}
@Override
public Project getOwningProject() {
return J2SEModularProject.this;
}
}
private static final DocumentBuilder db;
static {
try {
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new AssertionError(e);
}
}
// private static Document createNewDocument() {
// // #50198: for thread safety, use a separate document.
// // Using XMLUtil.createDocument is much too slow.
// synchronized (db) {
// return db.newDocument();
// }
// }
//
//
@NonNull
private Runnable newStartMainUpdaterAction() {
return () -> {
//register updater of main.class
//the updater is active only on the opened projects
mainClassUpdater = new MainClassUpdater (
J2SEModularProject.this,
evaluator(),
updateHelper,
getSourceRoots(),
ProjectProperties.MAIN_CLASS);
mainClassUpdater.start();
};
}
@NonNull
private Runnable newStopMainUpdaterAction() {
return () -> {
if (mainClassUpdater != null) {
mainClassUpdater.stop();
mainClassUpdater = null;
}
};
}
//
// @NonNull
// private Runnable newWebServicesAction() {
// return new Runnable() {
// private final String JAX_RPC_NAMESPACE="http://www.netbeans.org/ns/j2se-project/jax-rpc"; //NOI18N
// private final String JAX_RPC_CLIENTS="web-service-clients"; //NOI18N
// private final String JAX_RPC_CLIENT="web-service-client"; //NOI18N
// @Override
// public void run() {
// //remove jaxws.endorsed.dir property
// EditableProperties ep = updateHelper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
// ep.remove("jaxws.endorsed.dir");
// // move web-service-clients one level up from in project.xml
// // WS should be part of auxiliary configuration
// Element data = helper.getPrimaryConfigurationData(true);
// NodeList nodes = data.getElementsByTagName(JAX_RPC_CLIENTS);
// if(nodes.getLength() > 0) {
// Element oldJaxRpcClients = (Element) nodes.item(0);
// Document doc = createNewDocument();
// Element newJaxRpcClients = doc.createElementNS(JAX_RPC_NAMESPACE, JAX_RPC_CLIENTS);
// NodeList childNodes = oldJaxRpcClients.getElementsByTagName(JAX_RPC_CLIENT);
// for (int i=0;i<childNodes.getLength();i++) {
// Element oldJaxRpcClient = (Element) childNodes.item(i);
// Element newJaxRpcClient = doc.createElementNS(JAX_RPC_NAMESPACE, JAX_RPC_CLIENT);
// NodeList nodeProps = oldJaxRpcClient.getChildNodes();
// for (int j=0;j<nodeProps.getLength();j++) {
// Node n = nodeProps.item(j);
// if (n instanceof Element) {
// Element oldProp = (Element) n;
// Element newProp = doc.createElementNS(JAX_RPC_NAMESPACE, oldProp.getLocalName());
// String text = oldProp.getTextContent();
// newProp.setTextContent(text);
// newJaxRpcClient.appendChild(newProp);
// }
// }
// newJaxRpcClients.appendChild(newJaxRpcClient);
// }
// aux.putConfigurationFragment(newJaxRpcClients, true);
// data.removeChild(oldJaxRpcClients);
// helper.putPrimaryConfigurationData(data, true);
// }
// updateHelper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
// }
// };
// }
//
// @NonNull
// private Runnable newMissingPropertiesAction() {
// return new Runnable() {
// @Override
// public void run() {
// final EditableProperties ep = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
// if (!ep.containsKey(ProjectProperties.INCLUDES)) {
// ep.setProperty(ProjectProperties.INCLUDES, "**"); // NOI18N
// }
// if (!ep.containsKey(ProjectProperties.EXCLUDES)) {
// ep.setProperty(ProjectProperties.EXCLUDES, ""); // NOI18N
// }
// if (!ep.containsKey("build.generated.sources.dir")) { // NOI18N
// ep.setProperty("build.generated.sources.dir", "${build.dir}/generated-sources"); // NOI18N
// }
// J2SEProjectBuilder.createDefaultModuleProperties(
// ep,
// testRoots.getRoots().length > 0);
// helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
// }
// };
// }
//
// @NonNull
// private Runnable newUpdateCopyLibsAction() {
// return new Runnable() {
// private final String LIB_COPY_LIBS = "CopyLibs"; //NOI18N
// private final String PROP_VERSION = "version"; //NOI18N
// private final String VOL_CP = "classpath"; //NOI18N
//
// @Override
// public void run() {
// final LibraryManager projLibManager = refHelper.getProjectLibraryManager();
// if (projLibManager == null) {
// return;
// }
// final Library globalCopyLibs = LibraryManager.getDefault().getLibrary(LIB_COPY_LIBS);
// final Library projectCopyLibs = projLibManager.getLibrary(LIB_COPY_LIBS);
// if (globalCopyLibs == null || projectCopyLibs == null) {
// return;
// }
// final String globalStr = globalCopyLibs.getProperties().get(PROP_VERSION);
// if (globalStr == null) {
// return;
// }
// try {
// final SpecificationVersion globalVersion = new SpecificationVersion(globalStr);
// final String projectStr = projectCopyLibs.getProperties().get(PROP_VERSION);
// if (projectStr != null && globalVersion.compareTo(new SpecificationVersion(projectStr)) <= 0) {
// return;
// }
//
// final List<URL> content = projectCopyLibs.getContent(VOL_CP);
// projLibManager.removeLibrary(projectCopyLibs);
// final FileObject projLibLoc = URLMapper.findFileObject(projLibManager.getLocation());
// if (projLibLoc != null) {
// final FileObject libFolder = projLibLoc.getParent();
// boolean canDelete = libFolder.canWrite();
// FileObject container = null;
// for (URL u : content) {
// FileObject fo = toFile(u);
// if (fo != null) {
// canDelete &= fo.canWrite();
// if (container == null) {
// container = fo.getParent();
// canDelete &= container.canWrite();
// canDelete &= LIB_COPY_LIBS.equals(container.getName());
// canDelete &= libFolder.equals(container.getParent());
// } else {
// canDelete &= container.equals(fo.getParent());
// }
// }
// }
// if (canDelete && container != null) {
// container.delete();
// }
// }
// refHelper.copyLibrary(globalCopyLibs);
//
// } catch (IllegalArgumentException iae) {
// LOG.log(
// Level.WARNING,
// "Cannot update {0} due to invalid version.", //NOI18N
// projectCopyLibs.getDisplayName());
// } catch (IOException ioe) {
// Exceptions.printStackTrace(ioe);
// }
// }
//
// @CheckForNull
// private FileObject toFile(@NonNull final URL url) {
// final URL file = FileUtil.getArchiveFile(url);
// return URLMapper.findFileObject(file != null ? file : url);
// }
// };
// }
//
@NonNull
private Runnable newConfigCustomizerAction() {
return () -> {
J2SEModularProject.this.getLookup().lookup(CustomizerProviderImpl.class).
showCustomizer(J2SECompositePanelProvider.RUN);
};
}
@NonNull
private LogicalViewProviders.CompileOnSaveBadge newCoSBadge() {
return new LogicalViewProviders.CompileOnSaveBadge() {
@Override
public boolean isBadgeVisible() {
return !J2SEModularProjectUtil.isCompileOnSaveEnabled(J2SEModularProject.this) &&
J2SEModularProjectUtil.isCompileOnSaveSupported(J2SEModularProject.this);
}
@Override
public boolean isImportant(@NonNull final String propertyName) {
return ProjectProperties.COMPILE_ON_SAVE.equals(propertyName) ||
propertyName.startsWith(ProjectProperties.COMPILE_ON_SAVE_UNSUPPORTED_PREFIX);
}
};
}
@NonNull
private static ProjectOperations.Callback newProjectOperationsCallback (
@NonNull final J2SEModularProject project,
@NonNull final UpdateProjectImpl projectUpdate) {
return new ProjectOperations.Callback() {
@Override
public void beforeOperation(@NonNull final ProjectOperations.Callback.Operation operation) {
}
@Override
@SuppressWarnings("fallthrough")
public void afterOperation(
@NonNull final ProjectOperations.Callback.Operation operation,
@NullAllowed final String newName,
@NullAllowed final Pair<File, Project> oldProject) {
switch (operation) {
case COPY:
projectUpdate.setTransparentUpdate(true);
case MOVE:
case RENAME:
project.setName(newName);
}
}
};
}
private static final class PropertyEvaluatorProviderImpl implements PropertyEvaluatorProvider {
private final PropertyEvaluator eval;
PropertyEvaluatorProviderImpl(@NonNull final PropertyEvaluator eval) {
Parameters.notNull("eval", eval); //NOI18N
this.eval = eval;
}
@NonNull
@Override
public PropertyEvaluator getPropertyEvaluator() {
return this.eval;
}
}
private final class PlatformChangedHook implements BrokenReferencesSupport.PlatformUpdatedCallBack {
@Override
public void platformPropertyUpdated(@NonNull final JavaPlatform platform) {
ProjectPlatformProviderImpl.updateProjectXml(platform, updateHelper);
}
}
}