? java/j2seproject/copylibstask/test Index: ant/project/apichanges.xml =================================================================== RCS file: /shared/data/ccvs/repository/ant/project/apichanges.xml,v retrieving revision 1.11 retrieving revision 1.11.28.1 diff -u -r1.11 -r1.11.28.1 --- ant/project/apichanges.xml 7 Sep 2005 12:56:30 -0000 1.11 +++ ant/project/apichanges.xml 15 Jun 2006 20:38:20 -0000 1.11.28.1 @@ -76,6 +76,25 @@ + + + Added utilities for constructing richer property evaluators + + + + + +

+ Added a new method and nested class to PropertyUtils to + make it easier to write a customizer version of + AntProjectHelper.getStandardPropertyEvaluator(), + among other things. +

+
+ + +
+ Semantic changes in the ReferenceHelper behavior Index: ant/project/manifest.mf =================================================================== RCS file: /shared/data/ccvs/repository/ant/project/manifest.mf,v retrieving revision 1.17 retrieving revision 1.17.12.1 diff -u -r1.17 -r1.17.12.1 --- ant/project/manifest.mf 12 Dec 2005 15:37:33 -0000 1.17 +++ ant/project/manifest.mf 15 Jun 2006 20:38:20 -0000 1.17.12.1 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.project.ant/1 -OpenIDE-Module-Specification-Version: 1.13 +OpenIDE-Module-Specification-Version: 1.14 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/project/ant/Bundle.properties OpenIDE-Module-Install: org/netbeans/modules/project/ant/AntProjectModule.class Index: ant/project/src/org/netbeans/spi/project/support/ant/ProjectProperties.java =================================================================== RCS file: /shared/data/ccvs/repository/ant/project/src/org/netbeans/spi/project/support/ant/ProjectProperties.java,v retrieving revision 1.14 retrieving revision 1.14.22.1 diff -u -r1.14 -r1.14.22.1 --- ant/project/src/org/netbeans/spi/project/support/ant/ProjectProperties.java 18 Oct 2005 18:10:51 -0000 1.14 +++ ant/project/src/org/netbeans/spi/project/support/ant/ProjectProperties.java 14 Jun 2006 23:46:19 -0000 1.14.22.1 @@ -13,8 +13,6 @@ package org.netbeans.spi.project.support.ant; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -397,7 +395,8 @@ getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH), } ); - PropertyProvider globalProperties = new UserPropertiesProvider(findUserPropertiesFile); + PropertyProvider globalProperties = PropertyUtils.userPropertiesProvider(findUserPropertiesFile, + "user.properties.file", FileUtil.toFile(helper.getProjectDirectory())); // NOI18N standardPropertyEvaluator = PropertyUtils.sequentialPropertyEvaluator( getStockPropertyPreprovider(), new PropertyProvider[] { @@ -408,35 +407,6 @@ ); } return standardPropertyEvaluator; - } - private PropertyProvider computeDelegate(PropertyEvaluator findUserPropertiesFile) { - String userPropertiesFile = findUserPropertiesFile.getProperty("user.properties.file"); // NOI18N - if (userPropertiesFile != null) { - // Have some defined global properties file, so read it and listen to changes in it. - File f = helper.resolveFile(userPropertiesFile); - if (f.equals(PropertyUtils.userBuildProperties())) { - // Just to share the cache. - return PropertyUtils.globalPropertyProvider(); - } else { - return PropertyUtils.propertiesFilePropertyProvider(f); - } - } else { - // Use the in-IDE default. - return PropertyUtils.globalPropertyProvider(); - } - } - private final class UserPropertiesProvider extends PropertyUtils.DelegatingPropertyProvider implements PropertyChangeListener { - private final PropertyEvaluator findUserPropertiesFile; - public UserPropertiesProvider(PropertyEvaluator findUserPropertiesFile) { - super(computeDelegate(findUserPropertiesFile)); - this.findUserPropertiesFile = findUserPropertiesFile; - findUserPropertiesFile.addPropertyChangeListener(this); - } - public void propertyChange(PropertyChangeEvent ev) { - if ("user.properties.file".equals(ev.getPropertyName())) { // NOI18N - setDelegate(computeDelegate(findUserPropertiesFile)); - } - } } } Index: ant/project/src/org/netbeans/spi/project/support/ant/PropertyUtils.java =================================================================== RCS file: /shared/data/ccvs/repository/ant/project/src/org/netbeans/spi/project/support/ant/PropertyUtils.java,v retrieving revision 1.33 retrieving revision 1.33.12.2 diff -u -r1.33 -r1.33.12.2 --- ant/project/src/org/netbeans/spi/project/support/ant/PropertyUtils.java 20 Feb 2006 20:07:31 -0000 1.33 +++ ant/project/src/org/netbeans/spi/project/support/ant/PropertyUtils.java 15 Jun 2006 20:38:19 -0000 1.33.12.2 @@ -706,6 +706,55 @@ public static PropertyEvaluator sequentialPropertyEvaluator(PropertyProvider preprovider, PropertyProvider[] providers) { return new SequentialPropertyEvaluator(preprovider, providers); } + + /** + * Creates a property provider similar to {@link #globalPropertyProvider} + * but which can use a different global properties file. + * If a specific file is pointed to, that is loaded; otherwise behaves like {@link #globalPropertyProvider}. + * Permits behavior similar to command-line Ant where not erroneous, but using the IDE's + * default global properties for projects which do not yet have this property registered. + * @param findUserPropertiesFile an evaluator in which to look up propertyName + * @param propertyName a property pointing to the global properties file (typically "user.properties.file") + * @param basedir a base directory to use when resolving the path to the global properties file, if relative + * @return a provider of global properties + * @since org.netbeans.modules.project.ant/1 1.14 + */ + public static PropertyProvider userPropertiesProvider(PropertyEvaluator findUserPropertiesFile, String propertyName, File basedir) { + return new UserPropertiesProvider(findUserPropertiesFile, propertyName, basedir); + } + private static final class UserPropertiesProvider extends DelegatingPropertyProvider implements PropertyChangeListener { + private final PropertyEvaluator findUserPropertiesFile; + private final String propertyName; + private final File basedir; + public UserPropertiesProvider(PropertyEvaluator findUserPropertiesFile, String propertyName, File basedir) { + super(computeDelegate(findUserPropertiesFile, propertyName, basedir)); + this.findUserPropertiesFile = findUserPropertiesFile; + this.propertyName = propertyName; + this.basedir = basedir; + findUserPropertiesFile.addPropertyChangeListener(this); + } + public void propertyChange(PropertyChangeEvent ev) { + if (propertyName.equals(ev.getPropertyName())) { + setDelegate(computeDelegate(findUserPropertiesFile, propertyName, basedir)); + } + } + private static PropertyProvider computeDelegate(PropertyEvaluator findUserPropertiesFile, String propertyName, File basedir) { + String userPropertiesFile = findUserPropertiesFile.getProperty(propertyName); + if (userPropertiesFile != null) { + // Have some defined global properties file, so read it and listen to changes in it. + File f = PropertyUtils.resolveFile(basedir, userPropertiesFile); + if (f.equals(PropertyUtils.userBuildProperties())) { + // Just to share the cache. + return PropertyUtils.globalPropertyProvider(); + } else { + return PropertyUtils.propertiesFilePropertyProvider(f); + } + } else { + // Use the in-IDE default. + return PropertyUtils.globalPropertyProvider(); + } + } + } private static final class SequentialPropertyEvaluator implements PropertyEvaluator, ChangeListener { @@ -858,19 +907,34 @@ /** * Property provider that delegates to another source. - * Currently attaches a strong listener to it. + * Useful, for example, when conditionally loading from one or another properties file. + * @since org.netbeans.modules.project.ant/1 1.14 */ - static abstract class DelegatingPropertyProvider implements PropertyProvider, ChangeListener { + public static abstract class DelegatingPropertyProvider implements PropertyProvider { private PropertyProvider delegate; private final List/**/ listeners = new ArrayList(); + private final ChangeListener strongListener = new ChangeListener() { + public void stateChanged(ChangeEvent e) { + //System.err.println("DPP: change from current provider " + delegate); + fireChange(); + } + }; private ChangeListener weakListener = null; // #50572: must be weak - + + /** + * Initialize the proxy. + * @param delegate the initial delegate to use + */ protected DelegatingPropertyProvider(PropertyProvider delegate) { assert delegate != null; setDelegate(delegate); } + /** + * Change the current delegate (firing changes as well). + * @param delegate the initial delegate to use + */ protected final void setDelegate(PropertyProvider delegate) { if (delegate == this.delegate) { return; @@ -880,7 +944,7 @@ this.delegate.removeChangeListener(weakListener); } this.delegate = delegate; - weakListener = WeakListeners.change(this, delegate); + weakListener = WeakListeners.change(strongListener, delegate); delegate.addChangeListener(weakListener); fireChange(); } @@ -912,11 +976,6 @@ } } - public final void stateChanged(ChangeEvent changeEvent) { - //System.err.println("DPP: change from current provider " + delegate); - fireChange(); - } - } } Index: ant/project/test/unit/src/org/netbeans/spi/project/support/ant/PropertyUtilsTest.java =================================================================== RCS file: /shared/data/ccvs/repository/ant/project/test/unit/src/org/netbeans/spi/project/support/ant/PropertyUtilsTest.java,v retrieving revision 1.19 retrieving revision 1.19.42.1 diff -u -r1.19 -r1.19.42.1 --- ant/project/test/unit/src/org/netbeans/spi/project/support/ant/PropertyUtilsTest.java 3 Aug 2005 00:03:01 -0000 1.19 +++ ant/project/test/unit/src/org/netbeans/spi/project/support/ant/PropertyUtilsTest.java 14 Jun 2006 23:46:20 -0000 1.19.42.1 @@ -557,7 +557,6 @@ } public void testDelegatingPropertyProvider() throws Exception { - // Used only by ProjectProperties, not publically, but still worth testing. TestMutablePropertyProvider mpp = new TestMutablePropertyProvider(new HashMap()); DPP dpp = new DPP(mpp); AntBasedTestUtil.TestCL l = new AntBasedTestUtil.TestCL(); Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/Bundle.properties =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/Bundle.properties,v retrieving revision 1.27 retrieving revision 1.27.2.1 diff -u -r1.27 -r1.27.2.1 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/Bundle.properties 30 May 2006 14:52:52 -0000 1.27 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/Bundle.properties 14 Jun 2006 18:36:21 -0000 1.27.2.1 @@ -69,3 +69,5 @@ MSG_OldProjectMetadata=The project is not of the current version. CopyLibs=CopyLibs Task + +J2SEConfigurationProvider.default.label= Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProvider.java =================================================================== RCS file: java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProvider.java diff -N java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProvider.java 15 Jun 2006 03:35:13 -0000 1.1.2.6 @@ -0,0 +1,244 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.java.j2seproject; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.InputStream; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.modules.java.j2seproject.ui.customizer.CustomizerProviderImpl; +import org.netbeans.modules.java.j2seproject.ui.customizer.J2SECompositePanelProvider; +import org.netbeans.spi.project.ProjectConfiguration; +import org.netbeans.spi.project.ProjectConfigurationProvider; +import org.netbeans.spi.project.support.ant.EditableProperties; +import org.openide.filesystems.FileChangeAdapter; +import org.openide.filesystems.FileChangeListener; +import org.openide.filesystems.FileEvent; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileRenameEvent; +import org.openide.filesystems.FileUtil; +import org.openide.util.Mutex; +import org.openide.util.MutexException; +import org.openide.util.NbBundle; +import org.openide.util.Utilities; + +/** + * Manages configurations for a Java SE project. + * @author Jesse Glick + */ +final class J2SEConfigurationProvider implements ProjectConfigurationProvider { + + /** + * Ant property name for active config. + */ + public static final String PROP_CONFIG = "config"; // NOI18N + /** + * Ant property file which specified active config. + */ + public static final String CONFIG_PROPS_PATH = "nbproject/private/config.properties"; // NOI18N + + private static final class Config implements ProjectConfiguration { + /** file basename, or null for default config */ + public final String name; + private final String displayName; + public Config(String name, String displayName) { + this.name = name; + this.displayName = displayName; + } + public String getDisplayName() { + return displayName; + } + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + public boolean equals(Object o) { + return (o instanceof Config) && Utilities.compareObjects(name, ((Config) o).name); + } + public String toString() { + return "J2SEConfigurationProvider.Config[" + name + "," + displayName + "]"; // NOI18N + } + } + + private static final ProjectConfiguration DEFAULT = new Config(null, + NbBundle.getMessage(J2SEConfigurationProvider.class, "J2SEConfigurationProvider.default.label")); + + private final J2SEProject p; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private final FileChangeListener fcl = new FileChangeAdapter() { + public void fileFolderCreated(FileEvent fe) { + update(); + } + public void fileDataCreated(FileEvent fe) { + update(); + } + public void fileDeleted(FileEvent fe) { + update(); + } + public void fileRenamed(FileRenameEvent fe) { + update(); + } + private void update() { + Set/**/ oldConfigs = configs != null ? configs.keySet() : Collections.emptySet(); + configDir = p.getProjectDirectory().getFileObject("nbproject/configs"); // NOI18N + if (configDir != null) { + configDir.removeFileChangeListener(fclWeak); + configDir.addFileChangeListener(fclWeak); + } + calculateConfigs(); + Set/**/ newConfigs = configs.keySet(); + if (!oldConfigs.equals(newConfigs)) { + pcs.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATIONS, null, null); + // XXX also fire PROP_ACTIVE_CONFIGURATION? + } + } + }; + private final FileChangeListener fclWeak; + private FileObject configDir; + private Map/**/ configs; + + public J2SEConfigurationProvider(J2SEProject p) { + this.p = p; + fclWeak = FileUtil.weakFileChangeListener(fcl, null); + FileObject nbp = p.getProjectDirectory().getFileObject("nbproject"); // NOI18N + if (nbp != null) { + nbp.addFileChangeListener(fclWeak); + configDir = nbp.getFileObject("configs"); // NOI18N + if (configDir != null) { + configDir.addFileChangeListener(fclWeak); + } + } + p.evaluator().addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + if (PROP_CONFIG.equals(evt.getPropertyName())) { + pcs.firePropertyChange(PROP_CONFIGURATION_ACTIVE, null, null); + } + } + }); + } + + private void calculateConfigs() { + configs = new HashMap(); + if (configDir != null) { + FileObject[] kids = configDir.getChildren(); + for (int i = 0; i < kids.length; i++) { + if (!kids[i].hasExt("properties")) { + continue; + } + try { + InputStream is = kids[i].getInputStream(); + try { + Properties p = new Properties(); + p.load(is); + String name = kids[i].getName(); + String label = p.getProperty("$label"); // NOI18N + configs.put(name, new Config(name, label != null ? label : name)); + } finally { + is.close(); + } + } catch (IOException x) { + Logger.getLogger(J2SEConfigurationProvider.class.getName()).log(Level.INFO, null, x); + } + } + } + } + + public Collection/**/ getConfigurations() { + calculateConfigs(); + List/**/ l = new ArrayList(); + l.addAll(configs.values()); + Collections.sort(l, new Comparator() { + Collator c = Collator.getInstance(); + public int compare(Object o1, Object o2) { + return c.compare(((ProjectConfiguration) o1).getDisplayName(), ((ProjectConfiguration) o2).getDisplayName()); + } + }); + l.add(0, DEFAULT); + return l; + } + + public ProjectConfiguration getActiveConfiguration() { + calculateConfigs(); + String config = p.evaluator().getProperty(PROP_CONFIG); + if (config != null && configs.containsKey(config)) { + return (ProjectConfiguration) configs.get(config); + } else { + return DEFAULT; + } + } + + public void setActiveConfiguration(ProjectConfiguration configuration) throws IllegalArgumentException, IOException { + if (!(configuration instanceof Config)) { + throw new IllegalArgumentException(); + } + Config c = (Config) configuration; + if (c != DEFAULT && !configs.values().contains(c)) { + throw new IllegalArgumentException(); + } + final String n = c.name; + try { + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + public Object run() throws IOException { + EditableProperties ep = p.getAntProjectHelper().getProperties(CONFIG_PROPS_PATH); + if (Utilities.compareObjects(n, ep.getProperty(PROP_CONFIG))) { + return null; + } + if (n != null) { + ep.setProperty(PROP_CONFIG, n); + } else { + ep.remove(PROP_CONFIG); + } + p.getAntProjectHelper().putProperties(CONFIG_PROPS_PATH, ep); + pcs.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE, null, null); + ProjectManager.getDefault().saveProject(p); + assert p.getProjectDirectory().getFileObject(CONFIG_PROPS_PATH) != null; + return null; + } + }); + } catch (MutexException x) { + throw (IOException) x.getException(); + } + } + + public boolean hasCustomizer() { + return true; + } + + public void customize() { + CustomizerProviderImpl cust = (CustomizerProviderImpl) p.getLookup().lookup(CustomizerProviderImpl.class); + cust.showCustomizer(J2SECompositePanelProvider.RUN); + } + + public void addPropertyChangeListener(PropertyChangeListener lst) { + pcs.addPropertyChangeListener(lst); + } + + public void removePropertyChangeListener(PropertyChangeListener lst) { + pcs.removePropertyChangeListener(lst); + } + +} Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java,v retrieving revision 1.61 retrieving revision 1.61.4.2 diff -u -r1.61 -r1.61.4.2 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java 22 May 2006 15:09:32 -0000 1.61 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java 14 Jun 2006 23:46:19 -0000 1.61.4.2 @@ -13,10 +13,12 @@ package org.netbeans.modules.java.j2seproject; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.io.IOException; +import java.util.Collections; import javax.swing.Icon; import javax.swing.ImageIcon; import org.netbeans.api.java.classpath.ClassPath; @@ -25,8 +27,6 @@ import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectInformation; import org.netbeans.api.project.ProjectManager; -import org.netbeans.api.project.SourceGroup; -import org.netbeans.api.project.Sources; import org.netbeans.api.project.ant.AntArtifact; import org.netbeans.modules.java.j2seproject.classpath.ClassPathProviderImpl; import org.netbeans.modules.java.j2seproject.classpath.J2SEProjectClassPathExtender; @@ -53,6 +53,7 @@ import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; import org.netbeans.spi.project.support.ant.ProjectXmlSavedHook; import org.netbeans.spi.project.support.ant.PropertyEvaluator; +import org.netbeans.spi.project.support.ant.PropertyProvider; import org.netbeans.spi.project.support.ant.PropertyUtils; import org.netbeans.spi.project.support.ant.ReferenceHelper; import org.netbeans.spi.project.ui.PrivilegedTemplates; @@ -60,6 +61,7 @@ import org.netbeans.spi.project.ui.RecommendedTemplates; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; import org.openide.util.Lookup; import org.openide.util.Mutex; import org.openide.util.Utilities; @@ -120,9 +122,54 @@ } private PropertyEvaluator createEvaluator() { - // XXX might need to use a custom evaluator to handle active platform substitutions... TBD // It is currently safe to not use the UpdateHelper for PropertyEvaluator; UH.getProperties() delegates to APH - return helper.getStandardPropertyEvaluator(); + // Adapted from APH.getStandardPropertyEvaluator (delegates to ProjectProperties): + PropertyEvaluator baseEval1 = PropertyUtils.sequentialPropertyEvaluator( + helper.getStockPropertyPreprovider(), + new PropertyProvider[] { + helper.getPropertyProvider(J2SEConfigurationProvider.CONFIG_PROPS_PATH), + }); + PropertyEvaluator baseEval2 = PropertyUtils.sequentialPropertyEvaluator( + helper.getStockPropertyPreprovider(), + new PropertyProvider[] { + helper.getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH), + }); + return PropertyUtils.sequentialPropertyEvaluator( + helper.getStockPropertyPreprovider(), + new PropertyProvider[] { + helper.getPropertyProvider(J2SEConfigurationProvider.CONFIG_PROPS_PATH), + new ConfigPropertyProvider(baseEval1, "nbproject/private/configs", helper), // NOI18N + helper.getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH), + PropertyUtils.userPropertiesProvider(baseEval2, + "user.properties.file", FileUtil.toFile(getProjectDirectory())), // NOI18N + new ConfigPropertyProvider(baseEval1, "nbproject/configs", helper), // NOI18N + helper.getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH), + }); + } + private static final class ConfigPropertyProvider extends PropertyUtils.DelegatingPropertyProvider implements PropertyChangeListener { + private final PropertyEvaluator baseEval; + private final String prefix; + private final AntProjectHelper helper; + public ConfigPropertyProvider(PropertyEvaluator baseEval, String prefix, AntProjectHelper helper) { + super(computeDelegate(baseEval, prefix, helper)); + this.baseEval = baseEval; + this.prefix = prefix; + this.helper = helper; + baseEval.addPropertyChangeListener(this); + } + public void propertyChange(PropertyChangeEvent ev) { + if (J2SEConfigurationProvider.PROP_CONFIG.equals(ev.getPropertyName())) { + setDelegate(computeDelegate(baseEval, prefix, helper)); + } + } + private static PropertyProvider computeDelegate(PropertyEvaluator baseEval, String prefix, AntProjectHelper helper) { + String config = baseEval.getProperty(J2SEConfigurationProvider.PROP_CONFIG); + if (config != null) { + return helper.getPropertyProvider(prefix + "/" + config + ".properties"); // NOI18N + } else { + return PropertyUtils.fixedPropertyProvider(Collections.emptyMap()); + } + } } PropertyEvaluator evaluator() { @@ -173,6 +220,7 @@ cpMod, this, // never cast an externally obtained Project to J2SEProject - use lookup instead new J2SEProjectOperations(this), + new J2SEConfigurationProvider(this), new J2SEProjectWebServicesSupportProvider() }); } Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/resources/build-impl.xsl =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/resources/build-impl.xsl,v retrieving revision 1.74 retrieving revision 1.74.2.2 diff -u -r1.74 -r1.74.2.2 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/resources/build-impl.xsl 8 Jun 2006 22:37:54 -0000 1.74 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/resources/build-impl.xsl 15 Jun 2006 00:09:23 -0000 1.74.2.2 @@ -71,6 +71,8 @@ -pre-init + + @@ -85,6 +87,7 @@ -pre-init,-init-private,-init-user + Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java,v retrieving revision 1.17 retrieving revision 1.17.14.1 diff -u -r1.17 -r1.17.14.1 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java 5 Dec 2005 15:18:08 -0000 1.17 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java 14 Jun 2006 18:36:22 -0000 1.17.14.1 @@ -503,6 +503,7 @@ actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_RUN, bundle.getString("LBL_RunAction_Name"), null)); // NOI18N actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_DEBUG, bundle.getString("LBL_DebugAction_Name"), null)); // NOI18N actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_TEST, bundle.getString("LBL_TestAction_Name"), null)); // NOI18N + actions.add(CommonProjectActions.setProjectConfigurationAction()); actions.add(null); actions.add(CommonProjectActions.setAsMainProjectAction()); actions.add(CommonProjectActions.openSubprojectsAction()); Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/Bundle.properties =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/Bundle.properties,v retrieving revision 1.80 retrieving revision 1.80.6.2 diff -u -r1.80 -r1.80.6.2 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/Bundle.properties 25 Apr 2006 12:17:26 -0000 1.80 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/Bundle.properties 15 Jun 2006 03:35:12 -0000 1.80.6.2 @@ -479,3 +479,10 @@ TXT_ModifiedTitle=Edit Project Properties MSG_CustomizerLibraries_CompileCpMessage=Compile-time libraries are propagated to all library categories. + +CustomizerRun.configLabel=&Profile\: +CustomizerRun.configNew=&New... +CustomizerRun.configDelete=&Delete +CustomizerRun.default= +CustomizerRun.input.prompt=Profile Name: +CustomizerRun.input.title=Create New Profile Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.form =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.form,v retrieving revision 1.12 retrieving revision 1.12.68.1 diff -u -r1.12 -r1.12.68.1 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.form 23 Mar 2005 13:07:37 -0000 1.12 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.form 15 Jun 2006 01:14:16 -0000 1.12.68.1 @@ -3,6 +3,7 @@
+ @@ -11,191 +12,291 @@ - - - - - - - - - - - - + - + - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.java =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.java,v retrieving revision 1.20 retrieving revision 1.20.68.4 diff -u -r1.20 -r1.20.68.4 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.java 23 Mar 2005 13:07:37 -0000 1.20 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/CustomizerRun.java 15 Jun 2006 19:56:09 -0000 1.20.68.4 @@ -13,49 +13,134 @@ package org.netbeans.modules.java.j2seproject.ui.customizer; +import java.awt.Component; import java.awt.Dialog; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.io.File; +import java.text.Collator; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListCellRenderer; import javax.swing.JButton; import javax.swing.JFileChooser; +import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import org.netbeans.api.project.Project; import org.netbeans.modules.java.j2seproject.J2SEProject; import org.netbeans.modules.java.j2seproject.SourceRoots; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; import org.openide.awt.MouseUtils; -import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; - -/** - * - * @author phrebejk - */ public class CustomizerRun extends JPanel implements HelpCtx.Provider { private J2SEProject project; + private JTextField[] data; + private String[] keys; + private Map/*|null>*/ configs; + J2SEProjectProperties uiProperties; + public CustomizerRun( J2SEProjectProperties uiProperties ) { + this.uiProperties = uiProperties; initComponents(); this.project = uiProperties.getProject(); - jTextFieldMainClass.setDocument( uiProperties.MAIN_CLASS_MODEL ); - jTextFieldArgs.setDocument( uiProperties.APPLICATION_ARGS_MODEL ); - jTextVMOptions.setDocument( uiProperties.RUN_JVM_ARGS_MODEL ); - jTextWorkingDirectory.setDocument( uiProperties.RUN_WORK_DIR_MODEL ); - + configs = uiProperties.RUN_CONFIGS; + + data = new JTextField[] { + jTextFieldMainClass, + jTextFieldArgs, + jTextVMOptions, + jTextWorkingDirectory, + }; + keys = new String[] { + J2SEProjectProperties.MAIN_CLASS, + J2SEProjectProperties.APPLICATION_ARGS, + J2SEProjectProperties.RUN_JVM_ARGS, + J2SEProjectProperties.RUN_WORK_DIR, + }; + assert data.length == keys.length; + + configChanged(uiProperties.activeConfig); + + configCombo.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String config = (String) value; + String label; + if (config == null) { + // uninitialized? + label = null; + } else if (config.length() > 0) { + Map m = (Map) configs.get(config); + label = m != null ? (String) m.get("$label") : /* temporary? */ null; + if (label == null) { + label = config; + } + } else { + label = NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.default"); + } + return super.getListCellRendererComponent(list, label, index, isSelected, cellHasFocus); + } + }); + + for (int i = 0; i < data.length; i++) { + final JTextField field = data[i]; + final String prop = keys[i]; + field.getDocument().addDocumentListener(new DocumentListener() { + Font basefont = field.getFont(); + Font boldfont = basefont.deriveFont(Font.BOLD); + { + updateFont(); + } + public void insertUpdate(DocumentEvent e) { + changed(); + } + public void removeUpdate(DocumentEvent e) { + changed(); + } + public void changedUpdate(DocumentEvent e) {} + void changed() { + String config = (String) configCombo.getSelectedItem(); + if (config.length() == 0) { + config = null; + } + String v = field.getText(); + if (v != null && config != null && v.equals(((Map) configs.get(null)).get(prop))) { + // default value, do not store as such + v = null; + } + ((Map) configs.get(config)).put(prop, v); + updateFont(); + } + void updateFont() { + String v = field.getText(); + String config = (String) configCombo.getSelectedItem(); + if (config.length() == 0) { + config = null; + } + field.setFont(config != null && v != null && !v.equals(((Map) configs.get(null)).get(prop)) ? boldfont : basefont); + } + }); + } + jButtonMainClass.addActionListener( new MainClassListener( project.getSourceRoots(), jTextFieldMainClass ) ); } @@ -72,6 +157,13 @@ private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; + configSep = new javax.swing.JSeparator(); + configPanel = new javax.swing.JPanel(); + configLabel = new javax.swing.JLabel(); + configCombo = new javax.swing.JComboBox(); + configNew = new javax.swing.JButton(); + configDel = new javax.swing.JButton(); + mainPanel = new javax.swing.JPanel(); jLabelMainClass = new javax.swing.JLabel(); jTextFieldMainClass = new javax.swing.JTextField(); jButtonMainClass = new javax.swing.JButton(); @@ -86,50 +178,113 @@ setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 0, 6, 0); + add(configSep, gridBagConstraints); + + configPanel.setLayout(new java.awt.GridBagLayout()); + + configLabel.setLabelFor(configCombo); + org.openide.awt.Mnemonics.setLocalizedText(configLabel, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.configLabel")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0); + configPanel.add(configLabel, gridBagConstraints); + + configCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "" })); + configCombo.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + configComboActionPerformed(evt); + } + }); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(2, 6, 2, 0); + configPanel.add(configCombo, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(configNew, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.configNew")); // NOI18N + configNew.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + configNewActionPerformed(evt); + } + }); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(2, 6, 2, 0); + configPanel.add(configNew, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(configDel, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.configDelete")); // NOI18N + configDel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + configDelActionPerformed(evt); + } + }); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(2, 6, 2, 0); + configPanel.add(configDel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 0, 6, 0); + add(configPanel, gridBagConstraints); + + mainPanel.setLayout(new java.awt.GridBagLayout()); + jLabelMainClass.setLabelFor(jTextFieldMainClass); - org.openide.awt.Mnemonics.setLocalizedText(jLabelMainClass, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_MainClass_JLabel")); + org.openide.awt.Mnemonics.setLocalizedText(jLabelMainClass, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_MainClass_JLabel")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); - add(jLabelMainClass, gridBagConstraints); + mainPanel.add(jLabelMainClass, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 12, 5, 0); - add(jTextFieldMainClass, gridBagConstraints); - jTextFieldMainClass.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(CustomizerRun.class).getString("AD_jTextFieldMainClass")); + mainPanel.add(jTextFieldMainClass, gridBagConstraints); + jTextFieldMainClass.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(CustomizerRun.class).getString("AD_jTextFieldMainClass")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jButtonMainClass, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_MainClass_JButton")); + org.openide.awt.Mnemonics.setLocalizedText(jButtonMainClass, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_MainClass_JButton")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 6, 5, 0); - add(jButtonMainClass, gridBagConstraints); - jButtonMainClass.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(CustomizerRun.class).getString("AD_jButtonMainClass")); + mainPanel.add(jButtonMainClass, gridBagConstraints); + jButtonMainClass.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(CustomizerRun.class).getString("AD_jButtonMainClass")); // NOI18N jLabelArgs.setLabelFor(jTextFieldArgs); - org.openide.awt.Mnemonics.setLocalizedText(jLabelArgs, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_Args_JLabel")); + org.openide.awt.Mnemonics.setLocalizedText(jLabelArgs, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_Args_JLabel")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0); - add(jLabelArgs, gridBagConstraints); + mainPanel.add(jLabelArgs, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 12, 12, 0); - add(jTextFieldArgs, gridBagConstraints); - jTextFieldArgs.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(CustomizerRun.class).getString("AD_jTextFieldArgs")); + mainPanel.add(jTextFieldArgs, gridBagConstraints); + jTextFieldArgs.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(CustomizerRun.class).getString("AD_jTextFieldArgs")); // NOI18N jLabelWorkingDirectory.setLabelFor(jTextWorkingDirectory); - org.openide.awt.Mnemonics.setLocalizedText(jLabelWorkingDirectory, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_Working_Directory")); + org.openide.awt.Mnemonics.setLocalizedText(jLabelWorkingDirectory, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_Working_Directory")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); - add(jLabelWorkingDirectory, gridBagConstraints); + mainPanel.add(jLabelWorkingDirectory, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 2; @@ -137,10 +292,11 @@ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 12, 5, 0); - add(jTextWorkingDirectory, gridBagConstraints); - jTextWorkingDirectory.getAccessibleContext().setAccessibleDescription(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/j2seproject/ui/customizer/Bundle").getString("AD_CustomizeRun_Run_Working_Directory ")); + mainPanel.add(jTextWorkingDirectory, gridBagConstraints); + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/netbeans/modules/java/j2seproject/ui/customizer/Bundle"); // NOI18N + jTextWorkingDirectory.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_CustomizeRun_Run_Working_Directory ")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jButtonWorkingDirectoryBrowse, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_Working_Directory_Browse")); + org.openide.awt.Mnemonics.setLocalizedText(jButtonWorkingDirectoryBrowse, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_Working_Directory_Browse")); // NOI18N jButtonWorkingDirectoryBrowse.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonWorkingDirectoryBrowseActionPerformed(evt); @@ -152,25 +308,25 @@ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 6, 5, 0); - add(jButtonWorkingDirectoryBrowse, gridBagConstraints); - jButtonWorkingDirectoryBrowse.getAccessibleContext().setAccessibleDescription(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/j2seproject/ui/customizer/Bundle").getString("AD_CustomizeRun_Run_Working_Directory_Browse")); + mainPanel.add(jButtonWorkingDirectoryBrowse, gridBagConstraints); + jButtonWorkingDirectoryBrowse.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_CustomizeRun_Run_Working_Directory_Browse")); // NOI18N jLabelVMOptions.setLabelFor(jTextVMOptions); - org.openide.awt.Mnemonics.setLocalizedText(jLabelVMOptions, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_VM_Options")); + org.openide.awt.Mnemonics.setLocalizedText(jLabelVMOptions, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_VM_Options")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); - add(jLabelVMOptions, gridBagConstraints); + mainPanel.add(jLabelVMOptions, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0); - add(jTextVMOptions, gridBagConstraints); - jTextVMOptions.getAccessibleContext().setAccessibleDescription(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/j2seproject/ui/customizer/Bundle").getString("AD_CustomizeRun_Run_VM_Options")); + mainPanel.add(jTextVMOptions, gridBagConstraints); + jTextVMOptions.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_CustomizeRun_Run_VM_Options")); // NOI18N jLabelVMOptionsExample.setLabelFor(jTextFieldMainClass); - org.openide.awt.Mnemonics.setLocalizedText(jLabelVMOptionsExample, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_VM_Options_Example")); + org.openide.awt.Mnemonics.setLocalizedText(jLabelVMOptionsExample, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "LBL_CustomizeRun_Run_VM_Options_Example")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 4; @@ -179,11 +335,59 @@ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weighty = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 12, 12, 0); - add(jLabelVMOptionsExample, gridBagConstraints); - jLabelVMOptionsExample.getAccessibleContext().setAccessibleDescription(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/j2seproject/ui/customizer/Bundle").getString("LBL_CustomizeRun_Run_VM_Options_Example")); + mainPanel.add(jLabelVMOptionsExample, gridBagConstraints); + jLabelVMOptionsExample.getAccessibleContext().setAccessibleDescription(bundle.getString("LBL_CustomizeRun_Run_VM_Options_Example")); // NOI18N - } - // //GEN-END:initComponents + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(6, 0, 6, 0); + add(mainPanel, gridBagConstraints); + + }// //GEN-END:initComponents + + private void configDelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configDelActionPerformed + String config = (String) configCombo.getSelectedItem(); + assert config != null; + configs.put(config, null); + configChanged(null); + uiProperties.activeConfig = null; + }//GEN-LAST:event_configDelActionPerformed + + private void configNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configNewActionPerformed + NotifyDescriptor.InputLine d = new NotifyDescriptor.InputLine( + NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.input.prompt"), + NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.input.title")); + if (DialogDisplayer.getDefault().notify(d) != NotifyDescriptor.OK_OPTION) { + return; + } + String name = d.getInputText(); + String config = name.replaceAll("[^a-zA-Z0-9_.-]", "_"); // NOI18N + if (configs.containsKey(config)) { + // XXX complain? + return; + } + Map m = new HashMap(); + if (!name.equals(config)) { + m.put("$label", name); // NOI18N + } + configs.put(config, m); + configChanged(config); + uiProperties.activeConfig = config; + }//GEN-LAST:event_configNewActionPerformed + + private void configComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configComboActionPerformed + String config = (String) configCombo.getSelectedItem(); + if (config.length() == 0) { + config = null; + } + configChanged(config); + uiProperties.activeConfig = config; + }//GEN-LAST:event_configComboActionPerformed private void jButtonWorkingDirectoryBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonWorkingDirectoryBrowseActionPerformed JFileChooser chooser = new JFileChooser(); @@ -202,9 +406,58 @@ jTextWorkingDirectory.setText(file.getAbsolutePath()); } }//GEN-LAST:event_jButtonWorkingDirectoryBrowseActionPerformed + + private void configChanged(String activeConfig) { + DefaultComboBoxModel model = new DefaultComboBoxModel(); + model.addElement(""); + SortedSet alphaConfigs = new TreeSet(new Comparator() { + Collator coll = Collator.getInstance(); + public int compare(Object o1, Object o2) { + return coll.compare(label(o1), label(o2)); + } + private String label(Object o) { + String c = (String) o; + Map m = (Map) configs.get(c); + String label = (String) m.get("$label"); // NOI18N + return label != null ? label : c; + } + }); + Iterator it = configs.keySet().iterator(); + while (it.hasNext()) { + String config = (String) it.next(); + if (config != null && configs.get(config) != null) { + alphaConfigs.add(config); + } + } + it = alphaConfigs.iterator(); + while (it.hasNext()) { + model.addElement(it.next()); + } + configCombo.setModel(model); + configCombo.setSelectedItem(activeConfig != null ? activeConfig : ""); + Map m = (Map) configs.get(activeConfig); + Map def = (Map) configs.get(null); + if (m != null) { + for (int i = 0; i < data.length; i++) { + String v = (String) m.get(keys[i]); + if (v == null) { + // display default value + v = (String) def.get(keys[i]); + } + data[i].setText(v); + } + } // else ?? + configDel.setEnabled(activeConfig != null); + } // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JComboBox configCombo; + private javax.swing.JButton configDel; + private javax.swing.JLabel configLabel; + private javax.swing.JButton configNew; + private javax.swing.JPanel configPanel; + private javax.swing.JSeparator configSep; private javax.swing.JButton jButtonMainClass; private javax.swing.JButton jButtonWorkingDirectoryBrowse; private javax.swing.JLabel jLabelArgs; @@ -216,6 +469,7 @@ private javax.swing.JTextField jTextFieldMainClass; private javax.swing.JTextField jTextVMOptions; private javax.swing.JTextField jTextWorkingDirectory; + private javax.swing.JPanel mainPanel; // End of variables declaration//GEN-END:variables Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SECompositePanelProvider.java =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SECompositePanelProvider.java,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SECompositePanelProvider.java 25 Apr 2006 12:17:26 -0000 1.1 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SECompositePanelProvider.java 14 Jun 2006 18:36:20 -0000 1.1.6.1 @@ -30,9 +30,6 @@ * @author mkleint */ public class J2SECompositePanelProvider implements ProjectCustomizer.CompositeCategoryProvider { - // Names of categories - private static final String BUILD_CATEGORY = "BuildCategory"; - private static final String RUN_CATEGORY = "RunCategory"; private static final String SOURCES = "Sources"; static final String LIBRARIES = "Libraries"; @@ -41,7 +38,7 @@ // private static final String BUILD_TESTS = "BuildTests"; private static final String JAR = "Jar"; private static final String JAVADOC = "Javadoc"; - private static final String RUN = "Run"; + public static final String RUN = "Run"; // private static final String RUN_TESTS = "RunTests"; private static final String WEBSERVICECLIENTS = "WebServiceClients"; Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SEProjectProperties.java =================================================================== RCS file: /shared/data/ccvs/repository/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SEProjectProperties.java,v retrieving revision 1.57 retrieving revision 1.57.10.3 diff -u -r1.57 -r1.57.10.3 --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SEProjectProperties.java 6 Jan 2006 14:14:08 -0000 1.57 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/J2SEProjectProperties.java 15 Jun 2006 20:20:13 -0000 1.57.10.3 @@ -20,7 +20,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.Vector; @@ -34,7 +35,6 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Document; import org.netbeans.api.project.ProjectManager; -import org.netbeans.api.queries.CollocationQuery; import org.netbeans.modules.java.j2seproject.J2SEProject; import org.netbeans.modules.java.j2seproject.J2SEProjectUtil; import org.netbeans.modules.java.j2seproject.SourceRoots; @@ -44,7 +44,6 @@ import org.netbeans.spi.project.support.ant.EditableProperties; import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; import org.netbeans.spi.project.support.ant.PropertyEvaluator; -import org.netbeans.spi.project.support.ant.PropertyUtils; import org.netbeans.spi.project.support.ant.ReferenceHelper; import org.netbeans.spi.project.support.ant.ui.StoreGroup; import org.openide.DialogDisplayer; @@ -52,10 +51,10 @@ import org.openide.NotifyDescriptor; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; -import org.openide.modules.SpecificationVersion; import org.openide.util.Mutex; import org.openide.util.MutexException; import org.openide.util.NbBundle; +import org.openide.util.Utilities; /** * @author Petr Hrebejk @@ -185,11 +184,8 @@ Document JAVADOC_ADDITIONALPARAM_MODEL; // CustomizerRun - Document MAIN_CLASS_MODEL; - Document APPLICATION_ARGS_MODEL; - Document RUN_JVM_ARGS_MODEL; - Document RUN_WORK_DIR_MODEL; - + Map/*|null>*/ RUN_CONFIGS; + String activeConfig; // CustomizerRunTest @@ -283,10 +279,8 @@ JAVADOC_ADDITIONALPARAM_MODEL = projectGroup.createStringDocument( evaluator, JAVADOC_ADDITIONALPARAM ); // CustomizerRun - MAIN_CLASS_MODEL = projectGroup.createStringDocument( evaluator, MAIN_CLASS ); - APPLICATION_ARGS_MODEL = privateGroup.createStringDocument( evaluator, APPLICATION_ARGS ); - RUN_JVM_ARGS_MODEL = projectGroup.createStringDocument( evaluator, RUN_JVM_ARGS ); - RUN_WORK_DIR_MODEL = privateGroup.createStringDocument( evaluator, RUN_WORK_DIR ); + RUN_CONFIGS = readRunConfigs(); + activeConfig = evaluator.getProperty("config"); } @@ -357,6 +351,15 @@ projectGroup.store( projectProperties ); privateGroup.store( privateProperties ); + storeRunConfigs(RUN_CONFIGS, projectProperties, privateProperties); + EditableProperties ep = updateHelper.getProperties("nbproject/private/config.properties"); + if (activeConfig == null) { + ep.remove("config"); + } else { + ep.setProperty("config", activeConfig); + } + updateHelper.putProperties("nbproject/private/config.properties", ep); + //Hotfix of the issue #70058 //Should use the StoreGroup when the StoreGroup SPI will be extended to allow false default value in ToggleButtonModel //Save javac.debug @@ -381,10 +384,6 @@ projectProperties.remove( NO_DEPENDENCIES ); // Remove the property completely if not set } - if ( getDocumentText( RUN_WORK_DIR_MODEL ).trim().equals( "" ) ) { // NOI18N - privateProperties.remove( RUN_WORK_DIR ); // Remove the property completely if not set - } - storeAdditionalProperties(projectProperties); // Store the property changes into the project @@ -458,7 +457,6 @@ changed = true; } } - File projDir = FileUtil.toFile(updateHelper.getAntProjectHelper().getProjectDirectory()); for( Iterator it = added.iterator(); it.hasNext(); ) { ClassPathSupport.Item item = (ClassPathSupport.Item)it.next(); if (item.getType() == ClassPathSupport.Item.TYPE_LIBRARY && !item.isBroken()) { @@ -547,6 +545,109 @@ JToggleButton.ToggleButtonModel bm = new JToggleButton.ToggleButtonModel(); bm.setSelected(isSelected ); return bm; + } + + /** + * A mess. + */ + private Map/*>*/ readRunConfigs() { + Map m = new HashMap(); + Map def = new HashMap(); + String[] PROPS = {MAIN_CLASS, APPLICATION_ARGS, RUN_JVM_ARGS, RUN_WORK_DIR}; + for (int i = 0; i < PROPS.length; i++) { + String v = updateHelper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH).getProperty(PROPS[i]); + if (v == null) { + v = updateHelper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(PROPS[i]); + } + if (v != null) { + def.put(PROPS[i], v); + } + } + m.put(null, def); + FileObject configs = project.getProjectDirectory().getFileObject("nbproject/configs"); + if (configs != null) { + FileObject[] kids = configs.getChildren(); + for (int i = 0; i < kids.length; i++) { + if (!kids[i].hasExt("properties")) { + continue; + } + m.put(kids[i].getName(), new HashMap(updateHelper.getProperties(FileUtil.getRelativePath(project.getProjectDirectory(), kids[i])))); + } + } + configs = project.getProjectDirectory().getFileObject("nbproject/private/configs"); + if (configs != null) { + FileObject[] kids = configs.getChildren(); + for (int i = 0; i < kids.length; i++) { + if (!kids[i].hasExt("properties")) { + continue; + } + Map c = (Map) m.get(kids[i].getName()); + if (c == null) { + continue; + } + c.putAll(new HashMap(updateHelper.getProperties(FileUtil.getRelativePath(project.getProjectDirectory(), kids[i])))); + } + } + //System.err.println("readRunConfigs: " + m); + return m; + } + + /** + * A royal mess. + */ + private void storeRunConfigs(Map/*|null>*/ configs, + EditableProperties projectProperties, EditableProperties privateProperties) throws IOException { + //System.err.println("storeRunConfigs: " + configs); + Map def = (Map) configs.get(null); + String[] PROPS = {MAIN_CLASS, APPLICATION_ARGS, RUN_JVM_ARGS, RUN_WORK_DIR}; + for (int i = 0; i < PROPS.length; i++) { + String prop = PROPS[i]; + String v = (String) def.get(prop); + EditableProperties ep = (prop.equals(APPLICATION_ARGS) || prop.equals(RUN_WORK_DIR)) ? + privateProperties : projectProperties; + if (!Utilities.compareObjects(v, ep.getProperty(prop))) { + if (v != null && v.length() > 0) { + ep.setProperty(prop, v); + } else { + ep.remove(prop); + } + } + } + Iterator it = configs.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = (Entry) it.next(); + String config = (String) entry.getKey(); + if (config == null) { + continue; + } + String sharedPath = "nbproject/configs/" + config + ".properties"; // NOI18N + String privatePath = "nbproject/private/configs/" + config + ".properties"; // NOI18N + Map c = (Map) entry.getValue(); + if (c == null) { + updateHelper.putProperties(sharedPath, null); + updateHelper.putProperties(privatePath, null); + continue; + } + Iterator it2 = c.entrySet().iterator(); + while (it2.hasNext()) { + Map.Entry entry2 = (Entry) it2.next(); + String prop = (String) entry2.getKey(); + String v = (String) entry2.getValue(); + String path = (prop.equals(APPLICATION_ARGS) || prop.equals(RUN_WORK_DIR)) ? + privatePath : sharedPath; + EditableProperties ep = updateHelper.getProperties(path); + if (!Utilities.compareObjects(v, ep.getProperty(prop))) { + if (v != null && v.length() > 0) { + ep.setProperty(prop, v); + } else { + ep.remove(prop); + } + updateHelper.putProperties(path, ep); + } + } + // Make sure the definition file is always created, even if it is empty. + updateHelper.putProperties(sharedPath, updateHelper.getProperties(sharedPath)); + } } } Index: java/j2seproject/test/unit/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProviderTest.java =================================================================== RCS file: java/j2seproject/test/unit/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProviderTest.java diff -N java/j2seproject/test/unit/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProviderTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/j2seproject/test/unit/src/org/netbeans/modules/java/j2seproject/J2SEConfigurationProviderTest.java 15 Jun 2006 03:35:13 -0000 1.1.2.4 @@ -0,0 +1,199 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.java.j2seproject; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.junit.NbTestCase; +import org.netbeans.spi.project.ProjectConfiguration; +import org.netbeans.spi.project.ProjectConfigurationProvider; +import org.netbeans.spi.project.support.ant.EditableProperties; +import org.netbeans.spi.project.support.ant.PropertyEvaluator; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +/** + * @author Jesse Glick + */ +public class J2SEConfigurationProviderTest extends NbTestCase { + + public J2SEConfigurationProviderTest(String name) { + super(name); + } + + private FileObject d; + private J2SEProject p; + private ProjectConfigurationProvider cp; + + protected void setUp() throws Exception { + super.setUp(); + clearWorkDir(); + d = J2SEProjectGenerator.createProject(getWorkDir(), "test", null, null).getProjectDirectory(); + p = (J2SEProject) ProjectManager.getDefault().findProject(d); + cp = (ProjectConfigurationProvider) p.getLookup().lookup(ProjectConfigurationProvider.class); + assertNotNull(cp); + Locale.setDefault(Locale.US); + } + + public void testInitialState() throws Exception { + assertEquals(1, cp.getConfigurations().size()); + assertNotNull(cp.getActiveConfiguration()); + assertEquals(cp.getActiveConfiguration(), cp.getConfigurations().iterator().next()); + assertEquals("", cp.getActiveConfiguration().getDisplayName()); + assertTrue(cp.hasCustomizer()); + } + + public void testConfigurations() throws Exception { + TestListener l = new TestListener(); + cp.addPropertyChangeListener(l); + Properties p = new Properties(); + p.setProperty("$label", "Debug"); + write(p, d, "nbproject/configs/debug.properties"); + p = new Properties(); + p.setProperty("$label", "Release"); + write(p, d, "nbproject/configs/release.properties"); + write(new Properties(), d, "nbproject/configs/misc.properties"); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATIONS), l.events()); + List/**/ configs = new ArrayList(cp.getConfigurations()); + assertEquals(4, configs.size()); + assertEquals("", ((ProjectConfiguration) configs.get(0)).getDisplayName()); + assertEquals("Debug", ((ProjectConfiguration) configs.get(1)).getDisplayName()); + assertEquals("misc", ((ProjectConfiguration) configs.get(2)).getDisplayName()); + assertEquals("Release", ((ProjectConfiguration) configs.get(3)).getDisplayName()); + assertEquals(Collections.emptySet(), l.events()); + d.getFileObject("nbproject/configs/debug.properties").delete(); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATIONS), l.events()); + configs = new ArrayList(cp.getConfigurations()); + assertEquals(3, configs.size()); + d.getFileObject("nbproject/configs").delete(); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATIONS), l.events()); + configs = new ArrayList(cp.getConfigurations()); + assertEquals(1, configs.size()); + write(new Properties(), d, "nbproject/configs/misc.properties"); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATIONS), l.events()); + configs = new ArrayList(cp.getConfigurations()); + assertEquals(2, configs.size()); + } + + public void testActiveConfiguration() throws Exception { + write(new Properties(), d, "nbproject/configs/debug.properties"); + write(new Properties(), d, "nbproject/configs/release.properties"); + TestListener l = new TestListener(); + cp.addPropertyChangeListener(l); + ProjectConfiguration def = cp.getActiveConfiguration(); + assertEquals("", def.getDisplayName()); + List/**/ configs = new ArrayList(cp.getConfigurations()); + assertEquals(3, configs.size()); + ProjectConfiguration c = (ProjectConfiguration) configs.get(2); + assertEquals("release", c.getDisplayName()); + cp.setActiveConfiguration(c); + assertEquals(c, cp.getActiveConfiguration()); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE), l.events()); + cp.setActiveConfiguration(c); + assertEquals(c, cp.getActiveConfiguration()); + assertEquals(Collections.emptySet(), l.events()); + cp.setActiveConfiguration(def); + assertEquals(def, cp.getActiveConfiguration()); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE), l.events()); + try { + cp.setActiveConfiguration(null); + fail(); + } catch (IllegalArgumentException x) {/*OK*/} + assertEquals(Collections.emptySet(), l.events()); + try { + cp.setActiveConfiguration(new ProjectConfiguration() { + public String getDisplayName() { + return "bogus"; + } + }); + fail(); + } catch (IllegalArgumentException x) {/*OK*/} + assertEquals(Collections.emptySet(), l.events()); + EditableProperties ep = new EditableProperties(); + ep.setProperty("config", "debug"); + p.getAntProjectHelper().putProperties("nbproject/private/config.properties", ep); + assertEquals("debug", cp.getActiveConfiguration().getDisplayName()); + assertEquals(Collections.singleton(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE), l.events()); + } + + public void testEvaluator() throws Exception { + PropertyEvaluator eval = p.evaluator(); + TestListener l = new TestListener(); + eval.addPropertyChangeListener(l); + Properties p = new Properties(); + p.setProperty("debug", "true"); + write(p, d, "nbproject/configs/debug.properties"); + p = new Properties(); + p.setProperty("debug", "false"); + write(p, d, "nbproject/configs/release.properties"); + p = new Properties(); + p.setProperty("more", "stuff"); + write(p, d, "nbproject/private/configs/release.properties"); + List/**/ configs = new ArrayList(cp.getConfigurations()); + assertEquals(3, configs.size()); + ProjectConfiguration c = (ProjectConfiguration) configs.get(1); + assertEquals("debug", c.getDisplayName()); + cp.setActiveConfiguration(c); + assertEquals(new HashSet(Arrays.asList(new String[] {"config", "debug"})), l.events()); + assertEquals("debug", eval.getProperty("config")); + assertEquals("true", eval.getProperty("debug")); + assertEquals(null, eval.getProperty("more")); + c = (ProjectConfiguration) configs.get(2); + assertEquals("release", c.getDisplayName()); + cp.setActiveConfiguration(c); + assertEquals(new HashSet(Arrays.asList(new String[] {"config", "debug", "more"})), l.events()); + assertEquals("release", eval.getProperty("config")); + assertEquals("false", eval.getProperty("debug")); + assertEquals("stuff", eval.getProperty("more")); + c = (ProjectConfiguration) configs.get(0); + assertEquals("", c.getDisplayName()); + cp.setActiveConfiguration(c); + assertEquals(new HashSet(Arrays.asList(new String[] {"config", "debug", "more"})), l.events()); + assertEquals(null, eval.getProperty("config")); + assertEquals(null, eval.getProperty("debug")); + assertEquals(null, eval.getProperty("more")); + // XXX test nbproject/private/configs/*.properties + } + + private void write(Properties p, FileObject d, String path) throws IOException { + FileObject f = FileUtil.createData(d, path); + OutputStream os = f.getOutputStream(); + p.store(os, null); + os.close(); + } + + private static final class TestListener implements PropertyChangeListener { + private Set/**/ events = new HashSet(); + public void propertyChange(PropertyChangeEvent evt) { + events.add(evt.getPropertyName()); + } + public Set/**/ events() { + Set/**/ copy = events; + events = new HashSet(); + return copy; + } + } + +}