blob: 93fc8f25486beb599e965876fb0e92c20b44371e [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.web.project;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.swing.Icon;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
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.project.SourceGroup;
import org.netbeans.api.project.ant.AntBuildExtender;
import org.netbeans.api.queries.FileBuiltQuery.Status;
import org.netbeans.api.j2ee.core.Profile;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.modules.j2ee.dd.api.ejb.EjbJarMetadata;
import org.netbeans.modules.j2ee.metadata.model.api.MetadataModelAction;
import org.netbeans.modules.java.api.common.Roots;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.ArtifactListener.Artifact;
import org.netbeans.modules.web.common.spi.ProjectWebRootProvider;
import org.netbeans.modules.web.project.api.WebPropertyEvaluator;
import org.netbeans.modules.web.project.jaxws.WebProjectJAXWSClientSupport;
import org.netbeans.modules.web.project.jaxws.WebProjectJAXWSSupport;
import org.netbeans.modules.websvc.api.jaxws.client.JAXWSClientSupport;
import org.netbeans.modules.websvc.jaxws.api.JAXWSSupport;
import org.netbeans.modules.websvc.jaxws.spi.JAXWSSupportFactory;
import org.netbeans.modules.websvc.spi.client.WebServicesClientSupportFactory;
import org.netbeans.modules.websvc.spi.jaxws.client.JAXWSClientSupportFactory;
import org.netbeans.spi.queries.FileBuiltQueryImplementation;
import org.openide.util.ChangeSupport;
import org.openide.util.ImageUtilities;
import org.openide.util.RequestProcessor.Task;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.openide.filesystems.FileChangeAdapter;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileRenameEvent;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.FileAttributeEvent;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
import org.openide.util.lookup.Lookups;
import org.netbeans.modules.web.api.webmodule.WebModule;
import org.netbeans.modules.web.spi.webmodule.WebModuleFactory;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ant.AntArtifact;
import org.netbeans.modules.web.project.classpath.ClassPathProviderImpl;
import org.netbeans.modules.web.project.ui.WebLogicalViewProvider;
import org.netbeans.modules.web.project.ui.customizer.WebProjectProperties;
import org.netbeans.spi.project.AuxiliaryConfiguration;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.api.project.ui.ProjectProblems;
import org.netbeans.modules.j2ee.api.ejbjar.EjbJar;
import org.netbeans.modules.j2ee.common.ClasspathUtil;
import org.netbeans.modules.j2ee.common.J2eeProjectCapabilities;
import org.netbeans.modules.j2ee.common.SharabilityUtility;
import org.netbeans.modules.j2ee.common.dd.DDHelper;
import org.netbeans.modules.javaee.project.api.ant.ArtifactCopyOnSaveSupport;
import org.netbeans.modules.javaee.project.api.ClientSideDevelopmentSupport;
import org.netbeans.modules.j2ee.persistence.spi.entitymanagergenerator.EntityManagerGenerationStrategyResolverFactory;
import org.netbeans.modules.javaee.project.api.PersistenceProviderSupplierImpl;
import org.netbeans.modules.javaee.project.api.ant.AntProjectConstants;
import org.netbeans.modules.j2ee.common.ProjectUtil;
import org.netbeans.modules.j2ee.common.ServerUtil;
import org.netbeans.modules.javaee.project.api.WhiteListUpdater;
import org.netbeans.modules.java.api.common.classpath.ClassPathModifier;
import org.netbeans.modules.java.api.common.classpath.ClassPathModifierSupport;
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eePlatform;
import org.netbeans.modules.java.api.common.SourceRoots;
import org.netbeans.modules.java.api.common.ant.UpdateHelper;
import org.netbeans.modules.java.api.common.queries.QuerySupport;
import org.netbeans.spi.project.ant.AntArtifactProvider;
import org.netbeans.spi.project.ant.AntBuildExtenderFactory;
import org.netbeans.spi.project.ant.AntBuildExtenderImplementation;
import org.netbeans.spi.project.support.LookupProviderSupport;
import org.netbeans.spi.project.support.ant.AntProjectEvent;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.AntProjectListener;
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
import org.netbeans.spi.project.support.ant.ProjectXmlSavedHook;
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.project.support.ant.ReferenceHelper;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
import org.netbeans.spi.project.ui.ProjectOpenedHook;
import org.netbeans.modules.java.api.common.classpath.ClassPathSupport;
import org.netbeans.modules.java.api.common.project.ui.ClassPathUiSupport;
import org.netbeans.modules.javaee.project.api.ant.DeployOnSaveUtils;
import org.netbeans.modules.javaee.project.api.ant.ui.J2EEProjectProperties;
import org.netbeans.modules.j2ee.common.ui.BrokenServerLibrarySupport;
import org.netbeans.modules.j2ee.common.ui.BrokenServerSupport;
import org.netbeans.modules.javaee.project.spi.JavaEEProjectSettingsImplementation;
import org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata;
import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment;
import org.netbeans.modules.j2ee.deployment.devmodules.api.InstanceRemovedException;
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule.Type;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.ArtifactListener;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider.ConfigSupport.DeployOnSaveListener;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider.DeployOnSaveSupport;
import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
import org.netbeans.modules.j2ee.spi.ejbjar.EjbJarFactory;
import org.netbeans.modules.j2ee.spi.ejbjar.support.EjbJarSupport;
import org.netbeans.modules.java.api.common.project.ProjectProperties;
import org.netbeans.modules.javaee.project.api.JavaEEProjectSettingConstants;
import org.netbeans.modules.javaee.project.api.ant.AntProjectUtil;
import org.netbeans.modules.javaee.project.api.problems.PlatformUpdatedCallBackImpl;
import org.netbeans.modules.web.api.webmodule.WebProjectConstants;
import org.netbeans.modules.web.browser.spi.ProjectBrowserProvider;
import org.netbeans.modules.web.common.api.CssPreprocessors;
import org.netbeans.modules.web.common.ui.api.CssPreprocessorsUI;
import org.netbeans.modules.web.project.api.WebProjectUtilities;
import org.netbeans.modules.web.project.classpath.ClassPathSupportCallbackImpl;
import org.netbeans.modules.web.project.classpath.DelagatingProjectClassPathModifierImpl;
import org.netbeans.modules.web.project.classpath.WebProjectLibrariesModifierImpl;
import org.netbeans.modules.web.project.spi.BrokenLibraryRefFilter;
import org.netbeans.modules.web.project.spi.BrokenLibraryRefFilterProvider;
import org.netbeans.modules.web.project.ui.customizer.CustomizerProviderImpl;
import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation;
import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2;
import org.netbeans.modules.web.spi.webmodule.WebPrivilegedTemplates;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.netbeans.modules.websvc.api.webservices.WebServicesSupport;
import org.netbeans.modules.websvc.api.client.WebServicesClientSupport;
import org.netbeans.modules.websvc.spi.webservices.WebServicesSupportFactory;
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.whitelist.support.WhiteListQueryMergerSupport;
import org.netbeans.spi.project.support.ant.PropertyProvider;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.netbeans.spi.queries.FileEncodingQueryImplementation;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileSystem.AtomicAction;
import org.openide.loaders.DataObject;
import org.openide.modules.Places;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.WindowManager;
import org.openide.windows.WindowSystemEvent;
import org.openide.windows.WindowSystemListener;
/**
* Represents one plain Web project.
* @author Jesse Glick, et al., Pavel Buzek
* @author kaktus
*/
public final class WebProject implements Project {
private static final Logger LOGGER = Logger.getLogger(WebProject.class.getName());
private static final Icon WEB_PROJECT_ICON = ImageUtilities.loadImageIcon("org/netbeans/modules/web/project/ui/resources/webProjectIcon.gif", false); // NOI18
private static final Pattern TLD_PATTERN = Pattern.compile("(META-INF/.*\\.tld)|(META-INF/tlds/.*\\.tld)");
private final AntProjectHelper helper;
private final PropertyEvaluator eval;
private final ReferenceHelper refHelper;
private final GeneratedFilesHelper genFilesHelper;
private Lookup lookup;
private final ProjectWebModule webModule;
private final CopyOnSaveSupport copyOnSaveSupport;
private final ClientSideDevelopmentSupport easelSupport;
private final ArtifactCopyOnSaveSupport artifactSupport;
private final DeployOnSaveSupport deployOnSaveSupport;
private final EjbJarProvider webEjbJarProvider;
private final EjbJar apiEjbJar;
private WebModule apiWebModule;
private WebServicesSupport apiWebServicesSupport;
private JAXWSSupport apiJaxwsSupport;
private WebServicesClientSupport apiWebServicesClientSupport;
private JAXWSClientSupport apiJAXWSClientSupport;
private WebContainerImpl enterpriseResourceSupport;
private FileWatch webPagesFileWatch;
private FileWatch webInfFileWatch;
private PropertyChangeListener j2eePlatformListener;
private PropertyChangeListener enterpriseBeansListener;
private SourceRoots sourceRoots;
private SourceRoots testRoots;
private final UpdateHelper updateHelper;
private final UpdateProjectImpl updateProject;
private final AuxiliaryConfiguration aux;
private final DelagatingProjectClassPathModifierImpl cpMod;
private final WebProjectLibrariesModifierImpl libMod;
private final ClassPathProviderImpl cpProvider;
private ClassPathUiSupport.Callback classPathUiSupportCallback;
private WhiteListUpdater whiteListUpdater;
private CssPreprocessorsSupport cssSupport;
private AntBuildExtender buildExtender;
// set to true when project customizer is being closed and changes persisted
private final ThreadLocal<Boolean> projectPropertiesSave;
// #233052
private final WindowSystemListener windowSystemListener = new WindowSystemListener() {
@Override
public void beforeLoad(WindowSystemEvent event) {
}
@Override
public void afterLoad(WindowSystemEvent event) {
}
@Override
public void beforeSave(WindowSystemEvent event) {
easelSupport.close();
}
@Override
public void afterSave(WindowSystemEvent event) {
}
};
private class FileWatch implements AntProjectListener, FileChangeListener {
private String propertyName;
private FileObject fileObject = null;
private boolean watchRename = false;
public FileWatch(String property) {
this.propertyName = property;
}
public void init() {
helper.addAntProjectListener(this);
updateFileChangeListener();
}
public void reset() {
helper.removeAntProjectListener(this);
setFileObject(null);
}
public void updateFileChangeListener() {
File resolvedFile;
FileObject fo = null;
String propertyValue = helper.getStandardPropertyEvaluator().getProperty(propertyName);
if (propertyValue != null) {
String resolvedPath = helper.resolvePath(propertyValue);
resolvedFile = new File(resolvedPath).getAbsoluteFile();
File f = resolvedFile;
while (f != null && (fo = FileUtil.toFileObject(f)) == null) {
f = f.getParentFile();
}
watchRename = f == resolvedFile;
} else {
resolvedFile = null;
watchRename = false;
}
setFileObject(fo);
}
private void setFileObject(FileObject fo) {
if (!isEqual(fo, fileObject)) {
if (fileObject != null) {
fileObject.removeFileChangeListener(this);
}
fileObject = fo;
if (fileObject != null) {
fileObject.addFileChangeListener(this);
}
}
}
private boolean isEqual(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if(object1 == null) {
return false;
}
return object1.equals(object2);
}
// AntProjectListener
@Override
public void configurationXmlChanged(AntProjectEvent ev) {
updateFileChangeListener();
}
@Override
public void propertiesChanged(AntProjectEvent ev) {
updateFileChangeListener();
}
// FileChangeListener
@Override
public void fileFolderCreated(FileEvent fe) {
updateFileChangeListener();
}
@Override
public void fileDataCreated(FileEvent fe) {
updateFileChangeListener();
}
@Override
public void fileChanged(FileEvent fe) {
updateFileChangeListener();
}
@Override
public void fileDeleted(FileEvent fe) {
updateFileChangeListener();
}
@Override
public void fileRenamed(final FileRenameEvent fe) {
if(watchRename && fileObject.isValid()) {
String prop = helper.getStandardPropertyEvaluator().getProperty(propertyName);
if (prop == null) {
return;
}
final File f = new File(prop);
if(f.getName().equals(fe.getName())) {
ProjectManager.mutex().postWriteRequest(new Runnable() {
public void run() {
EditableProperties properties = new EditableProperties(true);
properties.setProperty(propertyName, new File(f.getParentFile(), fe.getFile().getName()).getPath());
Utils.updateProperties(helper, AntProjectHelper.PROJECT_PROPERTIES_PATH, properties);
try {
ProjectManager.getDefault().saveProject(WebProject.this);
updateFileChangeListener();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (IllegalArgumentException ex) {
Exceptions.printStackTrace(ex);
}
}
});
}
}
updateFileChangeListener();
}
@Override
public void fileAttributeChanged(FileAttributeEvent fe) {
}
};
WebProject(final AntProjectHelper helper) throws IOException {
this.projectPropertiesSave = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return Boolean.FALSE;
}
};
this.helper = helper;
aux = helper.createAuxiliaryConfiguration();
updateProject = new UpdateProjectImpl(this, this.helper, aux);
this.updateHelper = new UpdateHelper(updateProject, helper);
updateProject.setUpdateHelper(updateHelper);
eval = createEvaluator();
refHelper = new ReferenceHelper(helper, aux, eval);
buildExtender = AntBuildExtenderFactory.createAntExtender(new WebExtenderImplementation(), refHelper);
genFilesHelper = new GeneratedFilesHelper(helper, buildExtender);
this.cpProvider = new ClassPathProviderImpl(this.helper, evaluator(), getSourceRoots(),getTestSourceRoots());
webModule = new ProjectWebModule (this, updateHelper, cpProvider);
apiWebModule = WebModuleFactory.createWebModule(new WebModuleImpl2(webModule));
webEjbJarProvider = new EjbJarProvider(webModule, cpProvider);
apiEjbJar = EjbJarFactory.createEjbJar(webEjbJarProvider);
WebProjectWebServicesSupport webProjectWebServicesSupport = new WebProjectWebServicesSupport(this, helper, refHelper);
WebProjectJAXWSSupport jaxwsSupport = new WebProjectJAXWSSupport(this, helper);
WebProjectJAXWSClientSupport jaxWsClientSupport = new WebProjectJAXWSClientSupport(this, helper);
WebProjectWebServicesClientSupport webProjectWebServicesClientSupport = new WebProjectWebServicesClientSupport(this, helper, refHelper);
apiWebServicesSupport = WebServicesSupportFactory.createWebServicesSupport (webProjectWebServicesSupport);
apiJaxwsSupport = JAXWSSupportFactory.createJAXWSSupport(jaxwsSupport);
apiWebServicesClientSupport = WebServicesClientSupportFactory.createWebServicesClientSupport (webProjectWebServicesClientSupport);
apiJAXWSClientSupport = JAXWSClientSupportFactory.createJAXWSClientSupport(jaxWsClientSupport);
enterpriseResourceSupport = new WebContainerImpl(this, refHelper, helper);
ClassPathModifier cpModTemp = new ClassPathModifier(this, this.updateHelper, eval, refHelper,
new ClassPathSupportCallbackImpl(helper), createClassPathModifierCallback(), getClassPathUiSupportCallback());
libMod = new WebProjectLibrariesModifierImpl(this, this.updateHelper, eval, refHelper);
cpMod = new DelagatingProjectClassPathModifierImpl(cpModTemp, libMod);
easelSupport = ClientSideDevelopmentSupport.createInstance(this, WebProjectType.TYPE, Utils.USG_LOGGER_NAME);
cssSupport = new CssPreprocessorsSupport(this);
lookup = createLookup(aux, cpProvider);
copyOnSaveSupport = new CopyOnSaveSupport();
artifactSupport = new ArtifactCopySupport();
deployOnSaveSupport = new DeployOnSaveSupportProxy();
webPagesFileWatch = new FileWatch(WebProjectProperties.WEB_DOCBASE_DIR);
webInfFileWatch = new FileWatch(WebProjectProperties.WEBINF_DIR);
// whitelist updater listens on project properties and pays attention to whitelist changes
whiteListUpdater = new WhiteListUpdaterImpl(this);
WindowManager windowManager = WindowManager.getDefault();
windowManager.addWindowSystemListener(WeakListeners.create(WindowSystemListener.class, windowSystemListener, windowManager));
}
public void setProjectPropertiesSave(boolean value) {
this.projectPropertiesSave.set(value);
}
public DelagatingProjectClassPathModifierImpl getClassPathModifier() {
return cpMod;
}
public WebProjectLibrariesModifierImpl getLibrariesModifier() {
return libMod;
}
public DeployOnSaveSupport getDeployOnSaveSupport() {
return deployOnSaveSupport;
}
private ClassPathModifier.Callback createClassPathModifierCallback() {
return new ClassPathModifier.Callback() {
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
}
assert !classPathProperty[0].equals(WebProjectProperties.J2EE_PLATFORM_CLASSPATH);
return classPathProperty[0];
}
public String getElementName(String classpathProperty) {
if (ProjectProperties.JAVAC_CLASSPATH.equals(classpathProperty)) {
return ClassPathSupportCallbackImpl.TAG_WEB_MODULE_LIBRARIES;
}
return null;
}
};
}
public synchronized ClassPathUiSupport.Callback getClassPathUiSupportCallback() {
if (classPathUiSupportCallback == null) {
classPathUiSupportCallback = new ClassPathUiSupport.Callback() {
public void initItem(ClassPathSupport.Item item) {
switch (item.getType()) {
case ClassPathSupport.Item.TYPE_JAR:
item.setAdditionalProperty(ClassPathSupportCallbackImpl.PATH_IN_DEPLOYMENT,
item.getResolvedFile().isDirectory() ?
ClassPathSupportCallbackImpl.PATH_IN_WAR_DIR :
ClassPathSupportCallbackImpl.PATH_IN_WAR_LIB);
break;
case ClassPathSupport.Item.TYPE_LIBRARY:
if (item.getLibrary().getType().equals(J2eePlatform.LIBRARY_TYPE)) {
break;
}
item.setAdditionalProperty(ClassPathSupportCallbackImpl.PATH_IN_DEPLOYMENT,
Utils.isLibraryDirectoryBased(item) ?
ClassPathSupportCallbackImpl.PATH_IN_WAR_DIR :
ClassPathSupportCallbackImpl.PATH_IN_WAR_LIB);
break;
default:
item.setAdditionalProperty(ClassPathSupportCallbackImpl.PATH_IN_DEPLOYMENT,
ClassPathSupportCallbackImpl.PATH_IN_WAR_LIB);
}
}
};
}
return classPathUiSupportCallback;
}
public UpdateProjectImpl getUpdateImplementation() {
return updateProject;
}
public FileObject getProjectDirectory() {
return helper.getProjectDirectory();
}
public UpdateHelper getUpdateHelper() {
return updateHelper;
}
public String toString() {
return "WebProject[" + getProjectDirectory() + "]"; // NOI18N
}
private PropertyEvaluator createEvaluator() {
// XXX might need to add a custom evaluator to handle active platform substitutions... TBD
helper.getStandardPropertyEvaluator();//workaround for issue for #181253, need to call before custom creation
PropertyEvaluator baseEval2 = PropertyUtils.sequentialPropertyEvaluator(
helper.getStockPropertyPreprovider(),
helper.getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH));
return PropertyUtils.sequentialPropertyEvaluator(
helper.getStockPropertyPreprovider(),
helper.getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH),
helper.getProjectLibrariesPropertyProvider(),
PropertyUtils.userPropertiesProvider(baseEval2,
"user.properties.file", FileUtil.toFile(getProjectDirectory())), // NOI18N
helper.getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH),
UPDATE_PROPERTIES);
}
private static final PropertyProvider UPDATE_PROPERTIES;
static {
Map<String, String> defs = new HashMap<String, String>();
defs.put(ProjectProperties.ANNOTATION_PROCESSING_ENABLED, "true"); //NOI18N
defs.put(ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR, "true"); //NOI18N
defs.put(ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS, "true"); //NOI18N
defs.put(ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST, ""); //NOI18N
defs.put(ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT, "${build.generated.sources.dir}/ap-source-output"); //NOI18N
defs.put(ProjectProperties.JAVAC_PROCESSORPATH,"${" + ProjectProperties.JAVAC_CLASSPATH + "}"); //NOI18N
defs.put("javac.test.processorpath", "${" + ProjectProperties.JAVAC_TEST_CLASSPATH + "}"); // NOI18N
UPDATE_PROPERTIES = PropertyUtils.fixedPropertyProvider(defs);
}
public PropertyEvaluator evaluator() {
return eval;
}
public ReferenceHelper getReferenceHelper () {
return this.refHelper;
}
public Lookup getLookup() {
return lookup;
}
public AntProjectHelper getAntProjectHelper() {
return helper;
}
private Lookup createLookup(AuxiliaryConfiguration aux, ClassPathProviderImpl cpProvider) {
FileEncodingQueryImplementation encodingQuery = QuerySupport.createFileEncodingQuery(evaluator(), WebProjectProperties.SOURCE_ENCODING);
final WebLogicalViewProvider lvp = new WebLogicalViewProvider(this, this.updateHelper, evaluator (), refHelper, webModule);
Lookup base = Lookups.fixed(new Object[] {
QuerySupport.createProjectInformation(updateHelper, this, WEB_PROJECT_ICON),
aux,
helper.createCacheDirectoryProvider(),
helper.createAuxiliaryProperties(),
refHelper.createSubprojectProvider(),
new ProjectWebModuleProvider (),
new ProjectWebServicesSupportProvider(),
webModule, //implements J2eeModuleProvider
// FIXME this is just fallback for code searching for the old SPI in lookup
// remove in next release
new WebModuleImpl(apiWebModule),
enterpriseResourceSupport,
lvp,
new CustomizerProviderImpl(this, this.updateHelper, evaluator(), refHelper),
LookupMergerSupport.createClassPathProviderMerger(cpProvider),
QuerySupport.createCompiledSourceForBinaryQuery(helper, evaluator(), getSourceRoots(), getTestSourceRoots(),
new String[]{"build.classes.dir", "dist.war"}, new String[]{"build.test.classes.dir"}),
QuerySupport.createJavadocForBinaryQuery(helper, evaluator(), new String[]{"build.classes.dir", "dist.war"}),
QuerySupport.createAnnotationProcessingQuery(helper, eval, 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),
new AntArtifactProviderImpl(),
new ProjectXmlSavedHookImpl(),
UILookupMergerSupport.createProjectOpenHookMerger(new ProjectOpenedHookImpl()),
QuerySupport.createUnitTestForSourceQuery(getSourceRoots(), getTestSourceRoots()),
QuerySupport.createSourceLevelQuery2(evaluator()),
QuerySupport.createSources(this, helper, evaluator(),
getSourceRoots(),
getTestSourceRoots(),
Roots.propertyBased(new String[] {WebProjectProperties.SOURCE_ROOT}, new String[] {NbBundle.getMessage(WebProject.class, "LBL_Node_WebModule")}, false, null, null),
Roots.propertyBased(new String[] {WebProjectProperties.WEB_DOCBASE_DIR}, new String[] {NbBundle.getMessage(WebProject.class, "LBL_Node_DocBase")}, true, WebProjectConstants.TYPE_DOC_ROOT, null),
Roots.propertyBased(new String[] {WebProjectProperties.WEBINF_DIR}, new String[] {NbBundle.getMessage(WebProject.class, "LBL_Node_WebInf")}, false, WebProjectConstants.TYPE_WEB_INF, null),
Roots.nonSourceRoots(ProjectProperties.BUILD_DIR, WebProjectProperties.DIST_DIR)),
QuerySupport.createSharabilityQuery2(helper, evaluator(), getSourceRoots(),
getTestSourceRoots(), WebProjectProperties.WEB_DOCBASE_DIR),
LookupProviderSupport.createSharabilityQueryMerger(),
new RecommendedTemplatesImpl(this),
new CoSAwareFileBuiltQueryImpl(QuerySupport.createFileBuiltQuery(helper, evaluator(), getSourceRoots(), getTestSourceRoots()), this),
ProjectClassPathModifier.extenderForModifier(cpMod),
buildExtender,
cpMod,
cpMod.getClassPathModifier(),
new WebProjectOperations(this),
new WebPersistenceProvider(this, evaluator(), cpProvider),
new PersistenceProviderSupplierImpl(this),
EntityManagerGenerationStrategyResolverFactory.createInstance(this),
new WebJPADataSourceSupport(this),
ServerUtil.createServerStatusProvider(getWebModule()),
new WebJPAModuleInfo(this),
new WebJPATargetInfo(this),
UILookupMergerSupport.createPrivilegedTemplatesMerger(),
UILookupMergerSupport.createRecommendedTemplatesMerger(),
LookupProviderSupport.createSourcesMerger(),
LookupProviderSupport.createActionProviderMerger(),
WhiteListQueryMergerSupport.createWhiteListQueryMerger(),
new WebPropertyEvaluatorImpl(evaluator()),
WebProject.this, // never cast an externally obtained Project to WebProject - use lookup instead
libMod,
encodingQuery,
new CreateFromTemplateAttributesImpl(helper, encodingQuery),
ExtraSourceJavadocSupport.createExtraSourceQueryImplementation(this, helper, eval),
LookupMergerSupport.createSFBLookupMerger(),
ExtraSourceJavadocSupport.createExtraJavadocQueryImplementation(this, helper, eval),
LookupMergerSupport.createJFBLookupMerger(),
QuerySupport.createBinaryForSourceQueryImplementation(getSourceRoots(), getTestSourceRoots(), helper, eval),
new ProjectWebRootProviderImpl(this),
easelSupport,
new JavaEEProjectSettingsImpl(this),
BrokenReferencesSupport.createReferenceProblemsProvider(helper, refHelper, eval, lvp.getBreakableProperties(), lvp.getPlatformProperties()),
BrokenReferencesSupport.createPlatformVersionProblemProvider(helper, eval, PlatformUpdatedCallBackImpl.create(WebProjectType.PROJECT_CONFIGURATION_NAMESPACE, updateHelper), JavaPlatform.getDefault().getSpecification().getName(), ProjectProperties.PLATFORM_ACTIVE, ProjectProperties.JAVAC_SOURCE, ProjectProperties.JAVAC_TARGET),
CssPreprocessorsUI.getDefault().createProjectProblemsProvider(this),
UILookupMergerSupport.createProjectProblemsProviderMerger(),
});
Lookup ee6 = Lookups.fixed(new Object[]{
EjbJarSupport.createEjbJarProvider(this, apiEjbJar),
EjbJarSupport.createEjbJarsInProject(apiEjbJar)
});
WebProjectLookup wpl = new WebProjectLookup(this, base, ee6, new WebProjectBrowserProvider(this));
eval.addPropertyChangeListener(wpl);
lookup = wpl;
return LookupProviderSupport.createCompositeLookup(lookup, "Projects/org-netbeans-modules-web-project/Lookup"); //NOI18N
}
public ClassPathProviderImpl getClassPathProvider () {
return this.cpProvider;
}
String getBuildXmlName () {
String storedName = helper.getStandardPropertyEvaluator ().getProperty (WebProjectProperties.BUILD_FILE);
return storedName == null ? GeneratedFilesHelper.BUILD_XML_PATH : storedName;
}
// 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(), WebProjectType.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(this.updateHelper, evaluator(), getReferenceHelper(), WebProjectType.PROJECT_CONFIGURATION_NAMESPACE, "test-roots", true, "test.{0}{1}.dir"); //NOI18N
}
return this.testRoots;
}
File getTestClassesDirectory() {
String testClassesDir = evaluator().getProperty(ProjectProperties.BUILD_TEST_CLASSES_DIR);
if (testClassesDir == null) {
return null;
}
return helper.resolveFile(testClassesDir);
}
public ProjectWebModule getWebModule () {
return webModule;
}
public WebModule getAPIWebModule () {
return apiWebModule;
}
public EjbJar getAPIEjbJar() {
return apiEjbJar;
}
WebServicesSupport getAPIWebServicesSupport () {
return apiWebServicesSupport;
}
JAXWSSupport getAPIJAXWSSupport () {
return apiJaxwsSupport;
}
WebServicesClientSupport getAPIWebServicesClientSupport () {
return apiWebServicesClientSupport;
}
JAXWSClientSupport getAPIJAXWSClientSupport () {
return apiJAXWSClientSupport;
}
/** Return configured project name. */
public String getName() {
return ProjectUtils.getInformation(this).getName();
}
/** Store configured project name. */
public void setName(final String name) {
ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
public Void run() {
Element data = helper.getPrimaryConfigurationData(true);
// XXX replace by XMLUtil when that has findElement, findText, etc.
NodeList nl = data.getElementsByTagNameNS(WebProjectType.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(WebProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name");
data.insertBefore(nameEl, /* OK if null */data.getChildNodes().item(0));
}
nameEl.appendChild(data.getOwnerDocument().createTextNode(name));
helper.putPrimaryConfigurationData(data, true);
return null;
}
});
}
public void registerJ2eePlatformListener(final J2eePlatform platform) {
// listen to classpath changes
j2eePlatformListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(J2eePlatform.PROP_CLASSPATH)) {
updateClasspath(platform);
}
}
};
platform.addPropertyChangeListener(j2eePlatformListener);
}
public void unregisterJ2eePlatformListener(J2eePlatform platform) {
if (j2eePlatformListener != null) {
platform.removePropertyChangeListener(j2eePlatformListener);
}
}
private void updateClasspath(final J2eePlatform platform) {
ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
public Void run() {
EditableProperties ep = helper.getProperties(
AntProjectHelper.PRIVATE_PROPERTIES_PATH);
EditableProperties projectProps = helper.getProperties(
AntProjectHelper.PROJECT_PROPERTIES_PATH);
Map<String, String> roots = J2EEProjectProperties.extractPlatformLibrariesRoot(platform);
String classpath = J2EEProjectProperties.toClasspathString(
ClasspathUtil.getJ2eePlatformClasspathEntries(WebProject.this, null), roots);
if (roots != null) {
projectProps.setProperty(WebProjectProperties.J2EE_PLATFORM_CLASSPATH, classpath);
} else {
ep.setProperty(WebProjectProperties.J2EE_PLATFORM_CLASSPATH, classpath);
}
helper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, projectProps);
try {
ProjectManager.getDefault().saveProject(WebProject.this);
} catch (IOException e) {
Exceptions.printStackTrace(e);
}
return null;
}
});
}
// Private innerclasses ----------------------------------------------------
public static void makeSureProjectHasJspCompilationLibraries(final ReferenceHelper refHelper) {
if (refHelper.getProjectLibraryManager() == null) {
return;
}
ProjectManager.mutex().writeAccess(new Runnable() {
public void run() {
Library lib = refHelper.getProjectLibraryManager().getLibrary("jsp-compilation");
// #198056 - force libraries update by deleting old versions first:
if (lib != null) {
boolean oldNB69ver = lib.getURIContent("classpath").toString().contains("glassfish-jspparser-2.0.jar");
if (oldNB69ver) {
try {
refHelper.getProjectLibraryManager().removeLibrary(lib);
lib = refHelper.getProjectLibraryManager().getLibrary("jsp-compiler");
refHelper.getProjectLibraryManager().removeLibrary(lib);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (IllegalArgumentException ex) {
Exceptions.printStackTrace(ex);
}
}
}
lib = refHelper.getProjectLibraryManager().getLibrary("jsp-compiler");
if (lib == null) {
try {
refHelper.copyLibrary(LibraryManager.getDefault().getLibrary("jsp-compiler")); // NOI18N
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
lib = refHelper.getProjectLibraryManager().getLibrary("jsp-compilation");
if (lib == null) {
try {
refHelper.copyLibrary(LibraryManager.getDefault().getLibrary("jsp-compilation")); // NOI18N
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
lib = refHelper.getProjectLibraryManager().getLibrary("jsp-compilation-syscp");
if (lib == null) {
try {
refHelper.copyLibrary(LibraryManager.getDefault().getLibrary("jsp-compilation-syscp")); // NOI18N
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}
});
}
private final class ProjectXmlSavedHookImpl extends ProjectXmlSavedHook {
ProjectXmlSavedHookImpl() {}
protected void projectXmlSaved() throws IOException {
int state = genFilesHelper.getBuildScriptState(
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
WebProject.class.getResource("resources/build-impl.xsl"));
final Boolean projectPropertiesSave = WebProject.this.projectPropertiesSave.get();
if ((projectPropertiesSave && (state & GeneratedFilesHelper.FLAG_MODIFIED) == GeneratedFilesHelper.FLAG_MODIFIED) ||
state == (GeneratedFilesHelper.FLAG_UNKNOWN | GeneratedFilesHelper.FLAG_MODIFIED |
GeneratedFilesHelper.FLAG_OLD_PROJECT_XML | GeneratedFilesHelper.FLAG_OLD_STYLESHEET)) { //missing genfiles.properties
try {
AntProjectUtil.backupBuildImplFile(updateHelper);
genFilesHelper.generateBuildScriptFromStylesheet(
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
WebProject.class.getResource("resources/build-impl.xsl"));
} catch (IOException e) {
Exceptions.printStackTrace(e);
} catch (IllegalStateException e) {
Exceptions.printStackTrace(e);
}
} else {
genFilesHelper.refreshBuildScript(GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
org.netbeans.modules.web.project.WebProject.class.getResource("resources/build-impl.xsl"),
false);
}
genFilesHelper.refreshBuildScript(
getBuildXmlName (),
WebProject.class.getResource("resources/build.xsl"),false);
}
}
final class ProjectOpenedHookImpl extends ProjectOpenedHook {
ProjectOpenedHookImpl() {}
@Override
@NbBundle.Messages("ERR_ProjectReadOnly=The project folder is read-only.")
protected void projectOpened() {
evaluator().addPropertyChangeListener(WebProject.this.webModule);
WebLogicalViewProvider logicalViewProvider = (WebLogicalViewProvider) WebProject.this.getLookup().lookup (WebLogicalViewProvider.class);
if (logicalViewProvider != null) {
logicalViewProvider.initialize();
}
try {
getProjectDirectory().getFileSystem().runAtomicAction(new AtomicAction() {
public void run() throws IOException {
ProjectManager.mutex().writeAccess(new Runnable() {
public void run() {
updateProject();
}
});
}
});
} catch (IOException e) {
// #222721 - Provide a better error message in case of read-only location of project.
if (!WebProject.this.getProjectDirectory().canWrite()) {
NotifyDescriptor nd = new NotifyDescriptor.Message(Bundle.ERR_ProjectReadOnly());
DialogDisplayer.getDefault().notify(nd);
} else {
Logger.getLogger("global").log(Level.INFO, null, e);
}
}
try {
if (webModule.getDeploymentDescriptor() == null
&& webModule.getConfigSupport().isDescriptorRequired()) {
DDHelper.createWebXml(webModule.getJ2eeProfile(), webModule.getWebInf());
}
//DDDataObject initialization to be ready to listen on changes (#45771)
// web.xml
try {
FileObject ddFO = webModule.getDeploymentDescriptor();
if (ddFO != null) {
DataObject dobj = DataObject.find(ddFO);
}
} catch (org.openide.loaders.DataObjectNotFoundException ex) {
//PENDING
}
// ejb-jar.xml
try {
FileObject ejbDdFO = webEjbJarProvider.getDeploymentDescriptor();
if (ejbDdFO != null) {
DataObject ejbdobj = DataObject.find(ejbDdFO);
}
} catch (org.openide.loaders.DataObjectNotFoundException ex) {
//PENDING`
}
// Register copy on save support
copyOnSaveSupport.initialize();
// Check up on build scripts.
if (updateHelper.isCurrent()) {
int flags = genFilesHelper.getBuildScriptState(
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
WebProject.class.getResource("resources/build-impl.xsl"));
if ((flags & GeneratedFilesHelper.FLAG_MODIFIED) != 0
&& (flags & GeneratedFilesHelper.FLAG_OLD_PROJECT_XML) != 0) {
AntProjectUtil.backupBuildImplFile(updateHelper);
genFilesHelper.generateBuildScriptFromStylesheet(
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
WebProject.class.getResource("resources/build-impl.xsl"));
} else {
genFilesHelper.refreshBuildScript(
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
WebProject.class.getResource("resources/build-impl.xsl"), true);
}
genFilesHelper.refreshBuildScript(
getBuildXmlName(),
WebProject.class.getResource("resources/build.xsl"), true);
String servInstID = evaluator().getProperty(WebProjectProperties.J2EE_SERVER_INSTANCE);
String serverType = null;
J2eePlatform platform = Deployment.getDefault().getJ2eePlatform(servInstID);
if (platform != null) {
// updates j2ee.platform.cp & wscompile.cp & reg. j2ee platform listener
WebProjectProperties.setServerInstance(WebProject.this, WebProject.this.updateHelper, servInstID);
} else {
// if there is some server instance of the type which was used
// previously do not ask and use it
serverType = evaluator().getProperty(WebProjectProperties.J2EE_SERVER_TYPE);
if (serverType != null) {
String instanceID = J2EEProjectProperties.getMatchingInstance(serverType, Type.WAR, WebProject.this.getWebModule().getJ2eeProfile());
if (instanceID != null) {
WebProjectProperties.setServerInstanceInner(WebProject.this, WebProject.this.updateHelper, instanceID);
platform = Deployment.getDefault().getJ2eePlatform(instanceID);
}
}
if (platform == null) {
BrokenServerSupport.showAlert();
}
}
// UI Logging
Utils.logUI(NbBundle.getBundle(WebProject.class), "UI_WEB_PROJECT_OPENED", // NOI18N
new Object[] {(serverType != null ? serverType : Deployment.getDefault().getServerID(servInstID)), servInstID});
// Usage Logging
String serverName = ""; // NOI18N
try {
if (servInstID != null) {
serverName = Deployment.getDefault().getServerInstance(servInstID).getServerDisplayName();
}
}
catch (InstanceRemovedException ire) {
// do nothing
}
Profile profile = WebProject.this.getWebModule().getJ2eeProfile();
Utils.logUsage(WebProject.class, "USG_PROJECT_OPEN_WEB", new Object[] { serverName, profile }); // NOI18N
}
} catch (IOException e) {
// #222721 - Provide a better error message in case of read-only location of project.
if (!WebProject.this.getProjectDirectory().canWrite()) {
NotifyDescriptor nd = new NotifyDescriptor.Message(Bundle.ERR_ProjectReadOnly());
DialogDisplayer.getDefault().notify(nd);
} else {
LOGGER.log(Level.INFO, null, e);
}
}
webModule.getConfigSupport().addLibraryChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
String servInstID = evaluator().getProperty(WebProjectProperties.J2EE_SERVER_INSTANCE);
J2eePlatform platform = Deployment.getDefault().getJ2eePlatform(servInstID);
if (platform != null) {
updateClasspath(platform);
}
}
});
if (BrokenServerLibrarySupport.isBroken(WebProject.this)) {
BrokenServerLibrarySupport.fixOrShowAlert(WebProject.this, new Runnable() {
@Override
public void run() {
WebLogicalViewProvider viewProvider = WebProject.this.getLookup().lookup(
WebLogicalViewProvider.class);
if (viewProvider != null) {
viewProvider.testBroken();
}
}
});
}
// register project's classpaths to GlobalPathRegistry
GlobalPathRegistry.getDefault().register(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, cpProvider.getProjectClassPaths(ClassPath.COMPILE));
// initialize the server configuration
// it MUST BE called AFTER classpaths are registered to GlobalPathRegistry!
// DDProvider (used here) needs classpath set correctly when resolving Java Extents for annotations
webModule.getConfigSupport().ensureConfigurationReady();
//check the config context path
String ctxRoot = webModule.getContextPath ();
if (ctxRoot == null) {
String sysName = getProjectDirectory ().getName (); //NOI18N
sysName = Utils.createDefaultContext(sysName); //NOI18N
webModule.setContextPath (sysName);
}
try {
getAPIEjbJar().getMetadataModel().runReadActionWhenReady(new MetadataModelAction<EjbJarMetadata, Void>() {
public Void run(EjbJarMetadata metadata) throws Exception {
enterpriseBeansListener = new EnterpriseBeansListener(WebProject.this);
metadata.getRoot().getEnterpriseBeans().addPropertyChangeListener(enterpriseBeansListener);
return null;
}
});
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
if (Boolean.parseBoolean(evaluator().getProperty(
WebProjectProperties.J2EE_COMPILE_ON_SAVE))) {
Deployment.getDefault().enableCompileOnSaveSupport(webModule);
}
artifactSupport.enableArtifactSynchronization(true);
if (logicalViewProvider != null && logicalViewProvider.hasBrokenLinks()) {
ProjectProblems.showAlert(WebProject.this);
}
if(apiWebServicesSupport.isBroken(WebProject.this)) {
apiWebServicesSupport.showBrokenAlert(WebProject.this);
}
else if(WebServicesClientSupport.isBroken(WebProject.this)) {
WebServicesClientSupport.showBrokenAlert(WebProject.this);
}
webPagesFileWatch.init();
webInfFileWatch.init();
CssPreprocessors.getDefault().addCssPreprocessorsListener(cssSupport);
}
private void updateProject() {
// Make it easier to run headless builds on the same machine at least.
EditableProperties ep = updateHelper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
File buildProperties = new File(Places.getUserDirectory(), "build.properties"); // NOI18N
ep.setProperty("user.properties.file", buildProperties.getAbsolutePath()); //NOI18N
//remove jaxws.endorsed.dir property
ep.remove("jaxws.endorsed.dir");
filterBrokenLibraryRefs();
EditableProperties props = updateHelper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); //Reread the properties, PathParser changes them
if (props.getProperty(WebProjectProperties.J2EE_DEPLOY_ON_SAVE) == null) {
String server = evaluator().getProperty(WebProjectProperties.J2EE_SERVER_INSTANCE);
props.setProperty(WebProjectProperties.J2EE_DEPLOY_ON_SAVE,
server == null ? "false" : DeployOnSaveUtils.isDeployOnSaveSupported(server));
}
if (props.getProperty(WebProjectProperties.J2EE_COMPILE_ON_SAVE) == null) {
props.setProperty(WebProjectProperties.J2EE_COMPILE_ON_SAVE,
props.getProperty(WebProjectProperties.J2EE_DEPLOY_ON_SAVE));
}
// #134642 - use Ant task from copylibs library
SharabilityUtility.makeSureProjectHasCopyLibsLibrary(helper, refHelper);
// make sure that sharable project which requires JSP compilation has its own
// copy of jsp-compiler and jsp-compilation library:
if (helper.isSharableProject() && "true".equals(props.get(WebProjectProperties.COMPILE_JSPS))) {
makeSureProjectHasJspCompilationLibraries(refHelper);
}
J2EEProjectProperties.removeObsoleteLibraryLocations(ep);
J2EEProjectProperties.removeObsoleteLibraryLocations(props);
//add webinf.dir required by 6.0 projects
if (props.getProperty(WebProjectProperties.WEBINF_DIR) == null) {
//we can do this because in previous versions WEB-INF was expected under docbase
String web = props.get(WebProjectProperties.WEB_DOCBASE_DIR);
props.setProperty(WebProjectProperties.WEBINF_DIR, web + "/WEB-INF"); //NOI18N
}
//add persistence.xml.dir introduced in 6.5 - see issue 143884 and 142164
if (props.getProperty(WebProjectProperties.PERSISTENCE_XML_DIR) == null) {
props.setProperty(WebProjectProperties.PERSISTENCE_XML_DIR, "${" + WebProjectProperties.CONF_DIR + "}");
}
updateHelper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
// update a dual build directory project to use a single directory
if (updateHelper.isCurrent()) { // #113297, #118187
// this operation should be safe in future as well - of course if properties with the same name weren't re-introduced
props.remove("build.ear.web.dir"); // used to be WebProjectProperties.BUILD_EAR_WEB_DIR // NOI18N
props.remove("build.ear.classes.dir"); // used to be WebProjectProperties.BUILD_EAR_CLASSES_DIR // NOI18N
}
// check debug.classpath - can be done every time, whenever
String debugClassPath = props.getProperty(WebProjectProperties.DEBUG_CLASSPATH);
props.setProperty(WebProjectProperties.DEBUG_CLASSPATH, Utils.correctDebugClassPath(debugClassPath));
if (!props.containsKey(ProjectProperties.INCLUDES)) {
props.setProperty(ProjectProperties.INCLUDES, "**"); // NOI18N
}
if (!props.containsKey(ProjectProperties.EXCLUDES)) {
props.setProperty(ProjectProperties.EXCLUDES, ""); // NOI18N
}
if (!props.containsKey("build.generated.sources.dir")) { // NOI18N
props.setProperty("build.generated.sources.dir", "${build.dir}/generated-sources"); // NOI18N
}
if (!props.containsKey(ProjectProperties.ANNOTATION_PROCESSING_ENABLED))props.setProperty(ProjectProperties.ANNOTATION_PROCESSING_ENABLED, "true"); //NOI18N
if (!props.containsKey(ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR))props.setProperty(ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR, "true"); //NOI18N
if (!props.containsKey(ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS))props.setProperty(ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS, "true"); //NOI18N
if (!props.containsKey(ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST))props.setProperty(ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST, ""); //NOI18N
if (!props.containsKey(ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT))props.setProperty(ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT, "${build.generated.sources.dir}/ap-source-output"); //NOI18N
if (!props.containsKey(ProjectProperties.JAVAC_PROCESSORPATH))props.setProperty(ProjectProperties.JAVAC_PROCESSORPATH,"${" + ProjectProperties.JAVAC_CLASSPATH + "}"); //NOI18N
if (!props.containsKey("javac.test.processorpath"))props.setProperty("javac.test.processorpath", "${" + ProjectProperties.JAVAC_TEST_CLASSPATH + "}"); // NOI18N
// #207149
if (!props.containsKey(WebProjectProperties.J2EE_COPY_STATIC_FILES_ON_SAVE)) {
boolean b = Boolean.parseBoolean(props.getProperty(WebProjectProperties.J2EE_COMPILE_ON_SAVE));
props.setProperty(WebProjectProperties.J2EE_COPY_STATIC_FILES_ON_SAVE, b ? "true" : "false");
}
updateHelper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
try {
ProjectManager.getDefault().saveProject(WebProject.this);
} catch (IOException e) {
// #222721 - Provide a better error message in case of read-only location of project.
if (!WebProject.this.getProjectDirectory().canWrite()) {
NotifyDescriptor nd = new NotifyDescriptor.Message(Bundle.ERR_ProjectReadOnly());
DialogDisplayer.getDefault().notify(nd);
} else {
Exceptions.printStackTrace(e);
}
}
}
/**
* Filters the broken library references (see issue 110040).
*/
private void filterBrokenLibraryRefs() {
// filter the compilation CP
EditableProperties props = updateHelper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
List<ClassPathSupport.Item> toRemove = filterBrokenLibraryItems(cpMod.getClassPathSupport().itemsList(props.getProperty(ProjectProperties.JAVAC_CLASSPATH), WebProjectProperties.TAG_WEB_MODULE_LIBRARIES));
if (!toRemove.isEmpty()) {
LOGGER.log(Level.FINE, "Will remove broken classpath library references: " + toRemove);
try {
ClassPathModifierSupport.handleLibraryClassPathItems(WebProject.this, getAntProjectHelper(), cpMod.getClassPathSupport(),
toRemove, ProjectProperties.JAVAC_CLASSPATH, WebProjectProperties.TAG_WEB_MODULE_LIBRARIES, ClassPathModifier.REMOVE, false);
} catch (IOException e) {
// should only occur when passing true as the saveProject parameter which we are not doing here
Exceptions.printStackTrace(e);
}
}
// filter the additional (packaged) items
// need to re-read the properites as the handleLibraryClassPathItems() might have changed them
props = updateHelper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
toRemove = filterBrokenLibraryItems(libMod.getClassPathSupport().itemsList(props.getProperty(WebProjectProperties.WAR_CONTENT_ADDITIONAL), WebProjectProperties.TAG_WEB_MODULE__ADDITIONAL_LIBRARIES));
if (!toRemove.isEmpty()) {
LOGGER.log(Level.FINE, "Will remove broken additional library references: " + toRemove);
try {
ClassPathModifierSupport.handleLibraryClassPathItems(WebProject.this, getAntProjectHelper(), cpMod.getClassPathSupport(),
toRemove, WebProjectProperties.WAR_CONTENT_ADDITIONAL, WebProjectProperties.TAG_WEB_MODULE__ADDITIONAL_LIBRARIES, ClassPathModifier.REMOVE, false);
} catch (IOException e) {
// should only occur when passing true as the saveProject parameter which we are not doing here
Exceptions.printStackTrace(e);
}
}
}
private List<ClassPathSupport.Item> filterBrokenLibraryItems(List<ClassPathSupport.Item> items) {
List<ClassPathSupport.Item> toRemove = new LinkedList<ClassPathSupport.Item>();
Collection<? extends BrokenLibraryRefFilter> filters = null;
for (ClassPathSupport.Item item : items) {
if (!item.isBroken() || item.getType() != ClassPathSupport.Item.TYPE_LIBRARY) {
continue;
}
String libraryName = ClassPathSupport.getLibraryNameFromReference(item.getReference());
LOGGER.log(Level.FINE, "Broken reference to library: " + libraryName);
if (filters == null) {
// initializing the filters lazily because usually they will not be needed anyway
// (most projects have no broken references)
filters = createFilters(WebProject.this);
}
for (BrokenLibraryRefFilter filter : filters) {
if (filter.removeLibraryReference(libraryName)) {
LOGGER.log(Level.FINE, "Will remove broken reference to library " + libraryName + " because of filter " + filter.getClass().getName());
toRemove.add(item);
break;
}
}
}
return toRemove;
}
private List<BrokenLibraryRefFilter> createFilters(Project project) {
List<BrokenLibraryRefFilter> filters = new LinkedList<BrokenLibraryRefFilter>();
for (BrokenLibraryRefFilterProvider provider : Lookups.forPath("Projects/org-netbeans-modules-web-project/BrokenLibraryRefFilterProviders").lookupAll(BrokenLibraryRefFilterProvider.class)) { // NOI18N
BrokenLibraryRefFilter filter = provider.createFilter(project);
if (filter != null) {
filters.add(filter);
}
}
return filters;
}
@Override
protected void projectClosed() {
evaluator().removePropertyChangeListener(WebProject.this.webModule);
webPagesFileWatch.reset();
webInfFileWatch.reset();
// listen to j2ee platform classpath changes
String servInstID = evaluator().getProperty(WebProjectProperties.J2EE_SERVER_INSTANCE);
if (servInstID != null) {
try {
J2eePlatform platform = Deployment.getDefault().getServerInstance(servInstID).getJ2eePlatform();
if (platform != null) {
unregisterJ2eePlatformListener(platform);
}
} catch (InstanceRemovedException ex) {
// ignore in this case
}
}
if (enterpriseBeansListener != null){
try {
getAPIEjbJar().getMetadataModel().runReadActionWhenReady(new MetadataModelAction<EjbJarMetadata, Void>() {
public Void run(EjbJarMetadata metadata) throws Exception {
metadata.getRoot().getEnterpriseBeans().removePropertyChangeListener(enterpriseBeansListener);
enterpriseBeansListener = null;
return null;
}
});
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
// remove ServiceListener from jaxWsModel
//if (jaxWsModel!=null) jaxWsModel.removeServiceListener(jaxWsServiceListener);
// Probably unnecessary, but just in case:
try {
ProjectManager.getDefault().saveProject(WebProject.this);
} catch (IOException e) {
// #222721 - Provide a better error message in case of read-only location of project.
if (!WebProject.this.getProjectDirectory().canWrite()) {
NotifyDescriptor nd = new NotifyDescriptor.Message(Bundle.ERR_ProjectReadOnly());
DialogDisplayer.getDefault().notify(nd);
} else {
Exceptions.printStackTrace(e);
}
}
// Unregister copy on save support
try {
copyOnSaveSupport.cleanup();
}
catch (FileStateInvalidException e) {
Logger.getLogger("global").log(Level.INFO, null, e);
}
artifactSupport.enableArtifactSynchronization(false);
Deployment.getDefault().disableCompileOnSaveSupport(webModule);
// TODO: dongmei: anything for EJBs???????
// unregister project's classpaths to GlobalPathRegistry
try {
GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
GlobalPathRegistry.getDefault().unregister(ClassPath.COMPILE, cpProvider.getProjectClassPaths(ClassPath.COMPILE));
} catch (IllegalArgumentException e) {
// Classpath were not registered before unregistration
LOGGER.log(Level.INFO, "While trying to close the project, it was not possible to unregister classpath items "
+ "because they were not registered in the first place.", e);
}
CssPreprocessors.getDefault().removeCssPreprocessorsListener(cssSupport);
easelSupport.close();
}
}
/**
* Exports the main JAR as an official build product for use from other scripts.
* The type of the artifact will be {@link AntArtifact#TYPE_JAR}.
*/
private final class AntArtifactProviderImpl implements AntArtifactProvider {
public AntArtifact[] getBuildArtifacts() {
return new AntArtifact[] {
helper.createSimpleAntArtifact(WebProjectConstants.ARTIFACT_TYPE_WAR, "dist.war", evaluator(), "dist", "clean", WebProjectProperties.BUILD_FILE), // NOI18N
helper.createSimpleAntArtifact(WebProjectConstants.ARTIFACT_TYPE_WAR_EAR_ARCHIVE, "dist.ear.war", evaluator(), "dist-ear", "clean-ear", WebProjectProperties.BUILD_FILE) // NOI18N
};
}
}
// List of primarily supported templates
private static final String[] TYPES = new String[] {
"java-classes", // NOI18N
"java-main-class", // NOI18N
"java-forms", // NOI18N
"java-beans", // NOI18N
"persistence", // NOI18N
"oasis-XML-catalogs", // NOI18N
"XML", // NOI18N
"ant-script", // NOI18N
"ant-task", // NOI18N
"REST-clients", // NOI18N
"servlet-types", // NOI18N
"web-types", // NOI18N
"web-types-server", // NOI18N
"web-services", // NOI18N
"web-service-clients", // NOI18N
"wsdl", // NOI18N
"junit", // NOI18N
"html5", // NOI18N
"simple-files" // NOI18N
};
private static final String[] TYPES_EJB31 = new String[] {
"ejb-types", // NOI18N
"ejb-types-server", // NOI18N
"ejb-types_3_0", // NOI18N
"ejb-types_3_1", // NOI18N
"ejb-types_3_1_full", // NOI18N
"ejb-deployment-descriptor", // NOI18N
};
private static final String[] TYPES_EJB31_LITE = new String[] {
"ejb-types", // NOI18N
"ejb-types_3_0", // NOI18N
"ejb-types_3_1", // NOI18N
"ejb-deployment-descriptor", // NOI18N
};
private static final String[] TYPES_EJB32_LITE = new String[] {
"ejb-types", // NOI18N
"ejb-types_3_0", // NOI18N
"ejb-types_3_1", // NOI18N
"ejb-types_3_2", // NOI18N
"ejb-deployment-descriptor", // NOI18N
};
private static final String[] TYPES_ARCHIVE = new String[] {
"deployment-descriptor", // NOI18N
"XML", // NOI18N
};
private static final String[] PRIVILEGED_NAMES = new String[] {
"Templates/JSP_Servlet/JSP.jsp", // NOI18N
"Templates/JSP_Servlet/Html.html", // NOI18N
"Templates/JSP_Servlet/Servlet.java", // NOI18N
"Templates/Classes/Class.java", // NOI18N
"Templates/Classes/Package", // NOI18N
"Templates/WebServices/WebService.java", // NOI18N
"Templates/WebServices/WebServiceClient", // NOI18N
"Templates/Other/Folder" // NOI18N
};
private static final String[] PRIVILEGED_NAMES_EE5 = new String[] {
"Templates/JSP_Servlet/JSP.jsp", // NOI18N
"Templates/JSP_Servlet/Html.html", // NOI18N
"Templates/JSP_Servlet/Servlet.java", // NOI18N
"Templates/Classes/Class.java", // NOI18N
"Templates/Classes/Package", // NOI18N
"Templates/Persistence/Entity.java", // NOI18N
"Templates/Persistence/RelatedCMP", // NOI18N
"Templates/Persistence/JsfFromDB", // NOI18N
"Templates/WebServices/WebService.java", // NOI18N
"Templates/WebServices/WebServiceFromWSDL.java", // NOI18N
"Templates/WebServices/WebServiceClient", // NOI18N
"Templates/WebServices/RestServicesFromEntities", // NOI18N
"Templates/WebServices/RestServicesFromPatterns", //NOI18N
"Templates/Other/Folder" // NOI18N
};
private static final String[] PRIVILEGED_NAMES_EE6_FULL = new String[] {
"Templates/J2EE/Session", // NOI18N
"Templates/J2EE/Message", // NOI18N
"Templates/J2EE/TimerSession" // NOI18N
};
private static final String[] PRIVILEGED_NAMES_EE6_WEB = new String[] {
"Templates/J2EE/Session" // NOI18N
};
private static final String[] PRIVILEGED_NAMES_EE7_WEB = new String[] {
"Templates/J2EE/Session", // NOI18N
"Templates/J2EE/TimerSession" // NOI18N
};
private static final String[] PRIVILEGED_NAMES_ARCHIVE = new String[] {
"Templates/JSP_Servlet/webXml" // NOI18N ---
};
// guarded by this, #115809
private List<String> privilegedTemplatesEE5 = null;
private List<String> privilegedTemplates = null;
// Path where instances of privileged templates are registered
private static final String WEBTEMPLATE_PATH = "j2ee/webtier/templates"; //NOI18N
synchronized List<String> getPrivilegedTemplates() {
ensureTemplatesInitialized();
return privilegedTemplates;
}
synchronized List<String> getPrivilegedTemplatesEE5() {
ensureTemplatesInitialized();
return privilegedTemplatesEE5;
}
public synchronized void resetTemplates() {
privilegedTemplates = null;
privilegedTemplatesEE5 = null;
}
private void ensureTemplatesInitialized() {
assert Thread.holdsLock(this);
if (privilegedTemplates != null
&& privilegedTemplatesEE5 != null
) {
return;
}
privilegedTemplatesEE5 = new ArrayList<String>();
privilegedTemplates = new ArrayList<String>();
for (WebPrivilegedTemplates webPrivililegedTemplates : Lookups.forPath(WEBTEMPLATE_PATH).lookupAll(WebPrivilegedTemplates.class)) {
String[] addedTemplates = webPrivililegedTemplates.getPrivilegedTemplates(apiWebModule);
if (addedTemplates != null && addedTemplates.length > 0){
List<String> addedList = Arrays.asList(addedTemplates);
privilegedTemplatesEE5.addAll(addedList);
privilegedTemplates.addAll(addedList);
}
}
privilegedTemplatesEE5.addAll(Arrays.asList(PRIVILEGED_NAMES_EE5));
privilegedTemplates.addAll(Arrays.asList(PRIVILEGED_NAMES));
}
private final class RecommendedTemplatesImpl implements RecommendedTemplates,
PrivilegedTemplates, PropertyChangeListener {
private WebProject project;
private J2eeProjectCapabilities projectCap;
RecommendedTemplatesImpl (WebProject project) {
this.project = project;
project.evaluator().addPropertyChangeListener(this);
}
private boolean checked = false;
private boolean isArchive = false;
private boolean isEE5 = false;
private boolean serverSupportsEJB31 = false;
private boolean serverSupportsEJB40 = false;
@Override
public String[] getRecommendedTypes() {
checkEnvironment();
if (isArchive) {
return TYPES_ARCHIVE;
} else if (projectCap.isEjb31LiteSupported() || projectCap.isEjb40LiteSupported()) {
Set<String> set = new HashSet<>(Arrays.asList(TYPES));
if (projectCap.isEjb31Supported() || projectCap.isEjb40Supported()
|| serverSupportsEJB31 || serverSupportsEJB40) {
set.addAll(Arrays.asList(TYPES_EJB31));
}
if (projectCap.isEjb32LiteSupported() || projectCap.isEjb40LiteSupported()) {
set.addAll(Arrays.asList(TYPES_EJB32_LITE));
} else {
set.addAll(Arrays.asList(TYPES_EJB31_LITE));
}
return set.toArray(new String[0]);
} else {
return TYPES;
}
}
@Override
public String[] getPrivilegedTemplates() {
checkEnvironment();
if (isArchive) {
return PRIVILEGED_NAMES_ARCHIVE;
} else {
Set<String> set = new HashSet<String>();
if (projectCap.isEjb31LiteSupported()) {
set.addAll(getPrivilegedTemplatesEE5());
if (projectCap.isEjb31Supported() || projectCap.isEjb40Supported()
|| serverSupportsEJB31 || serverSupportsEJB40) {
set.addAll(Arrays.asList(PRIVILEGED_NAMES_EE6_FULL));
}
if (projectCap.isEjb32LiteSupported() || projectCap.isEjb40LiteSupported()) {
set.addAll(Arrays.asList(PRIVILEGED_NAMES_EE7_WEB));
} else {
set.addAll(Arrays.asList(PRIVILEGED_NAMES_EE6_WEB));
}
} else if (isEE5) {
set.addAll(getPrivilegedTemplatesEE5());
} else {
set.addAll(WebProject.this.getPrivilegedTemplates());
}
return set.toArray(new String[set.size()]);
}
}
private void checkEnvironment() {
if (!checked) {
final Object srcType = helper.getStandardPropertyEvaluator().
getProperty(WebProjectProperties.JAVA_SOURCE_BASED);
if ("false".equals(srcType)) {
isArchive = true;
}
projectCap = J2eeProjectCapabilities.forProject(project);
Profile profile = Profile.fromPropertiesString(eval.getProperty(WebProjectProperties.J2EE_PLATFORM));
isEE5 = profile == Profile.JAVA_EE_5;
serverSupportsEJB31 = ProjectUtil.getSupportedProfiles(project).contains(Profile.JAVA_EE_6_FULL) ||
ProjectUtil.getSupportedProfiles(project).contains(Profile.JAVA_EE_7_FULL) ||
ProjectUtil.getSupportedProfiles(project).contains(Profile.JAVA_EE_8_FULL) ||
ProjectUtil.getSupportedProfiles(project).contains(Profile.JAKARTA_EE_8_FULL);
serverSupportsEJB40 = ProjectUtil.getSupportedProfiles(project).contains(Profile.JAKARTA_EE_9_FULL)
|| ProjectUtil.getSupportedProfiles(project).contains(Profile.JAKARTA_EE_9_1_FULL)
|| ProjectUtil.getSupportedProfiles(project).contains(Profile.JAKARTA_EE_10_FULL);
checked = true;
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (WebProjectProperties.J2EE_SERVER_INSTANCE.equals(evt.getPropertyName())) {
checked = false;
}
}
}
private class DeployOnSaveSupportProxy implements DeployOnSaveSupport {
public synchronized void addArtifactListener(ArtifactListener listener) {
copyOnSaveSupport.addArtifactListener(listener);
artifactSupport.addArtifactListener(listener);
}
public synchronized void removeArtifactListener(ArtifactListener listener) {
copyOnSaveSupport.removeArtifactListener(listener);
artifactSupport.removeArtifactListener(listener);
}
public boolean containsIdeArtifacts() {
return DeployOnSaveUtils.containsIdeArtifacts(eval, updateHelper, "build.classes.dir");
}
}
/**
* This class handle copying of web resources to appropriate place in build
* dir. User is not forced to perform redeploy on JSP change. This
* class is also used in true Deploy On Save.
*
* Class should not request project lock from FS listener methods
* (deadlock prone).
*/
private class CopyOnSaveSupport extends FileChangeAdapter implements PropertyChangeListener, DeployOnSaveListener {
private FileObject docBase = null;
private String docBaseValue = null;
private FileObject webInf = null;
private String webInfValue = null;
private File resources = null;
private String buildWeb = null;
private String buildClasses = null;
private final List<ArtifactListener> listeners = new CopyOnWriteArrayList<ArtifactListener>();
/** Creates a new instance of CopyOnSaveSupport */
public CopyOnSaveSupport() {
super();
}
public void addArtifactListener(ArtifactListener listener) {
listeners.add(listener);
}
public void removeArtifactListener(ArtifactListener listener) {
listeners.remove(listener);
}
private boolean isCopyOnSaveEnabled() {
return Boolean.parseBoolean(WebProject.this.evaluator().getProperty(WebProjectProperties.J2EE_COPY_STATIC_FILES_ON_SAVE));
}
public void initialize() throws FileStateInvalidException {
WebProject.this.evaluator().addPropertyChangeListener(this);
if (!isCopyOnSaveEnabled()) {
return;
}
docBase = getWebModule().getDocumentBase();
docBaseValue = evaluator().getProperty(WebProjectProperties.WEB_DOCBASE_DIR);
webInf = getWebModule().getWebInf();
webInfValue = evaluator().getProperty(WebProjectProperties.WEBINF_DIR);
if (resources != null) {
FileUtil.removeFileChangeListener(this, resources);
}
resources = getWebModule().getResourceDirectory();
buildWeb = evaluator().getProperty(WebProjectProperties.BUILD_WEB_DIR);
buildClasses = evaluator().getProperty("build.classes.dir");
if (docBase != null) {
docBase.addRecursiveListener(this);
}
if (webInf != null && !FileUtil.isParentOf(docBase, webInf)) {
webInf.addRecursiveListener(this);
}
if (resources != null) {
FileUtil.addFileChangeListener(this, resources);
}
// Add deployed resources notification listener
webModule.getConfigSupport().addDeployOnSaveListener(this);
LOGGER.log(Level.FINE, "Web directory is {0}", docBaseValue);
LOGGER.log(Level.FINE, "WEB-INF directory is {0}", webInfValue);
}
public void cleanup() throws FileStateInvalidException {
if (docBase != null) {
docBase.removeRecursiveListener(this);
}
if (webInf != null && !FileUtil.isParentOf(docBase, webInf)) {
webInf.removeRecursiveListener(this);
}
if (resources != null) {
FileUtil.removeFileChangeListener(this, resources);
resources = null;
}
WebProject.this.evaluator().removePropertyChangeListener(this);
webModule.getConfigSupport().removeDeployOnSaveListener(this);
}
public void propertyChange(PropertyChangeEvent evt) {
if (WebProjectProperties.WEB_DOCBASE_DIR.equals(evt.getPropertyName())
|| WebProjectProperties.WEBINF_DIR.equals(evt.getPropertyName())
|| WebProjectProperties.J2EE_COPY_STATIC_FILES_ON_SAVE.equals(evt.getPropertyName())
|| WebProjectProperties.RESOURCE_DIR.equals(evt.getPropertyName())) {
try {
cleanup();
initialize();
} catch (org.openide.filesystems.FileStateInvalidException e) {
LOGGER.log(Level.INFO, null, e);
}
} else if (WebProjectProperties.BUILD_WEB_DIR.equals(evt.getPropertyName())) {
// TODO copy all files ?
Object value = evt.getNewValue();
buildWeb = value == null ? null : value.toString();
}
}
private void checkPreprocessors(FileObject fileObject) {
CssPreprocessors.getDefault().process(WebProject.this, fileObject);
}
private void checkPreprocessors(FileObject fileObject, String originalName, String originalExtension) {
CssPreprocessors.getDefault().process(WebProject.this, fileObject, originalName, originalExtension);
}
@Override
public void fileChanged(FileEvent fe) {
checkPreprocessors(fe.getFile());
try {
if (!handleResource(fe)) {
handleCopyFileToDestDir(fe.getFile());
}
} catch (IOException e) {
LOGGER.log(Level.INFO, null, e);
}
}
@Override
public void fileFolderCreated(FileEvent fe) {
try {
if (!handleResource(fe)) {
handleCopyFileToDestDir(fe.getFile());
}
} catch (IOException e) {
LOGGER.log(Level.INFO, null, e);
}
}
@Override
public void fileDataCreated(FileEvent fe) {
checkPreprocessors(fe.getFile());
try {
if (!handleResource(fe)) {
handleCopyFileToDestDir(fe.getFile());
}
} catch (IOException e) {
LOGGER.log(Level.INFO, null, e);
}
}
@Override
public void fileRenamed(FileRenameEvent fe) {
checkPreprocessors(fe.getFile(), fe.getName(), fe.getExt());
try {
if (handleResource(fe)) {
return;
}
FileObject fo = fe.getFile();
handleCopyFileToDestDir(fo);
FileObject persistenceXmlDir = getWebModule().getPersistenceXmlDir();
if (persistenceXmlDir != null && FileUtil.isParentOf(persistenceXmlDir, fo)
&& "persistence.xml".equals(fe.getName() + "." + fe.getExt())) { // NOI18N
String path = "WEB-INF/classes/META-INF/" + FileUtil.getRelativePath(persistenceXmlDir, fo.getParent())
+ "/" + fe.getName() + "." + fe.getExt(); // NOI18N
if (!isSynchronizationAppropriate(path)) {
return;
}
handleDeleteFileInDestDir(path);
return;
}
FileObject webInf = getWebModule().resolveWebInf(docBaseValue, webInfValue, true, true);
FileObject docBase = getWebModule().resolveDocumentBase(docBaseValue, false);
if (webInf != null && FileUtil.isParentOf(webInf, fo)
&& !(webInf.getParent() != null && webInf.getParent().equals(docBase))) {
// inside webinf
FileObject parent = fo.getParent();
String path;
if (FileUtil.isParentOf(webInf, parent)) {
path = FileUtil.getRelativePath(webInf, fo.getParent())
+ "/" + fe.getName() + "." + fe.getExt(); // NOI18N
} else {
path = fe.getName() + "." + fe.getExt(); // NOI18N
}
path = "WEB-INF/" + path;
if (!isSynchronizationAppropriate(path)) {
return;
}
handleDeleteFileInDestDir(path);
}
if (docBase != null && FileUtil.isParentOf(docBase, fo)) {
// inside docbase
FileObject parent = fo.getParent();
String path;
if (FileUtil.isParentOf(docBase, parent)) {
path = FileUtil.getRelativePath(docBase, fo.getParent())
+ "/" + fe.getName() + "." + fe.getExt(); // NOI18N
} else {
path = fe.getName() + "." + fe.getExt(); // NOI18N
}
if (!isSynchronizationAppropriate(path)) {
return;
}
handleDeleteFileInDestDir(path);
}
} catch (IOException e) {
LOGGER.log(Level.INFO, null, e);
}
}
@Override
public void fileDeleted(FileEvent fe) {
checkPreprocessors(fe.getFile());
try {
if (handleResource(fe)) {
return;
}
FileObject fo = fe.getFile();
FileObject persistenceXmlDir = getWebModule().getPersistenceXmlDir();
if (persistenceXmlDir != null && FileUtil.isParentOf(persistenceXmlDir, fo)
&& "persistence.xml".equals(fo.getNameExt())) { // NOI18N
String path = "WEB-INF/classes/META-INF/" + FileUtil.getRelativePath(persistenceXmlDir, fo); // NOI18N
if (!isSynchronizationAppropriate(path)) {
return;
}
handleDeleteFileInDestDir(path);
return;
}
FileObject webInf = getWebModule().resolveWebInf(docBaseValue, webInfValue, true, true);
FileObject docBase = getWebModule().resolveDocumentBase(docBaseValue, false);
if (webInf != null && FileUtil.isParentOf(webInf, fo)
&& !(webInf.getParent() != null && webInf.getParent().equals(docBase))) {
// inside webInf
String path = "WEB-INF/" + FileUtil.getRelativePath(webInf, fo); // NOI18N
if (!isSynchronizationAppropriate(path)) {
return;
}
handleDeleteFileInDestDir(path);
}
if (docBase != null && FileUtil.isParentOf(docBase, fo)) {
// inside docbase
String path = FileUtil.getRelativePath(docBase, fo);
if (!isSynchronizationAppropriate(path)) {
return;
}
handleDeleteFileInDestDir(path);
}
} catch (IOException e) {
LOGGER.log(Level.INFO, null, e);
}
}
private boolean isSynchronizationAppropriate(String filePath) {
if (filePath.startsWith("WEB-INF/classes") && !filePath.startsWith("WEB-INF/classes/META-INF")) { // NOI18N
return false;
}
if (filePath.startsWith("WEB-INF/src")) { // NOI18N
return false;
}
if (filePath.startsWith("WEB-INF/lib")) { // NOI18N
return false;
}
return true;
}
private void fireArtifactChange(Iterable<ArtifactListener.Artifact> artifacts) {
for (ArtifactListener listener : listeners) {
listener.artifactsUpdated(artifacts);
}
}
private boolean handleResource(FileEvent fe) {
// this may happen in broken project - see issue #191516
// in any case it can't be resource event when resources is null
if (resources == null) {
return false;
}
FileObject resourceFo = FileUtil.toFileObject(resources);
if (resourceFo != null
&& (resourceFo.equals(fe.getFile()) || FileUtil.isParentOf(resourceFo, fe.getFile()))) {
fireArtifactChange(Collections.singleton(
Artifact.forFile(FileUtil.toFile(fe.getFile())).serverResource()));
return true;
}
return false;
}
private void handleDeleteFileInDestDir(String resourcePath) throws IOException {
File deleted = null;
FileObject webBuildBase = buildWeb == null ? null : helper.resolveFileObject(buildWeb);
if (webBuildBase != null) {
// project was built
FileObject toDelete = webBuildBase.getFileObject(resourcePath);
if (toDelete != null) {
deleted = FileUtil.toFile(toDelete);
toDelete.delete();
}
if (deleted != null) {
fireArtifactChange(Collections.singleton(ArtifactListener.Artifact.forFile(deleted)));
}
}
}
private void handleCopyFileToDestDir(FileObject fo) throws IOException {
if (fo.isVirtual()) {
return;
}
FileObject persistenceXmlDir = getWebModule().getPersistenceXmlDir();
if (persistenceXmlDir != null && FileUtil.isParentOf(persistenceXmlDir, fo)
&& "persistence.xml".equals(fo.getNameExt())) { // NOI18N
handleCopyFileToDestDir("WEB-INF/classes/META-INF", persistenceXmlDir, fo); // NOI18N
return;
}
FileObject webInf = getWebModule().resolveWebInf(docBaseValue, webInfValue, true, true);
FileObject docBase = getWebModule().resolveDocumentBase(docBaseValue, false);
if (webInf != null && FileUtil.isParentOf(webInf, fo)
&& !(webInf.getParent() != null && webInf.getParent().equals(docBase))) {
handleCopyFileToDestDir("WEB-INF", webInf, fo); // NOI18N
return;
}
if (docBase != null && FileUtil.isParentOf(docBase, fo)) {
handleCopyFileToDestDir(null, docBase, fo);
return;
}
}
private void handleCopyFileToDestDir(String prefix, FileObject baseDir, FileObject fo) throws IOException {
if (fo.isVirtual()) {
return;
}
if (baseDir != null && FileUtil.isParentOf(baseDir, fo)) {
// inside docbase
String path = FileUtil.getRelativePath(baseDir, fo);
if (prefix != null) {
path = prefix + "/" + path;
}
if (!isSynchronizationAppropriate(path)) {
return;
}
FileObject webBuildBase = buildWeb == null ? null : helper.resolveFileObject(buildWeb);
if (webBuildBase != null) {
// project was built
if (FileUtil.isParentOf(baseDir, webBuildBase) || FileUtil.isParentOf(webBuildBase, baseDir)) {
//cannot copy into self
return;
}
FileObject destFile = ensureDestinationFileExists(webBuildBase, path, fo.isFolder());
if (!fo.isFolder()) {
InputStream is = null;
OutputStream os = null;
FileLock fl = null;
try {
is = fo.getInputStream();
fl = destFile.lock();
os = destFile.getOutputStream(fl);
FileUtil.copy(is, os);
} finally {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
if (fl != null) {
fl.releaseLock();
}
File file = FileUtil.toFile(destFile);
if (file != null) {
fireArtifactChange(Collections.singleton(ArtifactListener.Artifact.forFile(file)));
}
}
} else {
File file = FileUtil.toFile(destFile);
if (file != null) {
fireArtifactChange(Collections.singleton(ArtifactListener.Artifact.forFile(file)));
}
}
}
}
}
/**
* Returns the destination (parent) directory needed to create file
* with relative path path under webBuilBase
*/
@NonNull
private FileObject ensureDestinationFileExists(FileObject webBuildBase, String path, boolean isFolder) throws IOException {
FileObject current = webBuildBase;
StringTokenizer st = new StringTokenizer(path, "/");
while (st.hasMoreTokens()) {
String pathItem = st.nextToken();
FileObject newCurrent = current.getFileObject(pathItem);
if (newCurrent == null) {
// need to create it
if (isFolder || st.hasMoreTokens()) {
// create a folder
newCurrent = FileUtil.createFolder(current, pathItem);
assert newCurrent != null : "webBuildBase: " + webBuildBase + ", path: " + path + ", isFolder: " + isFolder;
} else {
newCurrent = FileUtil.createData(current, pathItem);
assert newCurrent != null : "webBuildBase: " + webBuildBase + ", path: " + path + ", isFolder: " + isFolder;
}
}
current = newCurrent;
}
assert current != null : "webBuildBase: " + webBuildBase + ", path: " + path + ", isFolder: " + isFolder;
return current;
}
public void deployed(Iterable<Artifact> artifacts) {
if (!easelSupport.canReload()) {
return;
}
for (Artifact artifact : artifacts) {
FileObject fileObject = getReloadFileObject(artifact);
if (fileObject != null) {
easelSupport.reload(fileObject);
}
}
}
private FileObject getReloadFileObject(Artifact artifact) {
File file = artifact.getFile();
FileObject fileObject = FileUtil.toFileObject(FileUtil.normalizeFile(file));
if (fileObject == null) {
return null;
}
return findSourceForBinary(fileObject);
}
// "Binary" means compiled class file or web root document copied into build directory
private FileObject findSourceForBinary(FileObject artifact) {
FileObject webClassesBase = buildClasses == null ? null : helper.resolveFileObject(buildClasses);
FileObject webBuildBase = buildWeb == null ? null : helper.resolveFileObject(buildWeb);
if (webClassesBase != null && FileUtil.isParentOf(webClassesBase, artifact)) {
String path = FileUtil.getRelativePath(webClassesBase, artifact).replace(".class", ".java"); // NOI18N
for (SourceGroup sg : ProjectUtils.getSources(WebProject.this).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)) {
FileObject fo = sg.getRootFolder().getFileObject(path);
if (fo != null) {
return fo;
}
}
return null;
}
if (docBase != null && webBuildBase != null) {
if (FileUtil.isParentOf(webBuildBase, artifact)) {
String path = FileUtil.getRelativePath(webBuildBase, artifact);
return docBase.getFileObject(path);
}
}
return null;
}
}
private class ArtifactCopySupport extends ArtifactCopyOnSaveSupport {
public ArtifactCopySupport() {
super(WebProjectProperties.BUILD_WEB_DIR, evaluator(), getAntProjectHelper());
}
@Override
public List<ArtifactCopyOnSaveSupport.Item> getArtifacts() {
final AntProjectHelper helper = getAntProjectHelper();
ClassPathSupport cs = new ClassPathSupport(evaluator(), getReferenceHelper(),
helper, getUpdateHelper(), new ClassPathSupportCallbackImpl(helper));
List<ArtifactCopyOnSaveSupport.Item> result = new ArrayList<ArtifactCopyOnSaveSupport.Item>();
for (ClassPathSupport.Item item : cs.itemsList(
helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(ProjectProperties.JAVAC_CLASSPATH),
WebProjectProperties.TAG_WEB_MODULE_LIBRARIES)) {
if (!item.isBroken() && (item.getType() == ClassPathSupport.Item.TYPE_ARTIFACT
|| item.getType() == ClassPathSupport.Item.TYPE_LIBRARY
|| item.getType() == ClassPathSupport.Item.TYPE_JAR)) {
String path = item.getAdditionalProperty(ClassPathSupportCallbackImpl.PATH_IN_DEPLOYMENT);
String dirs = item.getAdditionalProperty(AntProjectConstants.DESTINATION_DIRECTORY);
if (path != null) {
result.add(new Item(item, new ItemDescription(path, RelocationType.fromString(dirs))));
}
}
}
return result;
}
@Override
protected Artifact filterArtifact(Artifact artifact, RelocationType type) {
if (containsTLD(artifact.getFile()) || type == RelocationType.NONE) {
return artifact;
}
if (type == RelocationType.ROOT) {
return artifact.relocatable();
} else if (type == RelocationType.LIB) {
return artifact.relocatable("lib"); // NOI18N
} else {
return artifact;
}
}
private boolean containsTLD(File f) {
if (f.exists() && f.isFile() && f.canRead()) {
ZipFile zip = null;
try {
zip = new ZipFile(f);
for (Enumeration entries = zip.entries(); entries.hasMoreElements();) {
String zipEntryName = ((ZipEntry) entries.nextElement()).getName();
if (TLD_PATTERN.matcher(zipEntryName).matches()) {
return true;
}
}
return false;
} catch (IOException ex) {
LOGGER.log(Level.INFO, null, ex);
} finally {
if (zip != null) {
try {
zip.close();
} catch (IOException ex) {
LOGGER.log(Level.INFO, null, ex);
}
}
}
}
return false;
}
}
public boolean isJavaEE5(Project project) {
return Profile.JAVA_EE_5.equals(getAPIWebModule().getJ2eeProfile());
}
private static final class WebPropertyEvaluatorImpl implements WebPropertyEvaluator {
private PropertyEvaluator evaluator;
public WebPropertyEvaluatorImpl (PropertyEvaluator eval) {
evaluator = eval;
}
public PropertyEvaluator evaluator() {
return evaluator;
}
}
private class WebExtenderImplementation implements AntBuildExtenderImplementation {
//add targets here as required by the external plugins..
public List<String> getExtensibleTargets() {
String[] targets = new String[] {
"-do-init", "-init-check", "-post-clean", "jar", "-pre-pre-compile","-do-ws-compile","-do-compile","-do-compile-single", "-post-compile", "-pre-dist", //NOI18N
};
return Arrays.asList(targets);
}
public Project getOwningProject() {
return WebProject.this;
}
}
private static final class CoSAwareFileBuiltQueryImpl implements FileBuiltQueryImplementation, PropertyChangeListener
{
private final FileBuiltQueryImplementation delegate;
private final WebProject project;
private final AtomicBoolean cosEnabled = new AtomicBoolean();
private final Map<FileObject, Reference<StatusImpl>> file2Status = new WeakHashMap<FileObject, Reference<StatusImpl>>();
public CoSAwareFileBuiltQueryImpl(FileBuiltQueryImplementation delegate, WebProject project)
{
this.delegate = delegate;
this.project = project;
project.evaluator().addPropertyChangeListener(this);
setCoSEnabledAndXor();
}
private synchronized StatusImpl readFromCache(FileObject file)
{
Reference<StatusImpl> r = file2Status.get(file);
return r != null ? r.get() : null;
}
public Status getStatus(FileObject file)
{
StatusImpl result = readFromCache(file);
if (result != null)
{
return result;
}
Status status = delegate.getStatus(file);
if (status == null)
{
return null;
}
synchronized (this)
{
StatusImpl foisted = readFromCache(file);
if (foisted != null)
{
return foisted;
}
file2Status.put(file, new WeakReference<StatusImpl>(result = new StatusImpl(cosEnabled, status)));
}
return result;
}
boolean setCoSEnabledAndXor()
{
boolean nue = Boolean.parseBoolean(project.evaluator().getProperty(
WebProjectProperties.J2EE_COMPILE_ON_SAVE));
boolean old = cosEnabled.getAndSet(nue);
return old != nue;
}
public void propertyChange(PropertyChangeEvent evt)
{
if (!setCoSEnabledAndXor())
{
return;
}
Collection<Reference<StatusImpl>> toRefresh;
synchronized (this)
{
toRefresh = new LinkedList<Reference<StatusImpl>>(file2Status.values());
}
for (Reference<StatusImpl> r : toRefresh)
{
StatusImpl s = r.get();
if (s != null)
{
s.stateChanged(null);
}
}
}
private static final class StatusImpl implements Status, ChangeListener
{
private final ChangeSupport cs = new ChangeSupport(this);
private final AtomicBoolean cosEnabled;
private final Status delegate;
public StatusImpl(AtomicBoolean cosEnabled, Status delegate)
{
this.cosEnabled = cosEnabled;
this.delegate = delegate;
this.delegate.addChangeListener(this);
}
public boolean isBuilt()
{
return cosEnabled.get() || delegate.isBuilt();
}
public void addChangeListener(ChangeListener l)
{
cs.addChangeListener(l);
}
public void removeChangeListener(ChangeListener l)
{
cs.removeChangeListener(l);
}
public void stateChanged(ChangeEvent e)
{
cs.fireChange();
}
}
}
// FIXME this is just fallback for code searching for the old SPI in lookup
// remove in next release
@SuppressWarnings("deprecation")
private static class WebModuleImpl implements WebModuleImplementation {
private final WebModule apiModule;
public WebModuleImpl(WebModule apiModule) {
this.apiModule = apiModule;
}
public FileObject getWebInf() {
return apiModule.getWebInf();
}
public MetadataModel<WebAppMetadata> getMetadataModel() {
return apiModule.getMetadataModel();
}
public FileObject[] getJavaSources() {
return apiModule.getJavaSources();
}
public String getJ2eePlatformVersion() {
return apiModule.getJ2eePlatformVersion();
}
public FileObject getDocumentBase() {
return apiModule.getDocumentBase();
}
public FileObject getDeploymentDescriptor() {
return apiModule.getDeploymentDescriptor();
}
public String getContextPath() {
return apiModule.getContextPath();
}
}
private static class WebModuleImpl2 implements WebModuleImplementation2 {
private final ProjectWebModule webModule;
public WebModuleImpl2(ProjectWebModule webModule) {
this.webModule = webModule;
}
public String getContextPath() {
return webModule.getContextPath();
}
public FileObject getDeploymentDescriptor() {
return webModule.getDeploymentDescriptor();
}
public FileObject getDocumentBase() {
return webModule.getDocumentBase();
}
public Profile getJ2eeProfile() {
return webModule.getJ2eeProfile();
}
public FileObject[] getJavaSources() {
return webModule.getJavaSources();
}
public MetadataModel<WebAppMetadata> getMetadataModel() {
return webModule.getMetadataModel();
}
public FileObject getWebInf() {
return webModule.getWebInf();
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
webModule.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
webModule.removePropertyChangeListener(listener);
}
}
private static class WebProjectLookup extends ProxyLookup implements PropertyChangeListener{
private Lookup base, ee6;
private WebProject project;
private ProjectBrowserProvider browserProvider;
public WebProjectLookup(WebProject project, Lookup base, Lookup ee6, ProjectBrowserProvider browserProvider) {
super(base);
this.project = project;
this.base = base;
this.ee6 = ee6;
this.browserProvider = browserProvider;
updateLookup();
}
private void updateLookup(){
List<Lookup> lookups = new ArrayList<>();
lookups.add(base);
Profile profile = Profile.fromPropertiesString(project.evaluator().getProperty(WebProjectProperties.J2EE_PLATFORM));
if (Profile.JAVA_EE_6_FULL.equals(profile) || Profile.JAVA_EE_6_WEB.equals(profile)
|| Profile.JAVA_EE_7_FULL.equals(profile) || Profile.JAVA_EE_7_WEB.equals(profile)
|| Profile.JAVA_EE_8_FULL.equals(profile) || Profile.JAVA_EE_8_WEB.equals(profile)
|| Profile.JAKARTA_EE_8_FULL.equals(profile) || Profile.JAKARTA_EE_8_WEB.equals(profile)
|| Profile.JAKARTA_EE_9_FULL.equals(profile) || Profile.JAKARTA_EE_9_WEB.equals(profile)
|| Profile.JAKARTA_EE_9_1_FULL.equals(profile) || Profile.JAKARTA_EE_9_1_WEB.equals(profile)
|| Profile.JAKARTA_EE_10_FULL.equals(profile) || Profile.JAKARTA_EE_10_WEB.equals(profile)) {
lookups.add(ee6);
}
if ("true".equals(project.evaluator().getProperty(WebProjectProperties.DISPLAY_BROWSER))) {
lookups.add(Lookups.singleton(browserProvider));
}
setLookups(lookups.toArray(new Lookup[lookups.size()]));
}
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(WebProjectProperties.J2EE_PLATFORM) ||
evt.getPropertyName().equals(WebProjectProperties.DISPLAY_BROWSER) ){
updateLookup();
}
}
}
private static class EnterpriseBeansListener implements PropertyChangeListener{
private static final RequestProcessor rp = new RequestProcessor();
private Task upgradeTask = null;
private WebProject project;
public EnterpriseBeansListener(WebProject project) {
this.project = project;
}
public synchronized void propertyChange(final PropertyChangeEvent evt) {
if (upgradeTask != null){
upgradeTask.schedule(100);
return;
}
upgradeTask = rp.post(new Runnable() {
public void run() {
WebProjectUtilities.upgradeJ2EEProfile(project);
}
}, 100);
}
}
private static final class ProjectWebRootProviderImpl implements ProjectWebRootProvider {
private final WebProject project;
private ProjectWebRootProviderImpl(WebProject project) {
assert project != null;
this.project = project;
}
@Override
public FileObject getWebRoot(FileObject file) {
WebModule webModule = WebModule.getWebModule(file);
FileObject webRoot = webModule != null ? webModule.getDocumentBase() : null;
if(webRoot != null) {
//#181480 - the WebModule.getWebModule() returns a webmodule instance
//also for files outside of document base, which is OK.
return FileUtil.isParentOf(webRoot, file) ?
webRoot :
null;
}
return null;
}
@Override
public Collection<FileObject> getWebRoots() {
WebModule webModule = project.getAPIWebModule();
FileObject webRoot = webModule != null ? webModule.getDocumentBase() : null;
if (webRoot != null) {
return Collections.singleton(webRoot);
}
return Collections.emptyList();
}
}
private final class WhiteListUpdaterImpl extends WhiteListUpdater {
public WhiteListUpdaterImpl(Project project) {
super(project);
}
@Override
public void addSettingListener() {
evaluator().addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(JavaEEProjectSettingConstants.J2EE_SERVER_INSTANCE)){
checkWhiteLists();
}
if (evt.getPropertyName().equals(ProjectProperties.JAVAC_CLASSPATH)){
// if classpath changes refresh whitelists as well:
updateWhitelist(null, getServerWhiteList());
}
}
});
}
}
private class JavaEEProjectSettingsImpl implements JavaEEProjectSettingsImplementation {
private final WebProject project;
public JavaEEProjectSettingsImpl(WebProject project) {
this.project = project;
evaluator().addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (WebProjectProperties.SELECTED_BROWSER.equals(evt.getPropertyName())) {
easelSupport.resetBrowserSupport();
}
}
});
}
@Override
public void setProfile(Profile profile) {
setInSharedProperties(JavaEEProjectSettingConstants.J2EE_PLATFORM, profile.toPropertiesString());
}
@Override
public Profile getProfile() {
return webModule.getJ2eeProfile();
}
@Override
public void setBrowserID(String browserID) {
setInSharedProperties(JavaEEProjectSettingConstants.SELECTED_BROWSER, browserID);
}
@Override
public String getBrowserID() {
return evaluator().getProperty(JavaEEProjectSettingConstants.SELECTED_BROWSER);
}
@Override
public void setServerInstanceID(String serverInstanceID) {
setInSharedProperties(JavaEEProjectSettingConstants.J2EE_SERVER_INSTANCE, serverInstanceID);
}
@Override
public String getServerInstanceID() {
return evaluator().getProperty(JavaEEProjectSettingConstants.J2EE_SERVER_INSTANCE);
}
private void setInSharedProperties(String key, String value) {
try {
UpdateHelper helper = project.getUpdateHelper();
EditableProperties projectProperties = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
projectProperties.setProperty(key, value);
helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, projectProperties);
ProjectManager.getDefault().saveProject(project);
} catch (IOException ex) {
LOGGER.log(Level.WARNING, "Project properties couldn't be saved.", ex);
}
}
}
}