Extract some content from jar-file downloaded with

2019-03-01 01:58发布

问题:

im trying to extract some files from a jar-file downloaded using java-webstart. below code was used to locate the jar and initiate the FileSystem

1 final ProtectionDomain domain = this.getClass().getProtectionDomain();
2 final CodeSource source = domain.getCodeSource();
3 final URL url    = source.getLocation();
4 final URI uri    = url.toURI();
5 Path jarPath = Paths.get(uri);
6
7 FileSystem fs = FileSystems.newFileSystem(jarPath, null);

This works fine when the jar-file is on a local disc, but fails at line 5 in the JWS scenario, because the

logs says: url=http://localhost:8080/myjarfile.jar

java.nio.file.FileSystemNotFoundException: Provider "http" not installed
at java.nio.file.Paths.get(Unknown Source)

If I understand JWS correctly, myjarfile.jar has been downloaded to some cache already, so implementing a FileSystemProvider for http to get some content from myjarfile.jar seems slow and complicated. So any good ideas of how to proceed?

回答1:

the logs says: url=http://localhost:8080/myjarfile.jar

That was a security decision made by Sun, before Oracle acquired them. They decided it was no business of applets or JWS apps. to know the location of the resources on the local file-system, so the URI returned will now always point back to the server, even if they are cached locally & the app. has all-permissions security level.

So any good ideas of how to proceed?

Redesign the app. That is the only practical solution.

There are a number of ways to iterate a Zip or Jar for the content, but the simplest method is to include a list of the content in a known location of the Jar, locate it using getResource(), read it, then extract each resource.



回答2:

Below is an implementation of your idea Andrew, it utilizes a DirUtil package I found here: http://codingjunkie.net/java-7-copy-move/

public class Zipper {

    private static final String TEMP_FILE_PREFIX = "temp-";
    private static final String TEMP_FILE_SUFIX = ".jar";

    private Logger logger = Logger.getLogger(getClass().getName());

    public Path extractProgram(String locationOfEmbeddedJar, String installDir) {
        Path installPath = null;
        try {
            installPath = Paths.get(installDir);
            if (Files.isDirectory(installPath)) {
                logger.warn("program already installed");
            } else {
                installPath = Files.createDirectory(installPath);
                Path tempJar = Files.createTempFile(TEMP_FILE_PREFIX,
                        TEMP_FILE_SUFIX);
                this.extractEmbeddedJar(locationOfEmbeddedJar, tempJar.toFile());

                logger.warn("in jarfile");
                // in jar file
                FileSystem fs = FileSystems.newFileSystem(tempJar, null);
                Path programPath = fs.getPath("/");

                logger.warn("programPath=" + programPath + " fileSystem="
                        + programPath.getFileSystem());

                DirUtils.copy(programPath, installPath);
            }
        } catch (IOException e) {
            logger.warn(e);
        }

        return (installPath);

    }

    private void extractEmbeddedJar(String locationOfEmbeddedJar,
            File locationOfTargetJar) {
        logger.warn("extractEmbeddedJar() " + locationOfEmbeddedJar);
        ClassLoader loader = this.getClass().getClassLoader();

        InputStream inputStream = loader
                .getResourceAsStream(locationOfEmbeddedJar);
        try {
            OutputStream out = new FileOutputStream(locationOfTargetJar);
            byte buf[] = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            out.close();
            inputStream.close();

        } catch (IOException e) {
            logger.warn(e);
        }
    }
}