1 /*
   2  * Copyright (c) 2015, 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 import java.io.ByteArrayInputStream;
  25 import java.io.ByteArrayOutputStream;
  26 import java.io.DataOutputStream;
  27 import java.io.IOException;
  28 import java.io.InputStream;
  29 import java.nio.ByteOrder;
  30 import java.nio.file.Path;
  31 import java.util.ArrayList;
  32 import java.util.Collections;
  33 import java.util.HashSet;
  34 import java.util.List;
  35 import java.util.Set;
  36 import java.util.stream.Stream;
  37 import jdk.tools.jlink.internal.Archive;
  38 import jdk.tools.jlink.internal.ImageFileCreator;
  39 import jdk.tools.jlink.internal.ImagePluginStack;
  40 import jdk.tools.jlink.internal.ExecutableImage;
  41 import jdk.tools.jlink.builder.ImageBuilder;
  42 import jdk.tools.jlink.plugin.ResourcePool;
  43 
  44 
  45 /*
  46  * @test
  47  * @summary ImageFileCreator class test
  48  * @author Jean-Francois Denise
  49  * @modules jdk.jlink/jdk.tools.jlink.internal
  50  *          jdk.jlink/jdk.tools.jlink.builder
  51  *          java.base/jdk.internal.jimage
  52  * @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
  53  */
  54 public class ImageFileCreatorTest {
  55 
  56     private static class TestArchive implements Archive {
  57 
  58         private final String name;
  59         private final List<Entry> entries = new ArrayList<>();
  60 
  61         private TestArchive(String name, List<String> entries) {
  62             this.name = name;
  63             for (String p : entries) {
  64                 this.entries.add(new TestEntry(p, p));
  65             }
  66         }
  67 
  68         @Override
  69         public String moduleName() {
  70             return name;
  71         }
  72 
  73         @Override
  74         public Stream<Entry> entries() {
  75             return entries.stream();
  76         }
  77 
  78         @Override
  79         public Path getPath() {
  80             return null;
  81         }
  82 
  83         @Override
  84         public void open() throws IOException {
  85         }
  86 
  87         @Override
  88         public void close() throws IOException {
  89         }
  90 
  91         private class TestEntry extends Entry {
  92 
  93             TestEntry(String path, String name) {
  94                 super(TestArchive.this, path, name, Entry.EntryType.CLASS_OR_RESOURCE);
  95             }
  96 
  97             @Override
  98             public long size() {
  99                 return 0;
 100             }
 101 
 102             @Override
 103             public InputStream stream() throws IOException {
 104                 return new ByteArrayInputStream(new byte[0]);
 105             }
 106         }
 107     }
 108 
 109     public static void main(String[] args) throws Exception {
 110 
 111         {
 112             List<String> entries = new ArrayList<>();
 113             entries.add("classes/class");
 114             test(entries);
 115         }
 116 
 117         {
 118             // Add an entry that is a directory, that is wrong
 119             List<String> entries = new ArrayList<>();
 120             entries.add("classes");
 121             entries.add("classes/class");
 122             test(entries);
 123         }
 124 
 125         {
 126             // Add an entry that is wrongly prefixed by /
 127             // /bad//classes/class is the resource added
 128             // /bad/classes/class is the metadata node built.
 129             List<String> entries = new ArrayList<>();
 130             entries.add("/classes/class");
 131             test(entries);
 132         }
 133 
 134         {
 135             // Trailing '/' is wrong
 136             List<String> entries = new ArrayList<>();
 137             entries.add("classes/class/");
 138             test(entries);
 139         }
 140 
 141         {
 142             // Too much '/' characters
 143             List<String> entries = new ArrayList<>();
 144             entries.add("classes//class/");
 145             test(entries);
 146         }
 147 
 148         {
 149             // Too much '/' characters
 150             List<String> entries = new ArrayList<>();
 151             entries.add("classes/////class/");
 152             test(entries);
 153         }
 154 
 155         {
 156             // Single '/' character
 157             List<String> entries = new ArrayList<>();
 158             entries.add("/");
 159             test(entries);
 160         }
 161 
 162         {
 163             // 2 '/' characters
 164             List<String> entries = new ArrayList<>();
 165             entries.add("//");
 166             test(entries);
 167         }
 168 
 169         {
 170             // 3 '/' characters
 171             List<String> entries = new ArrayList<>();
 172             entries.add("///");
 173             test(entries);
 174         }
 175 
 176         {
 177             // no character
 178             List<String> entries = new ArrayList<>();
 179             entries.add("");
 180             test(entries);
 181         }
 182 
 183         {
 184             // all together
 185             List<String> entries = new ArrayList<>();
 186             entries.add("");
 187             entries.add("///");
 188             entries.add("//");
 189             entries.add("/");
 190             entries.add("classes/////class/");
 191             entries.add("classes//class/");
 192             entries.add("classes/class/");
 193             entries.add("/classes/class");
 194             entries.add("classes");
 195             entries.add("classes/class");
 196             test(entries);
 197         }
 198 
 199     }
 200 
 201     private static void test(List<String> entries) throws Exception {
 202         TestArchive arch = new TestArchive("bad", entries);
 203         Set<Archive> archives = new HashSet<>();
 204         archives.add(arch);
 205         ImageBuilder noopBuilder = new ImageBuilder() {
 206 
 207             @Override
 208             public DataOutputStream getJImageOutputStream() {
 209                 return new DataOutputStream(new ByteArrayOutputStream());
 210             }
 211 
 212             @Override
 213             public ExecutableImage getExecutableImage() {
 214                 return null;
 215             }
 216 
 217             @Override
 218             public void storeFiles(ResourcePool content) {
 219             }
 220         };
 221 
 222         ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
 223                 null, null);
 224 
 225         ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
 226     }
 227 }