0

I have created a Java project with SpringBoot and want a Get-Request to display all available shell scripts. The shell scripts are inside the package: 'scripts'.

import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

@RestController
@RequestMapping("api/overview")
public class DME {

String packageName = "de.osp.scriptrunnerbackend.script";

@GetMapping
public List<Class<?>> getClassesInPackage() {
    String path = packageName.replaceAll("\\.", File.separator);
    List<Class<?>> classes = new ArrayList<>();
    String[] classPathEntries = System.getProperty("java.class.path").split(
            System.getProperty("path.separator")
    );

    String name;
    for (String classpathEntry : classPathEntries) {
        if (classpathEntry.endsWith(".sh")) {
            File file = new File(classpathEntry);
            try {
                JarInputStream is = new JarInputStream(new FileInputStream(file));
                JarEntry entry;
                while((entry = is.getNextJarEntry()) != null) {
                    name = entry.getName();
                    if (name.endsWith(".sh")) {
                        if (name.contains(path) && name.endsWith(".sh")) {
                            String classPath = name.substring(0, entry.getName().length() - 6);
                            classPath = classPath.replaceAll("[\\|/]", ".");
                            classes.add(Class.forName(classPath));
                        }
                    }
                }
            } catch (Exception ex) {
                // Silence is gold
            }
        } else {
            try {
                File base = new File(classpathEntry + File.separatorChar + path);
                for (File file : base.listFiles()) {
                    name = file.getName();
                    if (name.endsWith(".sh")) {
                        name = name.substring(0, name.length() - 6);
                        classes.add(Class.forName(packageName + "." + name));
                    }
                }
            } catch (Exception ex) {
                // Silence is gold
            }
        }
    }

    return classes;
}

With this method i can find classes inside specific packages, but it isnt working for shell scripts. Do u know the equivalent of "java.class.path" for a shell script?

String[] classPathEntries = 
 System.getProperty("java.class.path").split(
            System.getProperty("path.separator")
    );
Volnick
  • 89
  • 8
  • 1
    What have you implemented till now? Paste your controller class. If you haven't implemented it, please implement it first. Hint: make a simple hello world controller returning hello to your request. Then, replace the code inside container to read all the files inside your directory and check the file extensions. Make a set or list and display them. You can have a POJO as well for representing each file. – KnockingHeads May 08 '21 at 18:11
  • @Ashish just one more question. What is the name ending of "shell scripts". Like for java it could be .jar, .class. – Volnick May 08 '21 at 19:01
  • 1
    @Volnick "shell script" usually implies a unix-like environment. Unix-like systems don't really care about extensions. But it's customary to use `.sh`. – Federico klez Culloca May 08 '21 at 19:04
  • @FedericoklezCulloca i edited my question. The method is working for java classes, but until now i cant find any shell scripts. Please check out the last part of my question. – Volnick May 08 '21 at 19:15

1 Answers1

0

The problem is that your springboot application cannot look it up for a file with no .java extension from a package. You do not want to compile other files, together with .java from the same package.

Instead, you want to place .sh files and others under src/main/resources. Since this is how we put these files under classpath during compiling, you can use relative paths to specify a file/files.

I just tested the solution posted here Get a list of resources from classpath directory. Here is my test code below.

 Directory of ...\src\main\resources\json

05/09/2021  01:51 PM    <DIR>          .
05/09/2021  01:51 PM    <DIR>          ..
05/09/2021  01:51 PM                 2 1.json
05/09/2021  01:51 PM                 2 2.json
               2 File(s)              4 bytes
               2 Dir(s)  39,049,281,536 bytes free

Display a list of files

    @Test
    void getResourceFiles() throws IOException {
        String path = "json";
        List<String> filenames = new ArrayList<>();

        try (
                InputStream in = getResourceAsStream(path);
                BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
            String resource;

            while ((resource = br.readLine()) != null) {
                filenames.add(resource);
            }
        }
        System.out.println(filenames);
    }

    private InputStream getResourceAsStream(String resource) {
        final InputStream in
                = getContextClassLoader().getResourceAsStream(resource);

        return in == null ? getClass().getResourceAsStream(resource) : in;
    }

    private ClassLoader getContextClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

There is the output.

[1.json, 2.json]

Read one specify file with the full file name

As soon as you have the file name, you can read it via ClassPathResource

public String getInfo() {
        String msg = "";
        InputStreamReader intput = null;
        try {
            Resource resource = new ClassPathResource("json/1.json"); // Path and file name.
            // Get the input stream. The rest would be the same as other times when you manipulate an input stream.
            intput = new InputStreamReader(resource.getInputStream());      
            BufferedReader reader = new BufferedReader(intput);
            msg=  reader.readLine();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    return msg;
}

In your case, change the path and file names accordingly.

justthink
  • 439
  • 3
  • 6