/*
 * Copyright (C) 2012-present the original author or authors.
 *
 * Licensed 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.pf4j;

import org.pf4j.processor.LegacyExtensionStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * All extensions declared in a plugin are indexed in a file {@code META-INF/extensions.idx}.
 * This class lookup extensions in all extensions index files {@code META-INF/extensions.idx}.
 *
 * @author Decebal Suiu
 */
public class LegacyExtensionFinder extends AbstractExtensionFinder {

    private static final Logger log = LoggerFactory.getLogger(LegacyExtensionFinder.class);

    public LegacyExtensionFinder(PluginManager pluginManager) {
        super(pluginManager);
    }

    @Override
    public Map<String, Set<String>> readClasspathStorages() {
        log.debug("Reading extensions storages from classpath");
        Map<String, Set<String>> result = new LinkedHashMap<>();

        Set<String> bucket = new HashSet<>();
        try {
            Enumeration<URL> urls = getClass().getClassLoader().getResources(getExtensionsResource());
            if (urls.hasMoreElements()) {
                collectExtensions(urls, bucket);
            } else {
                log.debug("Cannot find '{}'", getExtensionsResource());
            }

            debugExtensions(bucket);

            result.put(null, bucket);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

        return result;
    }

    @Override
    public Map<String, Set<String>> readPluginsStorages() {
        log.debug("Reading extensions storages from plugins");
        Map<String, Set<String>> result = new LinkedHashMap<>();

        List<PluginWrapper> plugins = pluginManager.getPlugins();
        for (PluginWrapper plugin : plugins) {
            String pluginId = plugin.getDescriptor().getPluginId();
            log.debug("Reading extensions storage from plugin '{}'", pluginId);
            Set<String> bucket = new HashSet<>();

            try {
                Enumeration<URL> urls = ((PluginClassLoader) plugin.getPluginClassLoader()).findResources(getExtensionsResource());
                if (urls.hasMoreElements()) {
                    collectExtensions(urls, bucket);
                } else {
                    log.debug("Cannot find '{}'", getExtensionsResource());
                }

                debugExtensions(bucket);

                result.put(pluginId, bucket);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }

        return result;
    }

    private void collectExtensions(Enumeration<URL> urls, Set<String> bucket) throws IOException {
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            log.debug("Read '{}'", url.getFile());
            try (Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)) {
                LegacyExtensionStorage.read(reader, bucket);
            }
        }
    }

    private static String getExtensionsResource() {
        return LegacyExtensionStorage.EXTENSIONS_RESOURCE;
    }

}

@@ -771,24 +771,52 @@
 OException;%0A
+import java.io.InputStream;%0A
 import java.
@@ -2882,35 +2882,86 @@
     
-Enumeration%3CURL%3E urls = ((P
+log.debug(%22Read '%7B%7D'%22, getExtensionsResource());%0A                ClassLoader p
 lugi
@@ -2972,17 +2972,18 @@
 ssLoader
-)
+ =
  plugin.
@@ -3008,23 +3008,97 @@
 er()
-).findResources
+;%0A                try (InputStream resourceStream = pluginClassLoader.getResourceAsStream
 (get
@@ -3110,34 +3110,40 @@
 sionsResource())
-;%0A
+) %7B%0A    
                 
@@ -3146,38 +3146,38 @@
     if (
-urls.hasMoreElements()
+resourceStream == null
 ) %7B%0A    
@@ -3196,41 +3196,72 @@
     
-collectExtensions(urls, bucket);%0A
+    log.debug(%22Cannot find '%7B%7D'%22, getExtensionsResource());%0A    
     
@@ -3305,40 +3305,18 @@
     
-log.debug(%22Cannot find '%7B%7D'%22, ge
+    collec
 tExt
@@ -3318,36 +3318,71 @@
 ctExtensions
-R
+(r
 esource
-());
+Stream, bucket);%0A                    %7D
 %0A           
@@ -3845,32 +3845,203 @@
 getFile());%0A    
+        collectExtensions(url.openStream(), bucket);%0A        %7D%0A    %7D%0A%0A    private void collectExtensions(InputStream inputStream, Set%3CString%3E bucket) throws IOException %7B%0A
         try (Rea
@@ -4075,32 +4075,27 @@
 mReader(
-url.open
+input
 Stream
-()
 , Standa
@@ -4111,28 +4111,24 @@
 s.UTF_8)) %7B%0A
-    
             
@@ -4172,30 +4172,16 @@
 ucket);%0A
-            %7D%0A
         

Fix FileSystemException in windows on plugin delete (#322)