1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * Basic tests for ModuleFileParser
  26  */
  27 
  28 import java.io.*;
  29 import static java.lang.System.out;
  30 import java.util.Arrays;
  31 import java.util.Iterator;
  32 import java.util.Map.Entry;
  33 import org.openjdk.jigsaw.FileConstants.ModuleFile.SectionType;
  34 import static org.openjdk.jigsaw.FileConstants.ModuleFile.SectionType.*;
  35 import org.openjdk.jigsaw.ModuleFile;
  36 import org.openjdk.jigsaw.ModuleFile.SectionHeader;
  37 import org.openjdk.jigsaw.ModuleFile.SubSectionFileHeader;
  38 import org.openjdk.jigsaw.ModuleFileParser;
  39 import org.openjdk.jigsaw.ModuleFileParser.Event;
  40 import static org.openjdk.jigsaw.ModuleFileParser.Event.END_FILE;
  41 import static org.openjdk.jigsaw.ModuleFileParser.Event.END_SECTION;
  42 import org.openjdk.jigsaw.ModuleFileParserException;
  43 
  44 public class ModuleFileParserTest {
  45     public static void main(String[] args) throws Exception {
  46         if (args.length != 1) {
  47             usage();
  48             return;
  49         }
  50         File jmod = new File(args[0]);
  51 
  52         list(jmod);
  53         getClasses(jmod);
  54         getOneClass(jmod);
  55         getlibs(jmod);
  56         verify(jmod);
  57     }
  58 
  59     /*
  60      * List the sections of the given module file.
  61      */
  62     static void list(File jmod) {
  63         out.format("Listing sections of %s%n", jmod);
  64 
  65         try (FileInputStream fis = new FileInputStream(jmod)) {
  66             ModuleFileParser parser = ModuleFile.newParser(fis);
  67             while (parser.skipToNextStartSection()) {
  68                 SectionHeader header = parser.getSectionHeader();
  69                 SectionType type = header.getType();
  70                 switch (type) {
  71                     case MODULE_INFO:
  72                         out.format("%s section, %s%n", type, header); break;
  73                     case SIGNATURE:
  74                         out.format("%s section, %s%n", type, header); break;
  75                     case CLASSES:
  76                         out.format("%s section, %s%n", type, header); break;
  77                     case RESOURCES:
  78                         out.format("%s section, %s%n", type, header); break;
  79                     case NATIVE_LIBS:
  80                         out.format("%s section, %s%n", type, header); break;
  81                     case NATIVE_CMDS:
  82                         out.format("%s section, %s%n", type, header); break;
  83                     case CONFIG:
  84                         out.format("%s section, %s%n", type, header); break;
  85                     default:
  86                         throw new IOException("Unknown section type");
  87                 }
  88             }
  89         } catch (IOException | ModuleFileParserException e) {
  90             out.format("%s%n", e);
  91         }
  92     }
  93 
  94     /*
  95      * Extract classes from the given module file.
  96      */
  97     static void getClasses(File jmod) {
  98         out.format("Reading classes from %s%n", jmod);
  99 
 100         try (FileInputStream fis = new FileInputStream(jmod)) {
 101             ModuleFileParser parser = ModuleFile.newParser(fis);
 102             while (parser.skipToNextStartSection()) {
 103                 SectionHeader header = parser.getSectionHeader();
 104                 if (header.getType() == CLASSES) {
 105                     out.format("Has %s section%n", header.getType());
 106                     Iterator<Entry<String,InputStream>> classes = parser.getClasses();
 107                     while (classes.hasNext()) {
 108                         Entry<String,InputStream> entry = classes.next();
 109                         try (OutputStream os = createFile(jmod.getName() +
 110                                 File.separator + "classes" + File.separator +
 111                                 entry.getKey())) {
 112                             copyStream(entry.getValue(), os);
 113                         }
 114                     }
 115                     break;
 116                 }
 117             }
 118         } catch (IOException | ModuleFileParserException e) {
 119             out.format("%s%n", e);
 120         }
 121     }
 122 
 123     /*
 124      * Extracts the first class from the CLASSES section of the given module file.
 125      */
 126     static void getOneClass(File jmod) {
 127         out.format("Reading one classes from %s%n", jmod);
 128 
 129         try (FileInputStream fis = new FileInputStream(jmod)) {
 130             ModuleFileParser parser = ModuleFile.newParser(fis);
 131             while (parser.skipToNextStartSection()) {
 132                 SectionHeader header = parser.getSectionHeader();
 133                 if (header.getType() == CLASSES) {
 134                     out.format("Has %s section%n", header.getType());
 135                     Iterator<Entry<String,InputStream>> classes = parser.getClasses();
 136                     if (classes.hasNext()) {
 137                         Entry<String,InputStream> entry = classes.next();
 138                         try (OutputStream os = createFile(jmod.getName() +
 139                                 File.separator + "classes" + File.separator +
 140                                 entry.getKey())) {
 141                             copyStream(entry.getValue(), os);
 142                         }
 143                     }
 144                     break;
 145                 }
 146             }
 147         } catch (IOException | ModuleFileParserException e) {
 148             out.format("%s%n", e);
 149         }
 150     }
 151 
 152     /*
 153      * Extract the native libs from the given module file.
 154      */
 155     static void getlibs(File jmod) {
 156         out.format("Reading libs from %s%n", jmod);
 157 
 158         try (FileInputStream fis = new FileInputStream(jmod)) {
 159             ModuleFileParser parser = ModuleFile.newParser(fis);
 160             while (parser.skipToNextStartSection()) {
 161                 SectionHeader header = parser.getSectionHeader();
 162                 if (header.getType() == NATIVE_LIBS) {
 163                     out.format("Has %s section%n", header.getType());
 164                     while (parser.skipToNextStartSubSection()) {
 165                         SubSectionFileHeader subHeader = parser.getSubSectionFileHeader();
 166                         String path = subHeader.getPath();
 167                         try (OutputStream os = createFile(jmod.getName() +
 168                                 File.separator  + "lib" + File.separator + path)) {
 169                             copyStream(parser.getContentStream(), os);
 170                         }
 171                     }
 172                     break;
 173                 }
 174             }
 175         } catch (IOException | ModuleFileParserException e) {
 176             out.format("%s%n", e);
 177         }
 178     }
 179 
 180     /*
 181      * Verify the integraty of the given module file.
 182      */
 183     static void verify(File jmod) {
 184         out.format("Verifying %s%n", jmod);
 185 
 186         try (FileInputStream fis = new FileInputStream(jmod)) {
 187             ModuleFileParser parser = ModuleFile.newParser(fis);
 188             while (parser.hasNext()) {
 189                 Event event = parser.next();
 190                 if (event == END_SECTION) {
 191                     SectionHeader header = parser.getSectionHeader();
 192                     // compare hash in header to actual hash of content
 193                     if (!Arrays.equals(header.getHash(), parser.getHash()))
 194                         throw new RuntimeException("Verifying hash failed for "
 195                                                    + header.getType());
 196                 } else if (event == END_FILE) {
 197                     // compare hash in header to actual hash of file content
 198                     if (!Arrays.equals(parser.fileHeader().getHash(), parser.getHash()))
 199                         throw new RuntimeException("Verifying hash failed for File");
 200                 }
 201             }
 202         } catch (IOException | ModuleFileParserException e) {
 203             out.format("%s%n", e);
 204         }
 205     }
 206 
 207     /*
 208      * Helper method to create sub directories (if necessary)
 209      */
 210     private static OutputStream createFile(String pathName) throws IOException {
 211         File path = new File(pathName);
 212         File parent = new File(path.getParent());
 213         if (!parent.exists())
 214             parent.mkdirs();
 215         FileOutputStream fos = new FileOutputStream(path);
 216         return new BufferedOutputStream(fos);
 217     }
 218 
 219     private static void copyStream(InputStream in, OutputStream out)
 220         throws IOException
 221     {
 222         byte[] buf = new byte[8192];
 223         int read = 0;
 224         while ((read = in.read(buf)) > 0)
 225             out.write(buf, 0, read);
 226     }
 227 
 228     private static void usage() {
 229         out.format("Usage: java ModuleFileTest <module-file>%n");
 230     }
 231 }