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 /* 25 * @test 26 * @summary Test a pool containing jimage resources and classes. 27 * @author Jean-Francois Denise 28 * @modules jdk.jlink/jdk.tools.jlink.internal 29 * jdk.jlink/jdk.tools.jlink.plugin 30 * @run build ResourcePoolTest 31 * @run main ResourcePoolTest 32 */ 33 34 import java.io.ByteArrayInputStream; 35 import java.nio.ByteBuffer; 36 import java.nio.ByteOrder; 37 import java.util.ArrayList; 38 import java.util.Collection; 39 import java.util.HashSet; 40 import java.util.List; 41 import java.util.Optional; 42 import java.util.Set; 43 import java.util.function.Function; 44 import jdk.tools.jlink.internal.ResourcePoolManager; 45 import jdk.tools.jlink.plugin.ResourcePool; 46 import jdk.tools.jlink.plugin.ResourcePoolModule; 47 import jdk.tools.jlink.plugin.ResourcePool; 48 import jdk.tools.jlink.plugin.ResourcePoolEntry; 49 50 public class ResourcePoolTest { 51 main(String[] args)52 public static void main(String[] args) throws Exception { 53 new ResourcePoolTest().test(); 54 } 55 test()56 public void test() throws Exception { 57 checkResourceAdding(); 58 checkResourceVisitor(); 59 checkResourcesAfterCompression(); 60 } 61 62 private static final String SUFFIX = "END"; 63 checkResourceVisitor()64 private void checkResourceVisitor() throws Exception { 65 ResourcePoolManager input = new ResourcePoolManager(); 66 for (int i = 0; i < 1000; ++i) { 67 String module = "/module" + (i / 10); 68 String resourcePath = module + "/java/package" + i; 69 byte[] bytes = resourcePath.getBytes(); 70 input.add(ResourcePoolEntry.create(resourcePath, bytes)); 71 } 72 ResourcePoolManager output = new ResourcePoolManager(); 73 ResourceVisitor visitor = new ResourceVisitor(); 74 input.resourcePool().transformAndCopy(visitor, output.resourcePoolBuilder()); 75 if (visitor.getAmountBefore() == 0) { 76 throw new AssertionError("Resources not found"); 77 } 78 if (visitor.getAmountBefore() != input.entryCount()) { 79 throw new AssertionError("Number of visited resources. Expected: " + 80 visitor.getAmountBefore() + ", got: " + input.entryCount()); 81 } 82 if (visitor.getAmountAfter() != output.entryCount()) { 83 throw new AssertionError("Number of added resources. Expected: " + 84 visitor.getAmountAfter() + ", got: " + output.entryCount()); 85 } 86 output.entries().forEach(outResource -> { 87 String path = outResource.path().replaceAll(SUFFIX + "$", ""); 88 if (!input.findEntry(path).isPresent()) { 89 throw new AssertionError("Unknown resource: " + path); 90 } 91 }); 92 } 93 94 private static class ResourceVisitor implements Function<ResourcePoolEntry, ResourcePoolEntry> { 95 96 private int amountBefore; 97 private int amountAfter; 98 99 @Override apply(ResourcePoolEntry resource)100 public ResourcePoolEntry apply(ResourcePoolEntry resource) { 101 int index = ++amountBefore % 3; 102 switch (index) { 103 case 0: 104 ++amountAfter; 105 return ResourcePoolEntry.create(resource.path() + SUFFIX, 106 resource.type(), resource.contentBytes()); 107 case 1: 108 ++amountAfter; 109 return resource.copyWithContent(resource.contentBytes()); 110 } 111 return null; 112 } 113 getAmountAfter()114 public int getAmountAfter() { 115 return amountAfter; 116 } 117 getAmountBefore()118 public int getAmountBefore() { 119 return amountBefore; 120 } 121 } 122 checkResourceAdding()123 private void checkResourceAdding() { 124 List<String> samples = new ArrayList<>(); 125 samples.add("java.base"); 126 samples.add("java/lang/Object"); 127 samples.add("java.base"); 128 samples.add("java/lang/String"); 129 samples.add("java.management"); 130 samples.add("javax/management/ObjectName"); 131 test(samples, (resources, module, path) -> { 132 try { 133 resources.add(ResourcePoolEntry.create(path, new byte[0])); 134 } catch (Exception ex) { 135 throw new RuntimeException(ex); 136 } 137 }); 138 test(samples, (resources, module, path) -> { 139 try { 140 resources.add(ResourcePoolManager. 141 newCompressedResource(ResourcePoolEntry.create(path, new byte[0]), 142 ByteBuffer.allocate(99), "bitcruncher", null, 143 ((ResourcePoolManager)resources).getStringTable(), ByteOrder.nativeOrder())); 144 } catch (Exception ex) { 145 throw new RuntimeException(ex); 146 } 147 }); 148 } 149 test(List<String> samples, ResourceAdder adder)150 private void test(List<String> samples, ResourceAdder adder) { 151 if (samples.isEmpty()) { 152 throw new AssertionError("No sample to test"); 153 } 154 ResourcePoolManager resources = new ResourcePoolManager(); 155 Set<String> modules = new HashSet<>(); 156 for (int i = 0; i < samples.size(); i++) { 157 String module = samples.get(i); 158 modules.add(module); 159 i++; 160 String clazz = samples.get(i); 161 String path = "/" + module + "/" + clazz + ".class"; 162 adder.add(resources, module, path); 163 } 164 for (int i = 0; i < samples.size(); i++) { 165 String module = samples.get(i); 166 i++; 167 String clazz = samples.get(i); 168 String path = "/" + module + "/" + clazz + ".class"; 169 Optional<ResourcePoolEntry> res = resources.findEntry(path); 170 if (!res.isPresent()) { 171 throw new AssertionError("Resource not found " + path); 172 } 173 checkModule(resources.resourcePool(), res.get()); 174 if (resources.findEntry(clazz).isPresent()) { 175 throw new AssertionError("Resource found " + clazz); 176 } 177 } 178 if (resources.entryCount() != samples.size() / 2) { 179 throw new AssertionError("Invalid number of resources"); 180 } 181 } 182 checkModule(ResourcePool resources, ResourcePoolEntry res)183 private void checkModule(ResourcePool resources, ResourcePoolEntry res) { 184 Optional<ResourcePoolModule> optMod = resources.moduleView().findModule(res.moduleName()); 185 if (!optMod.isPresent()) { 186 throw new AssertionError("No module " + res.moduleName()); 187 } 188 ResourcePoolModule m = optMod.get(); 189 if (!m.name().equals(res.moduleName())) { 190 throw new AssertionError("Not right module name " + res.moduleName()); 191 } 192 if (!m.findEntry(res.path()).isPresent()) { 193 throw new AssertionError("resource " + res.path() 194 + " not in module " + m.name()); 195 } 196 } 197 checkResourcesAfterCompression()198 private void checkResourcesAfterCompression() throws Exception { 199 ResourcePoolManager resources1 = new ResourcePoolManager(); 200 ResourcePoolEntry res1 = ResourcePoolEntry.create("/module1/toto1", new byte[0]); 201 ResourcePoolEntry res2 = ResourcePoolEntry.create("/module2/toto1", new byte[0]); 202 resources1.add(res1); 203 resources1.add(res2); 204 205 checkResources(resources1, res1, res2); 206 ResourcePoolManager resources2 = new ResourcePoolManager(); 207 ResourcePoolEntry res3 = ResourcePoolEntry.create("/module2/toto1", new byte[7]); 208 resources2.add(res3); 209 resources2.add(ResourcePoolManager.newCompressedResource(res1, 210 ByteBuffer.allocate(7), "zip", null, resources1.getStringTable(), 211 ByteOrder.nativeOrder())); 212 checkResources(resources2, res1, res2); 213 } 214 checkResources(ResourcePoolManager resources, ResourcePoolEntry... expected)215 private void checkResources(ResourcePoolManager resources, ResourcePoolEntry... expected) { 216 List<String> modules = new ArrayList(); 217 resources.modules().forEach(m -> { 218 modules.add(m.name()); 219 }); 220 for (ResourcePoolEntry res : expected) { 221 if (!resources.contains(res)) { 222 throw new AssertionError("Resource not found: " + res); 223 } 224 225 if (!resources.findEntry(res.path()).isPresent()) { 226 throw new AssertionError("Resource not found: " + res); 227 } 228 229 if (!modules.contains(res.moduleName())) { 230 throw new AssertionError("Module not found: " + res.moduleName()); 231 } 232 233 if (!resources.contains(res)) { 234 throw new AssertionError("Resources not found: " + res); 235 } 236 237 try { 238 resources.add(res); 239 throw new AssertionError(res + " already present, but an exception is not thrown"); 240 } catch (Exception ex) { 241 // Expected 242 } 243 } 244 245 try { 246 resources.add(ResourcePoolEntry.create("/module2/toto1", new byte[0])); 247 throw new AssertionError("ResourcePool is read-only, but an exception is not thrown"); 248 } catch (Exception ex) { 249 // Expected 250 } 251 } 252 253 interface ResourceAdder { add(ResourcePoolManager resources, String module, String path)254 void add(ResourcePoolManager resources, String module, String path); 255 } 256 } 257