From de69efbffbf5d30ae8649a111f851ece52695a8a Mon Sep 17 00:00:00 2001 From: Attila Kelemen Date: Fri, 31 Aug 2012 21:42:49 +0200 Subject: [PATCH] Project properties are now automatically saved whenever a property changes making its use less error prone. --- .../gradle/project/NbGradleProject.java | 26 ----------- .../persistent/PropertiesPersister.java | 4 +- .../persistent/XmlPropertiesPersister.java | 23 +++++----- .../properties/AbstractProjectProperties.java | 17 +++++++ .../project/properties/GradleCustomizer.java | 1 - .../properties/MemProjectProperties.java | 4 +- .../project/properties/ProjectProperties.java | 3 ++ .../properties/ProjectPropertiesManager.java | 44 ++++++++++++++++++- .../properties/ProjectPropertiesProxy.java | 2 +- 9 files changed, 78 insertions(+), 46 deletions(-) create mode 100644 src/org/netbeans/gradle/project/properties/AbstractProjectProperties.java diff --git a/src/org/netbeans/gradle/project/NbGradleProject.java b/src/org/netbeans/gradle/project/NbGradleProject.java index 8cb51f83..1927fa0f 100644 --- a/src/org/netbeans/gradle/project/NbGradleProject.java +++ b/src/org/netbeans/gradle/project/NbGradleProject.java @@ -19,8 +19,6 @@ import org.netbeans.gradle.project.model.GradleModelLoader; import org.netbeans.gradle.project.model.ModelRetrievedListener; import org.netbeans.gradle.project.model.NbGradleModel; -import org.netbeans.gradle.project.persistent.PropertiesPersister; -import org.netbeans.gradle.project.persistent.XmlPropertiesPersister; import org.netbeans.gradle.project.properties.GradleCustomizer; import org.netbeans.gradle.project.properties.ProjectProperties; import org.netbeans.gradle.project.properties.ProjectPropertiesProxy; @@ -60,13 +58,11 @@ public final class NbGradleProject implements Project { private final AtomicBoolean hasModelBeenLoaded; private final AtomicReference currentModelRef; private final ProjectProperties properties; - private final PropertiesPersister propertiesPersister; private final ProjectInfoManager projectInfoManager; private final AtomicReference loadErrorRef; private volatile boolean loadedAtLeastOnce; - private boolean saveOnLoad; // access from the EDT public NbGradleProject(FileObject projectDir, ProjectState state) throws IOException { this.projectDir = projectDir; @@ -74,7 +70,6 @@ public NbGradleProject(FileObject projectDir, ProjectState state) throws IOExcep this.lookupRef = new AtomicReference(null); this.properties = new ProjectPropertiesProxy(this); this.projectInfoManager = new ProjectInfoManager(); - this.propertiesPersister = new XmlPropertiesPersister(this); this.hasModelBeenLoaded = new AtomicBoolean(false); this.loadErrorRef = new AtomicReference(null); @@ -83,7 +78,6 @@ public NbGradleProject(FileObject projectDir, ProjectState state) throws IOExcep this.cpProvider = new GradleClassPathProvider(this); this.loadedAtLeastOnce = false; - this.saveOnLoad = false; } private ProjectInfoRef getLoadErrorRef() { @@ -124,19 +118,6 @@ private void reloadProject(boolean mayUseCache) { loadProject(false, mayUseCache); } - public void saveProperties() { - if (!SwingUtilities.isEventDispatchThread()) { - throw new IllegalStateException("This method may only be called from the EDT."); - } - - if (loadedAtLeastOnce) { - propertiesPersister.save(properties); - } - else { - saveOnLoad = true; - } - } - public boolean hasLoadedProject() { return loadedAtLeastOnce; } @@ -146,13 +127,6 @@ private void onModelChange() { try { loadedAtLeastOnce = true; - if (saveOnLoad) { - saveOnLoad = false; - propertiesPersister.save(properties); - } - else { - propertiesPersister.load(properties); - } modelChanges.fireChange(); } finally { GradleCacheSourceForBinaryQuery.notifyCacheChange(); diff --git a/src/org/netbeans/gradle/project/persistent/PropertiesPersister.java b/src/org/netbeans/gradle/project/persistent/PropertiesPersister.java index 11ac291a..18ddec36 100644 --- a/src/org/netbeans/gradle/project/persistent/PropertiesPersister.java +++ b/src/org/netbeans/gradle/project/persistent/PropertiesPersister.java @@ -5,6 +5,6 @@ public interface PropertiesPersister { // These methods may only be called from the EDT - public void save(ProjectProperties properties); - public void load(ProjectProperties properties); + public void save(ProjectProperties properties, Runnable onDone); + public void load(ProjectProperties properties, Runnable onDone); } diff --git a/src/org/netbeans/gradle/project/persistent/XmlPropertiesPersister.java b/src/org/netbeans/gradle/project/persistent/XmlPropertiesPersister.java index 55219708..aac050ec 100644 --- a/src/org/netbeans/gradle/project/persistent/XmlPropertiesPersister.java +++ b/src/org/netbeans/gradle/project/persistent/XmlPropertiesPersister.java @@ -46,20 +46,11 @@ public final class XmlPropertiesPersister implements PropertiesPersister { private static final String PLATFORM_NODE = "target-platform"; private static final String SOURCE_LEVEL_NODE = "source-level"; - private final NbGradleProject project; private final File propertiesFile; - public XmlPropertiesPersister(NbGradleProject project) { - if (project == null) throw new NullPointerException("project"); - - this.project = project; - this.propertiesFile = null; - } - public XmlPropertiesPersister(File propertiesFile) { if (propertiesFile == null) throw new NullPointerException("propertiesFile"); - this.project = null; this.propertiesFile = propertiesFile; } @@ -82,7 +73,7 @@ public static File getFileForProject(NbGradleProject project) { } private File getPropertyFile() throws IOException { - return propertiesFile != null ? propertiesFile : getFileForProject(project); + return propertiesFile; } private void checkEDT() { @@ -204,7 +195,7 @@ private void saveDocument(Document document) throws TransformerException, IOExce } @Override - public void save(ProjectProperties properties) { + public void save(ProjectProperties properties, final Runnable onDone) { checkEDT(); final Charset sourceEncoding = properties.getSourceEncoding().getValue(); @@ -249,13 +240,17 @@ public void run() { LOGGER.log(Level.INFO, "Failed to save the properties.", ex); } catch (TransformerException ex) { LOGGER.log(Level.INFO, "Failed to save the properties.", ex); + } finally { + if (onDone != null) { + onDone.run(); + } } } }); } @Override - public void load(final ProjectProperties properties) { + public void load(final ProjectProperties properties, final Runnable onDone) { checkEDT(); // We must listen for changes, so that we do not overwrite properties @@ -322,6 +317,10 @@ public void run() { if (sourceEncoding != null && !sourceEncodingChanged.hasChanged()) { properties.getSourceEncoding().setValue(sourceEncoding); } + + if (onDone != null) { + onDone.run(); + } } }); diff --git a/src/org/netbeans/gradle/project/properties/AbstractProjectProperties.java b/src/org/netbeans/gradle/project/properties/AbstractProjectProperties.java new file mode 100644 index 00000000..d531a082 --- /dev/null +++ b/src/org/netbeans/gradle/project/properties/AbstractProjectProperties.java @@ -0,0 +1,17 @@ +package org.netbeans.gradle.project.properties; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collection; + +public abstract class AbstractProjectProperties implements ProjectProperties { + public static final Charset DEFAULT_SOURCE_ENCODING = Charset.forName("UTF-8"); + + @Override + public final Collection> getAllProperties() { + return Arrays.>asList( + getPlatform(), + getSourceEncoding(), + getSourceLevel()); + } +} diff --git a/src/org/netbeans/gradle/project/properties/GradleCustomizer.java b/src/org/netbeans/gradle/project/properties/GradleCustomizer.java index 8e77cebf..00460d06 100644 --- a/src/org/netbeans/gradle/project/properties/GradleCustomizer.java +++ b/src/org/netbeans/gradle/project/properties/GradleCustomizer.java @@ -32,7 +32,6 @@ public void showCustomizer() { dlg.setVisible(true); if (DialogDescriptor.OK_OPTION == dlgDescriptor.getValue()) { panel.updateProperties(project.getProperties()); - project.saveProperties(); } } } diff --git a/src/org/netbeans/gradle/project/properties/MemProjectProperties.java b/src/org/netbeans/gradle/project/properties/MemProjectProperties.java index 07711762..099630c4 100644 --- a/src/org/netbeans/gradle/project/properties/MemProjectProperties.java +++ b/src/org/netbeans/gradle/project/properties/MemProjectProperties.java @@ -5,9 +5,7 @@ import org.netbeans.api.java.platform.JavaPlatform; import org.openide.modules.SpecificationVersion; -public final class MemProjectProperties implements ProjectProperties { - public static final Charset DEFAULT_SOURCE_ENCODING = Charset.forName("UTF-8"); - +public final class MemProjectProperties extends AbstractProjectProperties { private final MutableProperty sourceLevel; private final MutableProperty platform; private final MutableProperty sourceEncoding; diff --git a/src/org/netbeans/gradle/project/properties/ProjectProperties.java b/src/org/netbeans/gradle/project/properties/ProjectProperties.java index c40eec53..651d4e65 100644 --- a/src/org/netbeans/gradle/project/properties/ProjectProperties.java +++ b/src/org/netbeans/gradle/project/properties/ProjectProperties.java @@ -1,10 +1,13 @@ package org.netbeans.gradle.project.properties; import java.nio.charset.Charset; +import java.util.Collection; import org.netbeans.api.java.platform.JavaPlatform; public interface ProjectProperties { public MutableProperty getSourceLevel(); public MutableProperty getPlatform(); public MutableProperty getSourceEncoding(); + + public Collection> getAllProperties(); } diff --git a/src/org/netbeans/gradle/project/properties/ProjectPropertiesManager.java b/src/org/netbeans/gradle/project/properties/ProjectPropertiesManager.java index 6b54eccf..f61d5584 100644 --- a/src/org/netbeans/gradle/project/properties/ProjectPropertiesManager.java +++ b/src/org/netbeans/gradle/project/properties/ProjectPropertiesManager.java @@ -2,9 +2,12 @@ import java.io.File; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import org.netbeans.gradle.project.persistent.PropertiesPersister; import org.netbeans.gradle.project.persistent.XmlPropertiesPersister; @@ -13,6 +16,40 @@ public final class ProjectPropertiesManager { private static final Map PROPERTIES = new WeakValueHashMap(); + private static void saveIfRequired( + final AtomicBoolean saveQueued, + final ProjectProperties properties, + final PropertiesPersister persister) { + + if (saveQueued.compareAndSet(false, true)) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + saveQueued.set(false); + persister.save(properties, null); + } + }); + } + } + + private static void setSaveOnChange( + final ProjectProperties properties, + final PropertiesPersister persister) { + + final AtomicBoolean saveQueued = new AtomicBoolean(false); + + ChangeListener saveIfRequiredTask = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + saveIfRequired(saveQueued, properties, persister); + } + }; + + for (MutableProperty property: properties.getAllProperties()) { + property.addChangeListener(saveIfRequiredTask); + } + } + public static ProjectProperties getProperties(File propertiesFile) { if (propertiesFile == null) throw new NullPointerException("propertiesFile"); @@ -32,7 +69,12 @@ public static ProjectProperties getProperties(File propertiesFile) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - persister.load(newProperties); + persister.load(newProperties, new Runnable() { + @Override + public void run() { + setSaveOnChange(newProperties, persister); + } + }); } }); diff --git a/src/org/netbeans/gradle/project/properties/ProjectPropertiesProxy.java b/src/org/netbeans/gradle/project/properties/ProjectPropertiesProxy.java index 99890e90..8eebf51b 100644 --- a/src/org/netbeans/gradle/project/properties/ProjectPropertiesProxy.java +++ b/src/org/netbeans/gradle/project/properties/ProjectPropertiesProxy.java @@ -17,7 +17,7 @@ import org.netbeans.gradle.project.persistent.XmlPropertiesPersister; import org.openide.util.ChangeSupport; -public final class ProjectPropertiesProxy implements ProjectProperties { +public final class ProjectPropertiesProxy extends AbstractProjectProperties { private static final Logger LOGGER = Logger.getLogger(ProjectPropertiesProxy.class.getName()); private final NbGradleProject project;