/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch 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 fr.pilato.elasticsearch.tools;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * list resources available from the classpath @ *
 * From http://stackoverflow.com/questions/3923129/get-a-list-of-resources-from-classpath-directory
 * http://www.uofr.net/~greg/java/get-resource-listing.html
 * @author Greg Briggs
 */
public class ResourceList {
    private static final Logger logger = LoggerFactory.getLogger(ResourceList.class);
    private static final String[] NO_RESOURCE = {};

    /**
     * List directory contents for a resource folder. Not recursive.
     * This is basically a brute-force implementation.
     * Works for regular files and also JARs.
     *
     * @param root Should end with "/", but not start with one.
     * @return Just the name of each member item, not the full paths.
     * @throws URISyntaxException When a file:// resource can not be converted to URL
     * @throws IOException When a URL can not be decoded
     */
    public static String[] getResources(final String root) throws URISyntaxException, IOException {
        logger.trace("Reading classpath resources from {}", root);
        URL dirURL = ResourceList.class.getClassLoader().getResource(root);
        if (dirURL != null && dirURL.getProtocol().equals("file")) {
            /* A file path: easy enough */
            logger.trace("found a file resource: {}", dirURL);
            String[] resources = new File(dirURL.toURI()).list();
            Arrays.sort(resources);
            return resources;
        }

        if (dirURL == null) {
            /*
             * In case of a jar file, we can't actually find a directory.
             * Have to assume the same jar as clazz.
             */
            String me = ResourceList.class.getName().replace(".", "/")+".class";
            dirURL = ResourceList.class.getClassLoader().getResource(me);
        }

        if (dirURL == null) {
            throw new RuntimeException("can not get resource file " + root);
        }

        if (dirURL.getProtocol().equals("jar")) {
            /* A JAR path */
            logger.trace("found a jar file resource: {}", dirURL);
            String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
            JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
            Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
            Set<String> result = new HashSet<>(); //avoid duplicates in case it is a subdirectory
            while(entries.hasMoreElements()) {
                String name = entries.nextElement().getName();
                if (name.startsWith(root)) { //filter according to the path
                    String entry = name.substring(root.length());
                    int checkSubdir = entry.indexOf("/");
                    if (checkSubdir >= 0) {
                        // if it is a subdirectory, we just return the directory name
                        entry = entry.substring(0, checkSubdir);
                    }
                    result.add(entry);
                }
            }
            String[] resources = result.toArray(new String[result.size()]);
            Arrays.sort(resources);
            return resources;
        }

        // Resource does not exist. We can return an empty list
        logger.trace("did not find any resource. returning empty array");
        return NO_RESOURCE;
    }
}

@@ -3371,16 +3371,119 @@
         
+Set%3CString%3E result = new HashSet%3C%3E(); //avoid duplicates in case it is a subdirectory%0A            try (
 JarFile 
@@ -3536,18 +3536,24 @@
 UTF-8%22))
-;%0A
+) %7B%0A    
         
@@ -3638,102 +3638,8 @@
     
-        Set%3CString%3E result = new HashSet%3C%3E(); //avoid duplicates in case it is a subdirectory%0A
     
@@ -3693,24 +3693,28 @@
             
+  
+  
 String name 
@@ -3744,24 +3744,28 @@
 .getName();%0A
+    
             
@@ -3844,24 +3844,28 @@
             
+  
+  
 String entry
@@ -3918,16 +3918,20 @@
         
+    
 int chec
@@ -3976,24 +3976,28 @@
             
+  
+  
 if (checkSub
@@ -4004,24 +4004,28 @@
 dir %3E= 0) %7B%0A
+    
             
@@ -4122,16 +4122,20 @@
         
+  
+  
 entry = 
@@ -4179,34 +4179,42 @@
                 
-%7D%0A
+    %7D%0A    
                 
@@ -4236,16 +4236,38 @@
 entry);%0A
+                    %7D%0A
         

Fix resource leak: jarfile resource is never closed