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 <laszlo.kisha...@gmail.com>
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: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to