This is an automated email from the ASF dual-hosted git repository.
lkishalmi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new c43ee9b [NETBEANS-4867] Fix inconsistent Gradle SubProject Detection
(#2411)
c43ee9b is described below
commit c43ee9b5091e16ccd0adfeeb50ebaa0e45be0799
Author: Laszlo Kishalmi <[email protected]>
AuthorDate: Wed Oct 7 09:47:33 2020 -0700
[NETBEANS-4867] Fix inconsistent Gradle SubProject Detection (#2411)
* Extract disk cache implementation from GradleProjectCache
* [NETBEANS-4867] Use a distinct disk cache for Gradle subprojects
---
.../modules/gradle/GradleProjectCache.java | 158 +++------------------
.../modules/gradle/NbGradleProjectFactory.java | 8 +-
.../gradle/api/GradleBaseProjectBuilder.java | 7 +-
.../modules/gradle/cache/AbstractDiskCache.java | 156 ++++++++++++++++++++
.../modules/gradle/cache/ProjectInfoDiskCache.java | 119 ++++++++++++++++
.../modules/gradle/cache/SubProjectDiskCache.java | 134 +++++++++++++++++
.../modules/gradle/nodes/SubProjectsNode.java | 20 +--
.../gradle/nodes/SubProjectsNodeFactory.java | 16 +--
8 files changed, 452 insertions(+), 166 deletions(-)
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
b/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
index 0453456..f0f69ee 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
@@ -18,6 +18,8 @@
*/
package org.netbeans.modules.gradle;
+import org.netbeans.modules.gradle.cache.ProjectInfoDiskCache;
+import org.netbeans.modules.gradle.cache.SubProjectDiskCache;
import org.netbeans.modules.gradle.spi.GradleFiles;
import org.netbeans.modules.gradle.api.GradleBaseProject;
import org.netbeans.modules.gradle.api.NbGradleProject.Quality;
@@ -26,17 +28,10 @@ import org.netbeans.modules.gradle.api.NbProjectInfo;
import org.netbeans.modules.gradle.spi.GradleSettings;
import org.netbeans.modules.gradle.spi.ProjectInfoExtractor;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -67,8 +62,9 @@ import static org.netbeans.modules.gradle.GradleDaemon.*;
import org.netbeans.modules.gradle.api.NbGradleProject;
import org.netbeans.modules.gradle.api.execute.GradleCommandLine;
import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JLabel;
+import org.netbeans.modules.gradle.cache.AbstractDiskCache.CacheEntry;
+import
org.netbeans.modules.gradle.cache.ProjectInfoDiskCache.QualifiedProjectInfo;
import org.netbeans.modules.gradle.api.execute.RunUtils;
import org.openide.awt.Notification;
import org.openide.awt.NotificationDisplayer;
@@ -86,18 +82,12 @@ public final class GradleProjectCache {
private enum GoOnline { NEVER, ON_DEMAND, ALWAYS }
private static final Logger LOG =
Logger.getLogger(GradleProjectCache.class.getName());
- private static final String INFO_CACHE_FILE_NAME = "project-info.ser";
//NOI18N
private static final Map<File, List<Notification>> NOTIFICATIONS = new
WeakHashMap<>();
private static AtomicLong timeInLoad = new AtomicLong();
private static AtomicInteger loadedProjects = new AtomicInteger();
- private static final Map<File, Set<File>> SUB_PROJECT_DIR_CACHE = new
ConcurrentHashMap<>();
-
- // Increase this number if new info is gathered from the projects.
- private static final int COMPATIBLE_CACHE_VERSION = 15;
-
private GradleProjectCache() {
}
@@ -121,12 +111,11 @@ public final class GradleProjectCache {
GradleProject prev = project.project != null ? project.project :
fallbackProject(files);
// Try to turn to the cache
- if (!(ignoreCache || GradleSettings.getDefault().isCacheDisabled())
- && (prev.getQuality() == FALLBACK)) {
- ProjectCacheEntry cacheEntry = loadCachedProject(files);
+ if (!ignoreCache && (prev.getQuality() == FALLBACK)) {
+ CacheEntry<QualifiedProjectInfo> cacheEntry = new
ProjectInfoDiskCache(files).loadEntry();
if (cacheEntry != null) {
if (cacheEntry.isCompatible()) {
- prev = createGradleProject(cacheEntry.quality,
cacheEntry.data);
+ prev = createGradleProject(cacheEntry.getData());
if (cacheEntry.isValid()) {
updateSubDirectoryCache(prev);
return prev;
@@ -242,12 +231,13 @@ public final class GradleProjectCache {
if (SwingUtilities.isEventDispatchThread()) {
LOG.log(FINE, "Load happened on AWT event dispatcher", new
RuntimeException());
}
- GradleProject ret = createGradleProject(quality, info);
+ QualifiedProjectInfo qinfo = new QualifiedProjectInfo(quality, info);
+ GradleProject ret = createGradleProject(qinfo);
GradleArtifactStore.getDefault().processProject(ret);
if (info.getMiscOnly()) {
ret = ctx.previous;
} else {
- saveCachedProjectInfo(info, ret);
+ saveCachedProjectInfo(qinfo, ret);
}
return ret;
}
@@ -391,24 +381,7 @@ public final class GradleProjectCache {
return sb.toString();
}
- private static ProjectCacheEntry loadCachedProject(GradleFiles gf) {
- File cacheFile = new File(getCacheDir(gf), INFO_CACHE_FILE_NAME);
- ProjectCacheEntry ret = null;
- if (cacheFile.canRead()) {
- try (ObjectInputStream is = new ObjectInputStream(new
FileInputStream(cacheFile))) {
- try {
- ret = (ProjectCacheEntry) is.readObject();
- } catch (ClassNotFoundException ex) {
- LOG.log(FINE, "Invalid cache entry.", ex);
- }
- } catch (IOException ex) {
- LOG.log(FINE, "Could no load project info from " + cacheFile,
ex);
- }
- }
- return ret;
- }
-
- private static GradleProject createGradleProject(Quality quality,
NbProjectInfo info) {
+ private static GradleProject createGradleProject(QualifiedProjectInfo
info) {
Collection<? extends ProjectInfoExtractor> extractors =
Lookup.getDefault().lookupAll(ProjectInfoExtractor.class);
Map<Class, Object> results = new HashMap<>();
Set<String> problems = new LinkedHashSet<>(info.getProblems());
@@ -424,7 +397,7 @@ public final class GradleProjectCache {
}
}
- return new GradleProject(quality, problems, results.values());
+ return new GradleProject(info.getQuality(), problems,
results.values());
}
@@ -432,32 +405,16 @@ public final class GradleProjectCache {
if (gp.getQuality().atLeast(EVALUATED)) {
GradleBaseProject baseProject = gp.getBaseProject();
if (baseProject.isRoot()) {
- SUB_PROJECT_DIR_CACHE.put(baseProject.getProjectDir(), new
HashSet<File>(baseProject.getSubProjects().values()));
+ SubProjectDiskCache spCache =
SubProjectDiskCache.get(baseProject.getRootDir());
+ spCache.storeData(new
SubProjectDiskCache.SubProjectInfo(baseProject));
}
}
}
- static Boolean isKnownSubProject(File rootDir, File subProjectDir) {
- Set<File> cache = SUB_PROJECT_DIR_CACHE.get(rootDir);
- return (cache != null) ? cache.contains(subProjectDir) : null;
- }
-
- private static void saveCachedProjectInfo(NbProjectInfo data,
GradleProject gp) {
+ private static void saveCachedProjectInfo(QualifiedProjectInfo data,
GradleProject gp) {
assert gp.getQuality().betterThan(FALLBACK) : "Never attempt to cache
FALLBACK projects."; //NOi18N
- //TODO: Make it possible to handle external file set as cache.
GradleFiles gf = new GradleFiles(gp.getBaseProject().getProjectDir(),
true);
- Set<File> cacheInvalidators = new HashSet<>(gf.getProjectFiles());
- if (gf.hasWrapper()) cacheInvalidators.add(gf.getWrapperProperties());
- ProjectCacheEntry entry = new ProjectCacheEntry(new
StoredProjectInfo(data), gp, cacheInvalidators);
- File cacheFile = new File(getCacheDir(gp), INFO_CACHE_FILE_NAME);
- if (!cacheFile.exists()) {
- cacheFile.getParentFile().mkdirs();
- }
- try (ObjectOutputStream os = new ObjectOutputStream(new
FileOutputStream(cacheFile))) {
- os.writeObject(entry);
- } catch (IOException ex) {
- LOG.log(FINE, "Failed to persist project info to" + cacheFile, ex);
- }
+ new ProjectInfoDiskCache(gf).storeData(data);
}
private static GradleProject fallbackProject(GradleFiles files) {
@@ -497,7 +454,7 @@ public final class GradleProjectCache {
return dir;
}
- static final class ReloadContext {
+ private static final class ReloadContext {
final NbGradleProjectImpl project;
final GradleProject previous;
@@ -519,85 +476,4 @@ public final class GradleProjectCache {
}
}
- private static class ProjectCacheEntry implements Serializable {
-
- int version;
-
- long timestamp;
- Set<File> sourceFiles;
- Quality quality;
- NbProjectInfo data;
-
- protected ProjectCacheEntry() {
- }
-
- public ProjectCacheEntry(NbProjectInfo data, GradleProject gp,
Set<File> sourceFiles) {
- this.sourceFiles = sourceFiles;
- this.data = data;
- this.quality = gp.getQuality();
- this.timestamp = gp.getEvaluationTime();
- this.version = COMPATIBLE_CACHE_VERSION;
- }
-
- public boolean isCompatible() {
- return version == COMPATIBLE_CACHE_VERSION;
- }
-
- public boolean isValid() {
- boolean ret = isCompatible();
- if (ret && (sourceFiles != null)) {
- for (File f : sourceFiles) {
- if (!f.exists() || (f.lastModified() > timestamp)) {
- ret = false;
- break;
- }
- }
- }
- return ret;
- }
- }
-
- private static class StoredProjectInfo implements NbProjectInfo {
-
- private final Map<String, Object> info;
- private final Set<String> problems;
- private final String gradleException;
-
- public StoredProjectInfo(NbProjectInfo pinfo) {
- info = new LinkedHashMap<>(pinfo.getInfo());
- problems = new LinkedHashSet<>(pinfo.getProblems());
- gradleException = pinfo.getGradleException();
- }
-
- @Override
- public Map<String, Object> getInfo() {
- return info;
- }
-
- @Override
- public Map<String, Object> getExt() {
- return Collections.emptyMap();
- }
-
- @Override
- public Set<String> getProblems() {
- return problems;
- }
-
- @Override
- public String getGradleException() {
- return gradleException;
- }
-
- @Override
- public boolean hasException() {
- return gradleException != null;
- }
-
- @Override
- public boolean getMiscOnly() {
- return false;
- }
-
- }
}
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java
b/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java
index 8308d51..8137835 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/NbGradleProjectFactory.java
@@ -19,6 +19,7 @@
package org.netbeans.modules.gradle;
+import org.netbeans.modules.gradle.cache.SubProjectDiskCache;
import java.io.File;
import org.netbeans.modules.gradle.spi.GradleFiles;
import org.netbeans.modules.gradle.api.NbGradleProject;
@@ -66,9 +67,10 @@ public final class NbGradleProjectFactory implements
ProjectFactory2 {
}
File suspect = FileUtil.toFile(dir);
GradleFiles files = new GradleFiles(suspect);
- if (!files.isRootProject()) {
- Boolean inSubDirCache =
GradleProjectCache.isKnownSubProject(files.getRootDir(), suspect);
- return inSubDirCache != null ? inSubDirCache : files.isProject();
+ if ((files.getSettingsScript() != null) && !files.isRootProject()) {
+ SubProjectDiskCache spCache =
SubProjectDiskCache.get(files.getRootDir());
+ SubProjectDiskCache.SubProjectInfo data = spCache.loadData();
+ return data != null && data.getProjectPath(suspect) != null;
} else {
return true;
}
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
index 7cdfed9..5c2c4e5 100644
---
a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
+++
b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
@@ -91,7 +91,12 @@ class GradleBaseProjectBuilder implements
ProjectInfoExtractor.Result {
prj.license = (String) info.get("license");
prj.plugins = new TreeSet<>(createSet((Set<String>)
info.get("plugins")));
- prj.subProjects = (Map<String, File>) info.get("project_subProjects");
+ Map<String, File> rawSubprojects = (Map<String, File>)
info.get("project_subProjects");
+ Map<String, File> refinedSubprojects = (Map<String, File>)
info.get("project_subProjects");
+ for (Map.Entry<String, File> entry : rawSubprojects.entrySet()) {
+ refinedSubprojects.put(entry.getKey(),
entry.getValue().isAbsolute() ? entry.getValue() : new File(prj.rootDir,
entry.getValue().toString()));
+ }
+ prj.subProjects = Collections.unmodifiableMap(refinedSubprojects);
prj.includedBuilds = (Map<String, File>)
info.get("project_includedBuilds");
if (info.containsKey("buildClassPath")) {
prj.buildClassPath = (Set<File>) info.get("buildClassPath");
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/cache/AbstractDiskCache.java
b/extide/gradle/src/org/netbeans/modules/gradle/cache/AbstractDiskCache.java
new file mode 100644
index 0000000..06299ba
--- /dev/null
+++ b/extide/gradle/src/org/netbeans/modules/gradle/cache/AbstractDiskCache.java
@@ -0,0 +1,156 @@
+/*
+ * 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.gradle.cache;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Set;
+import static java.util.logging.Level.*;
+import java.util.logging.Logger;
+import org.netbeans.modules.gradle.spi.GradleSettings;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public abstract class AbstractDiskCache <K extends Serializable, T extends
Serializable> implements Serializable {
+
+ private static final Logger LOG =
Logger.getLogger(AbstractDiskCache.class.getName());
+
+ protected K key;
+ private boolean valid = false;
+ private transient CacheEntry<T> entry;
+
+ protected AbstractDiskCache() {}
+
+ protected AbstractDiskCache(K key) {
+ this.key = key;
+ }
+
+ public synchronized final CacheEntry<T> loadEntry() {
+ CacheEntry<T> ret = entry;
+ if (ret == null && !GradleSettings.getDefault().isCacheDisabled()) {
+ File cacheFile = cacheFile();
+ if (cacheFile.canRead()) {
+ try (ObjectInputStream is = new ObjectInputStream(new
FileInputStream(cacheFile))) {
+ ret = (CacheEntry<T>) is.readObject();
+ valid = true;
+ } catch (ClassNotFoundException | IOException ex) {
+ LOG.log(INFO, "Could no load project info from {0} due to:
{1}", new Object[]{cacheFile, ex.getMessage()});
+ cacheFile.delete();
+ }
+ }
+ entry = ret;
+ }
+ return ret;
+
+ }
+
+ public synchronized final T loadData() {
+ CacheEntry<T> e = loadEntry();
+ return e != null && e.isValid() ? e.getData() : null;
+ }
+
+ public synchronized final void storeData(T data) {
+ File cacheFile = cacheFile();
+ if (!cacheFile.exists()) {
+ cacheFile.getParentFile().mkdirs();
+ }
+ try (ObjectOutputStream os = new ObjectOutputStream(new
FileOutputStream(cacheFile))) {
+ CacheEntry e = new CacheEntryImpl(data);
+ os.writeObject(e);
+ entry = e;
+ } catch (IOException ex) {
+ LOG.log(INFO, "Failed to persist info to {0} due to {1}", new
Object[]{cacheFile, ex.getMessage()});
+ cacheFile.delete();
+ }
+ }
+
+ public synchronized final void invalidate() {
+ File cacheFile = cacheFile();
+ valid = false;
+ if (cacheFile.canRead()) {
+ cacheFile.delete();
+ }
+ }
+ protected abstract int cacheVersion();
+ protected abstract File cacheFile();
+ protected abstract Set<File> cacheInvalidators();
+
+ public interface CacheEntry <D extends Serializable> extends Serializable {
+ boolean isCompatible();
+ boolean isValid();
+ D getData();
+ }
+
+ private final class CacheEntryImpl <T extends Serializable> implements
CacheEntry<T> {
+ int version;
+
+ long timestamp;
+ Set<File> sourceFiles;
+ T data;
+
+ protected CacheEntryImpl() {
+ }
+
+ protected CacheEntryImpl(T data) {
+ timestamp = System.currentTimeMillis();
+ version = cacheVersion();
+ this.sourceFiles = cacheInvalidators();
+ this.data = data;
+ }
+
+ @Override
+ public boolean isCompatible() {
+ return version == cacheVersion();
+ }
+
+ @Override
+ public boolean isValid() {
+ boolean ret = (data != null) && isCompatible();
+ if (AbstractDiskCache.this.valid && ret && (sourceFiles != null)) {
+ for (File f : sourceFiles) {
+ if (!f.exists() || (f.lastModified() > timestamp)) {
+ ret = false;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public T getData() {
+ return data;
+ }
+
+ @Override
+ public String toString() {
+ Class dataClass = data != null ? data.getClass() : null;
+ return "CacheEntryImpl{" + "data:version=" + dataClass + ":" +
version + ", timestamp=" + new Date(timestamp) + ", sourceFiles=" + sourceFiles
+ '}';
+ }
+
+ }
+}
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
new file mode 100644
index 0000000..66b5256
--- /dev/null
+++
b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
@@ -0,0 +1,119 @@
+/*
+ * 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.gradle.cache;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import org.netbeans.modules.gradle.GradleProjectCache;
+import
org.netbeans.modules.gradle.cache.ProjectInfoDiskCache.QualifiedProjectInfo;
+import org.netbeans.modules.gradle.api.NbGradleProject.Quality;
+import org.netbeans.modules.gradle.api.NbProjectInfo;
+import org.netbeans.modules.gradle.spi.GradleFiles;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public final class ProjectInfoDiskCache extends AbstractDiskCache<GradleFiles,
QualifiedProjectInfo> {
+
+ // Increase this number if new info is gathered from the projects.
+ private static final int COMPATIBLE_CACHE_VERSION = 16;
+ private static final String INFO_CACHE_FILE_NAME = "project-info.ser";
//NOI18N
+
+ public ProjectInfoDiskCache(GradleFiles gf) {
+ super(gf);
+ }
+
+ @Override
+ protected int cacheVersion() {
+ return COMPATIBLE_CACHE_VERSION;
+ }
+
+ @Override
+ protected File cacheFile() {
+ return new File(GradleProjectCache.getCacheDir(key),
INFO_CACHE_FILE_NAME);
+ }
+
+ @Override
+ protected Set<File> cacheInvalidators() {
+ Set<File> ret = new HashSet<>(key.getProjectFiles());
+ if (key.hasWrapper()) ret.add(key.getWrapperProperties());
+ return ret;
+ }
+
+ public static final class QualifiedProjectInfo implements NbProjectInfo {
+
+ private final Quality quality;
+ private final Map<String, Object> info;
+ private final Set<String> problems;
+ private final String gradleException;
+
+ public QualifiedProjectInfo(Quality quality, NbProjectInfo pinfo) {
+ this.quality = quality;
+ info = new LinkedHashMap<>(pinfo.getInfo());
+ problems = new LinkedHashSet<>(pinfo.getProblems());
+ gradleException = pinfo.getGradleException();
+ }
+
+ @Override
+ public Map<String, Object> getInfo() {
+ return info;
+ }
+
+ @Override
+ public Map<String, Object> getExt() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Set<String> getProblems() {
+ return problems;
+ }
+
+ @Override
+ public String getGradleException() {
+ return gradleException;
+ }
+
+ @Override
+ public boolean hasException() {
+ return gradleException != null;
+ }
+
+ @Override
+ public boolean getMiscOnly() {
+ return false;
+ }
+
+ public Quality getQuality() {
+ return quality;
+ }
+
+ @Override
+ public String toString() {
+ return "QualifiedProjectInfo{" + "quality=" + quality + '}';
+ }
+
+ }
+}
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/cache/SubProjectDiskCache.java
b/extide/gradle/src/org/netbeans/modules/gradle/cache/SubProjectDiskCache.java
new file mode 100644
index 0000000..91423ac
--- /dev/null
+++
b/extide/gradle/src/org/netbeans/modules/gradle/cache/SubProjectDiskCache.java
@@ -0,0 +1,134 @@
+/*
+ * 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.gradle.cache;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import org.netbeans.modules.gradle.cache.SubProjectDiskCache.SubProjectInfo;
+import org.netbeans.modules.gradle.spi.GradleFiles;
+import org.gradle.tooling.model.GradleProject;
+import org.netbeans.modules.gradle.api.GradleBaseProject;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public class SubProjectDiskCache extends AbstractDiskCache<File,
SubProjectInfo> {
+
+ private static final String SUBPROJECT_CACHE_FILE_NAME =
".gradle/nb-cache/subprojects.ser"; //NOI18N
+ private static final int COMPATIBLE_CACHE_VERSION = 1;
+
+ private static Map<File, SubProjectDiskCache> diskCaches = new
WeakHashMap<>();
+
+ protected SubProjectDiskCache() {}
+
+ private SubProjectDiskCache(File key) {
+ super(key);
+ }
+
+ @Override
+ protected int cacheVersion() {
+ return COMPATIBLE_CACHE_VERSION;
+ }
+
+ @Override
+ protected File cacheFile() {
+ return new File(key, SUBPROJECT_CACHE_FILE_NAME);
+ }
+
+ @Override
+ protected Set<File> cacheInvalidators() {
+ return Collections.singleton(new GradleFiles(key).getSettingsScript());
+ }
+
+ public static SubProjectDiskCache get(File key) {
+ SubProjectDiskCache ret = diskCaches.get(key);
+ if (ret == null) {
+ ret = new SubProjectDiskCache(key);
+ diskCaches.put(key, ret);
+ }
+ return ret;
+ }
+
+ public static final class SubProjectInfo implements Serializable {
+ String rootProjectName;
+ Map<String, String> path2Name;
+ Map<File, String> file2Path;
+
+ protected SubProjectInfo() {}
+
+ public SubProjectInfo(GradleProject prj) {
+ assert prj.getParent() == null : "This shall be called only on a
root project!";
+ rootProjectName = prj.getName();
+ path2Name = new HashMap<>();
+ file2Path = new HashMap<>();
+ for (GradleProject child : prj.getChildren()) {
+ path2Name.put(child.getPath(), child.getName());
+ File dir = child.getProjectDirectory();
+ if (!dir.isAbsolute()) {
+ dir = new File(prj.getProjectDirectory(), dir.toString());
+ }
+ file2Path.put(dir, child.getPath());
+ }
+ }
+
+ public SubProjectInfo(GradleBaseProject gbp) {
+ assert gbp.isRoot() : "This shall be called only on a root
project!";
+ rootProjectName = gbp.getName();
+ path2Name = new HashMap<>();
+ file2Path = new HashMap<>();
+ for (Map.Entry<String, File> sprj :
gbp.getSubProjects().entrySet()) {
+ file2Path.put(sprj.getValue(), sprj.getKey());
+ path2Name.put(sprj.getKey(), sprj.getKey());
+ }
+ }
+
+ public String gerRootProjectName() {
+ return rootProjectName;
+ }
+
+ public String getProjectName(String path) {
+ return path2Name.get(path);
+ }
+
+ public String getProjectName(File dir) {
+ String path = file2Path.get(dir);
+ return path != null ? path2Name.get(path) : null;
+ }
+
+ public String getProjectPath(File dir) {
+ return file2Path.get(dir);
+ }
+
+ public boolean isSubproject(File dir) {
+ return file2Path.containsKey(dir);
+ }
+
+ @Override
+ public String toString() {
+ return "SubProjects of [" + rootProjectName + "]: " +
file2Path.keySet();
+ }
+
+ }
+}
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java
b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java
index 721cf95..b50fb52 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNode.java
@@ -30,7 +30,6 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
@@ -117,12 +116,10 @@ public class SubProjectsNode extends AbstractNode {
project = proj;
this.rootPath = rootPath;
NbGradleProject watcher = project.getProjectWatcher();
- listener = new PropertyChangeListener() {
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if
(NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) {
- refresh(false);
- }
+ listener = (PropertyChangeEvent evt) -> {
+ if
(NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) {
+ ProjectManager.getDefault().clearNonProjectCache();
+ refresh(false);
}
};
@@ -133,7 +130,7 @@ public class SubProjectsNode extends AbstractNode {
@Override
protected boolean createKeys(final List<String> paths) {
Map<String, File> subProjects =
project.getGradleProject().getBaseProject().getSubProjects();
- Set<String> components = new TreeSet<String>();
+ Set<String> components = new TreeSet<>();
Set<String> projects = new TreeSet<>();
for (String path : subProjects.keySet()) {
if (path.startsWith(rootPath)) {
@@ -228,11 +225,8 @@ public class SubProjectsNode extends AbstractNode {
final NbGradleProjectImpl[] projectsArray =
projects.toArray(new NbGradleProjectImpl[0]);
OpenProjects.getDefault().open(projectsArray, false, true);
if (projectsArray.length > 0) {
- RequestProcessor.getDefault().post(new Runnable() {
- public @Override
- void run() {
- OpenProjects.getDefault().open(projectsArray,
false, true);
- }
+ RequestProcessor.getDefault().post(() -> {
+ OpenProjects.getDefault().open(projectsArray,
false, true);
}, 500);
}
}
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java
b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java
index 6451bab..39d54ce 100644
---
a/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java
+++
b/extide/gradle/src/org/netbeans/modules/gradle/nodes/SubProjectsNodeFactory.java
@@ -24,10 +24,12 @@ import org.netbeans.modules.gradle.NbGradleProjectImpl;
import org.netbeans.modules.gradle.api.NbGradleProject;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import java.io.File;
import java.util.Collections;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import org.netbeans.api.project.Project;
+import org.netbeans.modules.gradle.GradleProject;
import org.netbeans.spi.project.ui.support.NodeFactory;
import org.netbeans.spi.project.ui.support.NodeList;
import org.openide.nodes.Node;
@@ -39,15 +41,13 @@ import org.openide.nodes.Node;
@NodeFactory.Registration(projectType = NbGradleProject.GRADLE_PROJECT_TYPE,
position = 400)
public class SubProjectsNodeFactory implements NodeFactory {
- private static final String KEY_SUBPROJECTS = "subprojects"; //NOI18N
-
@Override
public NodeList<?> createNodes(Project project) {
NbGradleProjectImpl prj =
project.getLookup().lookup(NbGradleProjectImpl.class);
return new NList(prj);
}
- private static class NList extends AbstractGradleNodeList<String>
implements PropertyChangeListener {
+ private static class NList extends AbstractGradleNodeList<GradleProject>
implements PropertyChangeListener {
private final NbGradleProjectImpl project;
@@ -63,13 +63,13 @@ public class SubProjectsNodeFactory implements NodeFactory {
}
@Override
- public List<String> keys() {
- Set<String> subProjects =
project.getGradleProject().getBaseProject().getSubProjects().keySet();
- return subProjects.isEmpty() ? Collections.<String>emptyList() :
Collections.singletonList(KEY_SUBPROJECTS);
+ public List<GradleProject> keys() {
+ Map<String, File> subProjects =
project.getGradleProject().getBaseProject().getSubProjects();
+ return subProjects.isEmpty() ?
Collections.<GradleProject>emptyList() :
Collections.singletonList(project.getGradleProject());
}
@Override
- public Node node(String key) {
+ public Node node(GradleProject key) {
return new SubProjectsNode(project);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists