src/share/classes/org/openjdk/jigsaw/ModuleFile.java

Print this page

        

@@ -56,10 +56,13 @@
         }
     }
 
     public final static class Reader implements Closeable {
 
+        // The library where this module is to be installed, or null if
+        // simply extracting ( jmod Extract, or jsign )
+        private SimpleLibrary lib;
         private DataInputStream stream;
         private File destination;
         private boolean deflate;
         private HashType hashtype;
 

@@ -121,10 +124,15 @@
                 this.stream =
                     new DataInputStream(new BufferedInputStream(stream));
             }
         }
 
+        public Reader(DataInputStream stream, SimpleLibrary lib) {
+            this(stream);
+            this.lib = lib;
+        }
+
         private void checkHashMatch(byte[] expected, byte[] computed)
             throws IOException
         {
             if (!MessageDigest.isEqual(expected, computed))
                 throw new IOException("Expected hash "

@@ -258,10 +266,11 @@
             return contentStream;
         }
 
         public void close() throws IOException {
             try {
+                try {
                 if (contentStream != null) {
                     contentStream.close();
                     contentStream = null;
                 }
             } finally {

@@ -268,12 +277,19 @@
                 if (fileIn != null) {
                     fileIn.close();
                     fileIn = null;
                 }
             }
+            } finally {
+                if (oomFilesWriter != null) {
+                    oomFilesWriter.close();
+                    oomFilesWriter = null;
         }
+            }
+        }
 
+
         public void readModule() throws IOException {
             extract = false;
             readStart();
             readRest();
         }

@@ -381,10 +397,12 @@
         public void readClasses(DataInputStream in) throws IOException {
             unpack200gzip(in);
         }
 
         private File currentPath = null;
+        // true if currentPath points a path outside the module directory
+        private boolean oomPath;   // false
 
         private OutputStream openOutputStream(SectionType type,
                                               String path)
             throws IOException
         {

@@ -427,13 +445,16 @@
             try (GZIPInputStream gin = new GZIPInputStream(bain);
                  OutputStream out = openOutputStream(type, header.getPath())) {
                 copyStream(gin, out);
             }
 
-            if (extract)
+            if (extract) {
                 markNativeCodeExecutable(type, currentPath);
+                if (oomPath)
+                    trackOutOfModuleContent(currentPath);
         }
+        }
 
         public void readUncompressedFile(DataInputStream in,
                                          SectionType type,
                                          int csize)
             throws IOException

@@ -446,12 +467,16 @@
                 byte[] buf = new byte[8192];
                 int n;
                 while ((n = cin.read(buf)) >= 0)
                     out.write(buf, 0, n);
             }
+            if (extract) {
             markNativeCodeExecutable(type, currentPath);
+                if (oomPath)
+                    trackOutOfModuleContent(currentPath);
          }
+         }
 
         public byte[] readModuleInfo(DataInputStream in, int csize)
             throws IOException
         {
             CountingInputStream cin = new CountingInputStream(in, csize);

@@ -467,10 +492,60 @@
             throws IOException
         {
             return readModuleInfo(in, csize); // signature has the same format
         }
 
+        // Returns the path for the section type, if the library
+        // has one configured.
+        private File librarySectionPath(SectionType type) {
+            if (lib != null && type == SectionType.NATIVE_LIBS
+                && lib.natlibs() != null)
+                return lib.natlibs();
+            if (lib != null && type == SectionType.NATIVE_CMDS
+                && lib.natcmds() != null)
+                return lib.natcmds();
+
+            return null;
+        }
+
+        // Track files installed outside the module library. For later removal.
+        private PrintWriter oomFilesWriter;
+
+        private void trackOutOfModuleContent(File file)
+            throws IOException
+        {
+            if (file == null)
+                return;
+
+            // Lazy construction, not all modules will need this.
+            if (oomFilesWriter == null) {
+                oomFilesWriter = new PrintWriter(computeRealPath("oomfiles"));
+            }
+            oomFilesWriter.println(file);
+            oomFilesWriter.flush();
+        }
+
+        void remove() throws IOException {
+            ModuleFile.Reader.remove(destination);
+        }
+
+        // Removes a module, given its module install directory
+        static void remove(File moduleDir) throws IOException {
+            // Firstly remove any files installed outside of the module dir
+            File oomfiles = new File(moduleDir, "oomfiles");
+            if (oomfiles.exists()) {
+                try (FileInputStream fis = new FileInputStream(oomfiles);
+                     BufferedReader in = new BufferedReader(new InputStreamReader(fis))) {
+                    String filename;
+                    while ((filename = in.readLine()) != null)
+                        Files.delete(new File(filename));
+                }
+            }
+
+            Files.deleteTree(moduleDir);
+        }
+
         private File computeRealPath(String storedpath) throws IOException {
 
             String convertedpath = storedpath.replace('/', File.separatorChar);
             File path = new File(convertedpath);
 

@@ -487,10 +562,31 @@
 
         private File computeRealPath(SectionType type,
                                      String storedpath)
             throws IOException
         {
+            File lsp = librarySectionPath(type);
+            if (lsp != null) {
+                // The library has a configured path for this section
+                File realpath = new File(lsp, storedpath);
+
+                if (realpath.exists()) {
+                    // conflict, for now just fail
+                    throw new IOException("File " + realpath + " already exists");
+                }
+
+                // Create the parent directories if necessary
+                File parent = realpath.getParentFile();
+                if (!parent.exists())
+                    Files.mkdirs(parent, realpath.getName());
+
+                oomPath = true;
+                return realpath;
+            }
+
+            // reset since the path must be within the module directory
+            oomPath = false;
             String dir = getSubdirOfSection(type);
             return computeRealPath(dir + File.separatorChar + storedpath);
         }
 
         private static void markNativeCodeExecutable(SectionType type,