1 /* 2 * Copyright (c) 2016, 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 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 package jdk.internal.loader; 26 27 import java.io.File; 28 import java.nio.file.Path; 29 import java.nio.file.Paths; 30 31 import jdk.internal.module.Checks; 32 33 /** 34 * Helper class for Class#getResource, Module#getResourceAsStream, and other 35 * methods that locate a resource in a module. 36 */ 37 public final class ResourceHelper { 38 private ResourceHelper() { } 39 40 /** 41 * Returns the <em>package name</em> for a resource or the empty package if 42 * the resource name does not contain a slash. 43 */ 44 public static String getPackageName(String name) { 45 int index = name.lastIndexOf('/'); 46 if (index != -1) { 47 return name.substring(0, index).replace("/", "."); 48 } else { 49 return ""; 50 } 51 } 52 53 /** 54 * Returns true if the resource is a <em>simple resource</em>. Simple 55 * resources can never be encapsulated. Resources ending in "{@code .class}" 56 * or where the package name is not a legal package name can not be 57 * encapsulated. 58 */ 59 public static boolean isSimpleResource(String name) { 60 int len = name.length(); 61 if (len > 6 && name.endsWith(".class")) { 62 return true; 63 } 64 if (!Checks.isPackageName(getPackageName(name))) { 65 return true; 66 } 67 return false; 68 } 69 70 /** 71 * Converts a resource name to a file path. Returns {@code null} if the 72 * resource name cannot be converted into a file path. Resource names 73 * with empty elements, or elements that are "." or ".." are rejected, 74 * as is a resource name that translates to a file path with a root 75 * component. 76 */ 77 public static Path toFilePath(String name) { 78 // scan the resource name to eagerly reject obviously invalid names 79 int next; 80 int off = 0; 81 while ((next = name.indexOf('/', off)) != -1) { 82 int len = next - off; 83 if (!mayTranslate(name, off, len)) { 84 return null; 85 } 86 off = next + 1; 87 } 88 int rem = name.length() - off; 89 if (!mayTranslate(name, off, rem)) { 90 return null; 91 } 92 93 // convert to file path 94 Path path; 95 if (File.separatorChar == '/') { 96 path = Paths.get(name); 97 } else { 98 // not allowed to embed file separators 99 if (name.contains(File.separator)) 100 return null; 101 path = Paths.get(name.replace('/', File.separatorChar)); 102 } 103 104 // file path not allowed to have root component 105 return (path.getRoot() == null) ? path : null; 106 } 107 108 /** 109 * Returns {@code true} if the element in a resource name is a candidate 110 * to translate to the element of a file path. 111 */ 112 private static boolean mayTranslate(String name, int off, int len) { 113 if (len <= 2) { 114 if (len == 0) 115 return false; 116 boolean starsWithDot = (name.charAt(off) == '.'); 117 if (len == 1 && starsWithDot) 118 return false; 119 if (len == 2 && starsWithDot && (name.charAt(off+1) == '.')) 120 return false; 121 } 122 return true; 123 } 124 125 }