< prev index next >

make/src/classes/build/tools/module/ModuleArchive.java

Print this page




   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package build.tools.module;
  27 
  28 import jdk.internal.jimage.Archive;
  29 import jdk.internal.jimage.Resource;
  30 
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.io.OutputStream;
  34 import java.io.UncheckedIOException;
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 import java.util.function.Consumer;




  38 
  39 /**
  40  * An Archive backed by an exploded representation on disk.
  41  */
  42 public class ModuleArchive implements Archive {
  43     private final Path classes;
  44     private final Path cmds;
  45     private final Path libs;
  46     private final Path configs;
  47     private final String moduleName;
  48 


  49     public ModuleArchive(String moduleName, Path classes, Path cmds,
  50                          Path libs, Path configs) {
  51         this.moduleName = moduleName;
  52         this.classes = classes;
  53         this.cmds = cmds;
  54         this.libs = libs;
  55         this.configs = configs;
  56     }
  57 
  58     @Override
  59     public String moduleName() {
  60         return moduleName;
  61     }
  62 
  63     @Override
  64     public void visitResources(Consumer<Resource> consumer) {
  65         if (classes == null)
  66             return;
  67         try{
  68             Files.walk(classes)
  69                     .sorted()
  70                     .filter(p -> !Files.isDirectory(p)
  71                             && !classes.relativize(p).toString().startsWith("_the.")
  72                             && !classes.relativize(p).toString().equals("javac_state"))
  73                     .map(this::toResource)
  74                     .forEach(consumer::accept);
  75         } catch (IOException ioe) {
  76             throw new UncheckedIOException(ioe);
  77         }
  78     }
  79 
  80     private Resource toResource(Path path) {



  81         try {
  82             return new Resource(classes.relativize(path).toString().replace('\\','/'),
  83                                 Files.size(path),
  84                                 0 /* no compression support yet */);
  85         } catch (IOException ioe) {
  86             throw new UncheckedIOException(ioe);

  87         }
  88     }
  89 
  90     private enum Section {
  91         CLASSES,
  92         CMDS,
  93         LIBS,
  94         CONFIGS
  95     }
  96 
  97     @Override
  98     public void visitEntries(Consumer<Entry> consumer) {
  99         try{
 100             if (classes != null)
 101                 Files.walk(classes)
 102                         .sorted()









 103                         .filter(p -> !Files.isDirectory(p)
 104                                 && !classes.relativize(p).toString().startsWith("_the.")
 105                                 && !classes.relativize(p).toString().equals("javac_state"))
 106                         .map(p -> toEntry(p, classes, Section.CLASSES))
 107                         .forEach(consumer::accept);
 108             if (cmds != null)
 109                 Files.walk(cmds)




 110                         .filter(p -> !Files.isDirectory(p))
 111                         .map(p -> toEntry(p, cmds, Section.CMDS))
 112                         .forEach(consumer::accept);
 113             if (libs != null)
 114                 Files.walk(libs)



 115                         .filter(p -> !Files.isDirectory(p))
 116                         .map(p -> toEntry(p, libs, Section.LIBS))
 117                         .forEach(consumer::accept);
 118             if (configs != null)
 119                 Files.walk(configs)



 120                         .filter(p -> !Files.isDirectory(p))
 121                         .map(p -> toEntry(p, configs, Section.CONFIGS))
 122                         .forEach(consumer::accept);


 123         } catch (IOException ioe) {
 124             throw new UncheckedIOException(ioe);
 125         }

 126     }
 127 
 128     private static class FileEntry implements Entry {
 129         private final String name;
 130         private final InputStream is;
 131         private final boolean isDirectory;
 132         private final Section section;
 133         FileEntry(String name, InputStream is,
 134                   boolean isDirectory, Section section) {
 135             this.name = name;
 136             this.is = is;

 137             this.isDirectory = isDirectory;
 138             this.section = section;
 139         }
 140         public String getName() {
 141             return name;
 142         }
 143         public Section getSection() {
 144             return section;
 145         }
 146         public InputStream getInputStream() {
 147             return is;
 148         }

 149         public boolean isDirectory() {
 150             return isDirectory;
 151         }
 152     }
 153 
 154     private Entry toEntry(Path entryPath, Path basePath, Section section) {
 155         try {
 156             return new FileEntry(basePath.relativize(entryPath).toString().replace('\\', '/'),
 157                                  Files.newInputStream(entryPath), false,
 158                                  section);
 159         } catch (IOException e) {
 160             throw new UncheckedIOException(e);
 161         }
 162     }
 163 
 164     @Override
 165     public Consumer<Entry> defaultImageWriter(Path path, OutputStream out) {
 166         return new DefaultEntryWriter(path, out);
 167     }
 168 
 169     private static class DefaultEntryWriter implements Consumer<Archive.Entry> {
 170         private final Path root;
 171         private final OutputStream out;
 172 
 173         DefaultEntryWriter(Path root, OutputStream out) {
 174             this.root = root;
 175             this.out = out;
 176         }
 177 
 178         @Override
 179         public void accept(Archive.Entry entry) {
 180             try {
 181                 FileEntry e = (FileEntry)entry;
 182                 Section section = e.getSection();
 183                 String filename = e.getName();
 184 
 185                 try (InputStream in = entry.getInputStream()) {
 186                     switch (section) {
 187                         case CLASSES:
 188                             if (!filename.startsWith("_the.") && !filename.equals("javac_state"))
 189                                 writeEntry(in);
 190                             break;
 191                         case LIBS:
 192                             writeEntry(in, destFile(nativeDir(filename), filename));
 193                             break;
 194                         case CMDS:
 195                             Path path = destFile("bin", filename);
 196                             writeEntry(in, path);
 197                             path.toFile().setExecutable(true, false);
 198                             break;
 199                         case CONFIGS:
 200                             writeEntry(in, destFile("conf", filename));
 201                             break;
 202                         default:
 203                             throw new InternalError("unexpected entry: " + filename);
 204                     }
 205                 }
 206             } catch (IOException x) {
 207                 throw new UncheckedIOException(x);
 208             }
 209         }
 210 
 211         private Path destFile(String dir, String filename) {
 212             return root.resolve(dir).resolve(filename);
 213         }
 214 
 215         private static void writeEntry(InputStream in, Path dstFile) throws IOException {
 216             if (Files.notExists(dstFile.getParent()))
 217                 Files.createDirectories(dstFile.getParent());
 218             Files.copy(in, dstFile);
 219         }
 220 
 221         private void writeEntry(InputStream in) throws IOException {
 222             byte[] buf = new byte[8192];
 223             int n;
 224             while ((n = in.read(buf)) > 0)
 225                 out.write(buf, 0, n);
 226         }
 227 
 228         private static String nativeDir(String filename) {
 229             if (System.getProperty("os.name").startsWith("Windows")) {
 230                 if (filename.endsWith(".dll") || filename.endsWith(".diz")
 231                     || filename.endsWith(".pdb") || filename.endsWith(".map")) {
 232                     return "bin";
 233                 } else {
 234                     return "lib";
 235                 }
 236             } else {
 237                 return "lib";
 238             }
 239         }
 240     }
 241 }
 242 


   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package build.tools.module;
  27 
  28 import jdk.internal.jimage.Archive;

  29 
  30 import java.io.IOException;
  31 import java.io.InputStream;

  32 import java.io.UncheckedIOException;
  33 import java.nio.file.Files;
  34 import java.nio.file.Path;
  35 import java.util.ArrayList;
  36 import java.util.List;
  37 import java.util.stream.Collectors;
  38 import java.util.stream.Stream;
  39 import jdk.internal.jimage.Archive.Entry.EntryType;
  40 
  41 /**
  42  * An Archive backed by an exploded representation on disk.
  43  */
  44 public class ModuleArchive implements Archive {
  45     private final Path classes;
  46     private final Path cmds;
  47     private final Path libs;
  48     private final Path configs;
  49     private final String moduleName;
  50 
  51     private final List<InputStream> opened = new ArrayList<>();
  52 
  53     public ModuleArchive(String moduleName, Path classes, Path cmds,
  54                          Path libs, Path configs) {
  55         this.moduleName = moduleName;
  56         this.classes = classes;
  57         this.cmds = cmds;
  58         this.libs = libs;
  59         this.configs = configs;
  60     }
  61 
  62     @Override
  63     public String moduleName() {
  64         return moduleName;
  65     }
  66 
  67     @Override
  68     public void open() throws IOException {
  69         // NOOP












  70     }
  71 
  72     @Override
  73     public void close() throws IOException {
  74         IOException e = null;
  75         for (InputStream stream : opened) {
  76             try {
  77                 stream.close();
  78             } catch (IOException ex) {
  79                 if (e == null) {
  80                     e = ex;
  81                 } else {
  82                     e.addSuppressed(ex);
  83                 }
  84             }
  85         }
  86         if (e != null) {
  87             throw e;
  88         }


  89     }
  90 
  91     @Override
  92     public Stream<Entry> entries() {
  93         List<Entry> entries = new ArrayList<>();
  94         try {
  95             /*
  96              * This code should be revisited to avoid buffering of the entries.
  97              * 1) Do we really need sorting classes? This force buffering of entries. 
  98              *    libs, cmds and configs are not sorted.
  99              * 2) I/O streams should be concatenated instead of buffering into 
 100              *    entries list.
 101              * 3) Close I/O streams in a close handler.
 102              */
 103             if (classes != null) {
 104                 try (Stream<Path> stream = Files.walk(classes)) {
 105                     entries.addAll(stream
 106                             .filter(p -> !Files.isDirectory(p)
 107                                     && !classes.relativize(p).toString().startsWith("_the.")
 108                                     && !classes.relativize(p).toString().equals("javac_state"))
 109                             .sorted()
 110                             .map(p -> toEntry(p, classes, EntryType.CLASS_OR_RESOURCE))
 111                             .collect(Collectors.toList()));
 112                 }
 113             }
 114             if (cmds != null) {
 115                 try (Stream<Path> stream = Files.walk(cmds)) {
 116                     entries.addAll(stream
 117                             .filter(p -> !Files.isDirectory(p))
 118                             .map(p -> toEntry(p, cmds, EntryType.NATIVE_CMD))
 119                             .collect(Collectors.toList()));
 120                 }
 121             }
 122             if (libs != null) {
 123                 try (Stream<Path> stream = Files.walk(libs)) {
 124                     entries.addAll(stream
 125                             .filter(p -> !Files.isDirectory(p))
 126                             .map(p -> toEntry(p, libs, EntryType.NATIVE_LIB))
 127                             .collect(Collectors.toList()));
 128                 }
 129             }
 130             if (configs != null) {
 131                 try (Stream<Path> stream = Files.walk(configs)) {
 132                 entries.addAll(stream
 133                         .filter(p -> !Files.isDirectory(p))
 134                         .map(p -> toEntry(p, configs, EntryType.CONFIG))
 135                         .collect(Collectors.toList()));
 136                 }
 137             }
 138         } catch (IOException ioe) {
 139             throw new UncheckedIOException(ioe);
 140         }
 141         return entries.stream();
 142     }
 143 
 144     private class FileEntry extends Entry {


 145         private final boolean isDirectory;
 146         private final long size;
 147         private final Path entryPath;
 148         FileEntry(Path entryPath, String path, EntryType type,
 149                   boolean isDirectory, long size) {
 150             super(ModuleArchive.this, path, path, type);
 151             this.entryPath = entryPath;
 152             this.isDirectory = isDirectory;
 153             this.size = size;









 154         }
 155 
 156         public boolean isDirectory() {
 157             return isDirectory;
 158         }











 159 
 160         @Override
 161         public long size() {
 162             return size;









 163         }
 164 
 165         @Override
 166         public InputStream stream() throws IOException {
 167             InputStream stream = Files.newInputStream(entryPath);
 168             opened.add(stream);
 169             return stream;

























 170         }
 171     }
 172 
 173     private Entry toEntry(Path entryPath, Path basePath, EntryType section) {
 174         try {
 175             String path = basePath.relativize(entryPath).toString().replace('\\', '/');
 176             return new FileEntry(entryPath, path, section,
 177                     false, Files.size(entryPath));
 178         } catch (IOException e) {
 179             throw new UncheckedIOException(e);





















 180         }
 181     }
 182 }
 183 
< prev index next >