jdaugherty commented on code in PR #15409:
URL: https://github.com/apache/grails-core/pull/15409#discussion_r2927448735


##########
grails-core/src/main/groovy/org/apache/grails/core/plugins/GrailsPluginDiscovery.java:
##########
@@ -0,0 +1,593 @@
+/*
+ *  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
+ *
+ *    https://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.apache.grails.core.plugins;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import groovy.lang.GroovyClassLoader;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.runtime.IOGroovyMethods;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import grails.plugins.GrailsPluginSorter;
+import grails.plugins.GrailsVersionUtils;
+import grails.plugins.PluginFilter;
+import grails.plugins.exceptions.PluginException;
+import grails.util.Metadata;
+import org.apache.grails.core.plugins.filters.PluginFilterRetriever;
+import org.grails.core.io.CachingPathMatchingResourcePatternResolver;
+import org.grails.io.support.GrailsResourceUtils;
+
+/**
+ * This class provides the canonical implementations of Grails Plugin 
Discovery.
+ *
+ * @since 7.1
+ */
+public class GrailsPluginDiscovery {
+
+    public static final String BEAN_NAME = "grailsPluginDiscovery";
+    private static final Logger LOG = 
LoggerFactory.getLogger(GrailsPluginDiscovery.class);
+
+    protected Metadata applicationMeta = Metadata.getCurrent();
+    protected Resource[] pluginResources = new Resource[0];
+    protected Class<?>[] pluginClasses = new Class[0];
+    /**
+     * plugins ordered by the load order
+     */
+    protected LinkedHashMap<String, GrailsPluginInfo> plugins;
+    /**
+     * plugins sorted by the topographical sort
+     */
+    protected List<GrailsPluginInfo> orderedPlugins;
+    /**
+     * plugins sorted by the load order
+     */
+    protected List<GrailsPluginInfo> loadOrderedPlugins;
+    protected List<GrailsPluginInfo> dynamicPlugins;
+    protected Map<String, Set<GrailsPluginInfo>> pluginToObserverMap;
+    protected List<GrailsPluginInfo> delayedLoadPlugins;
+    protected Map<String, GrailsPluginInfo> failedPlugins;
+    protected Map<GrailsPluginInfo, String[]> delayedEvictions;
+    protected PluginFilter pluginFilter;
+    protected boolean loadClasspathPlugins = true;
+    protected boolean requireClasspathPlugin = true;
+    protected final PluginFilterRetriever filterRetriever;
+
+    public GrailsPluginDiscovery() {
+        this(new PluginFilterRetriever());
+    }
+
+    public GrailsPluginDiscovery(String resourcePath) {
+        this();
+
+        PathMatchingResourcePatternResolver resolver = 
CachingPathMatchingResourcePatternResolver.INSTANCE;
+        try {
+            pluginResources = resolver.getResources(resourcePath);
+        } catch (IOException ioe) {
+            LOG.debug("Unable to load plugins for resource path {}", 
resourcePath, ioe);
+        }
+    }
+
+    public GrailsPluginDiscovery(Class<?>[] pluginClasses) {
+        this();
+        this.pluginClasses = pluginClasses;
+    }
+
+    public GrailsPluginDiscovery(String[] pluginResources) {
+        this();
+
+        PathMatchingResourcePatternResolver resolver = 
CachingPathMatchingResourcePatternResolver.INSTANCE;
+
+        List<Resource> resourceList = new ArrayList<>();
+        for (String resourcePath : pluginResources) {
+            try {
+                
resourceList.addAll(Arrays.asList(resolver.getResources(resourcePath)));
+            } catch (IOException ioe) {
+                LOG.debug("Unable to load plugins for resource path {}", 
resourcePath, ioe);
+            }
+        }
+
+        this.pluginResources = resourceList.toArray(new Resource[0]);
+    }
+
+    public GrailsPluginDiscovery(Resource[] pluginFiles) {
+        this();
+        this.pluginResources = pluginFiles;
+    }
+
+    public GrailsPluginDiscovery(PluginFilterRetriever filterRetriever) {
+        this.filterRetriever = filterRetriever;
+    }
+
+    public GrailsPluginInfo[] getDynamicPlugins() {
+        return dynamicPlugins.toArray(new GrailsPluginInfo[0]);
+    }
+
+    public Map<String, GrailsPluginInfo> getFailedPlugins() {
+        return failedPlugins;
+    }
+
+    public GrailsPluginInfo getPlugin(String pluginName, Object version, 
Environment environment) {
+        if (plugins == null) {
+            if (environment == null) {
+                throw new IllegalArgumentException("Environment must be 
provided to fetch a plugin");
+            }
+            findPlugins(environment);
+        }
+
+        GrailsPluginInfo plugin = 
plugins.get(GrailsPluginUtils.normalizePluginName(pluginName));
+        if (plugin != null && 
GrailsVersionUtils.isValidVersion(plugin.pluginVersion(), version.toString())) {
+            return plugin;
+        }
+        return null;
+    }
+
+    public boolean hasPlugin(String name) {
+        return 
plugins.containsKey(GrailsPluginUtils.normalizePluginName(name));
+    }
+
+    public GrailsPluginInfo getPlugin(String pluginName, Environment 
environment) {
+        if (plugins == null) {
+            if (environment == null) {
+                throw new IllegalArgumentException("Environment must be 
provided to fetch a plugin");
+            }
+
+            findPlugins(environment);
+        }
+
+        return plugins.get(GrailsPluginUtils.normalizePluginName(pluginName));
+    }
+
+    public Collection<GrailsPluginInfo> getPluginObservers(GrailsPluginInfo 
plugin) {
+        Objects.requireNonNull(plugin, "Argument [plugin] cannot be null");
+
+        Collection<GrailsPluginInfo> c = 
pluginToObserverMap.get(plugin.name());
+
+        // Add any wildcard observers.
+        Collection<GrailsPluginInfo> wildcardObservers = 
pluginToObserverMap.get("*");
+        if (wildcardObservers != null) {
+            if (c != null) {
+                c.addAll(wildcardObservers);
+            } else {
+                c = wildcardObservers;
+            }
+        }
+
+        if (c != null) {
+            // Make sure this plugin is not observing itself!
+            c.remove(plugin);
+            return c;
+        }
+
+        return Collections.emptySet();
+    }
+
+    public Collection<GrailsPluginInfo> getPlugins(Environment environment) {
+        return plugins == null ? findPlugins(environment).values() : 
plugins.values();
+    }
+
+    /**
+     * @return plugins ordered by a topographical sort.
+     */
+    public Collection<GrailsPluginInfo> getOrderedPlugins(Environment 
environment) {
+        if (orderedPlugins == null) {
+            findPlugins(environment);
+        }
+
+        return orderedPlugins;
+    }
+
+    /**
+     * @return the order the plugins were loaded in.
+     */
+    public Collection<GrailsPluginInfo> getLoadOrderedPlugins(Environment 
environment) {

Review Comment:
   I'm going to refactor the GrailsPluginDiscovery class so that it has a 
common interface & then we ship a default implementation.  I'm also going to 
add an init() method instead of initing on the first time this is called.  This 
way the getters can be true getters.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to