1 /* 2 * Copyright (c) 2010, 2014, 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 * @bug 4777124 6920545 6911753 27 * @summary Verify that all Charset subclasses are available through the API 28 */ 29 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileNotFoundException; 33 import java.io.IOException; 34 import java.net.URI; 35 import java.net.URISyntaxException; 36 import java.net.URL; 37 import java.net.URLClassLoader; 38 import java.nio.charset.Charset; 39 import java.security.AccessController; 40 import java.security.PrivilegedAction; 41 import java.util.Collection; 42 import java.util.HashSet; 43 import java.util.Iterator; 44 import java.util.Set; 45 import java.util.Vector; 46 import java.util.zip.ZipEntry; 47 import java.util.zip.ZipInputStream; 48 import sun.misc.Launcher; 49 50 51 public class NIOCharsetAvailabilityTest { 52 53 public static void main(String[] args) throws Exception { 54 // build the set of all Charset subclasses in the 55 // two known charset implementation packages 56 Set charsets = new HashSet(); 57 addCharsets(charsets, "sun.nio.cs"); 58 addCharsets(charsets, "sun.nio.cs.ext"); 59 60 // remove the charsets that the API says are available 61 Collection availableCharsets = Charset.availableCharsets().values(); 62 Iterator iter = availableCharsets.iterator(); 63 while (iter.hasNext()) { 64 charsets.remove(((Charset) iter.next()).getClass()); 65 } 66 67 // remove the known pseudo-charsets that serve only to implement 68 // other charsets, but shouldn't be known to the public 69 charsets.remove(Class.forName("sun.nio.cs.Unicode")); 70 charsets.remove(Class.forName("sun.nio.cs.ext.ISO2022")); 71 charsets.remove(Class.forName("sun.nio.cs.ext.ISO2022_CN_GB")); 72 charsets.remove(Class.forName("sun.nio.cs.ext.ISO2022_CN_CNS")); 73 charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0208_Solaris")); 74 charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0208_MS932")); 75 charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0212_MS5022X")); 76 charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0212_Solaris")); 77 charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0208_MS5022X")); 78 79 // report the charsets that are implemented but not available 80 iter = charsets.iterator(); 81 while (iter.hasNext()) { 82 System.out.println("Unused Charset subclass: " + ((Class) iter.next()).getName()); 83 } 84 if (charsets.size() > 0) { 85 throw new RuntimeException(); 86 } 87 } 88 89 private static Vector classPathSegments = new Vector(); 90 91 private static void addCharsets(Set charsets, final String packageName) 92 throws Exception { 93 94 String classPath = AccessController.doPrivileged( 95 (PrivilegedAction<String>)() -> System.getProperty("sun.boot.class.path")); 96 String s = AccessController.doPrivileged( 97 (PrivilegedAction<String>)() -> System.getProperty("java.class.path")); 98 99 // Search combined system and application class path 100 if (s != null && s.length() != 0) { 101 classPath += File.pathSeparator + s; 102 } 103 while (classPath != null && classPath.length() != 0) { 104 int i = classPath.lastIndexOf(java.io.File.pathSeparatorChar); 105 String dir = classPath.substring(i + 1); 106 if (i == -1) { 107 classPath = null; 108 } else { 109 classPath = classPath.substring(0, i); 110 } 111 classPathSegments.insertElementAt(dir, 0); 112 } 113 114 // add extensions from the extension class loader 115 ClassLoader appLoader = Launcher.getLauncher().getClassLoader(); 116 URLClassLoader extLoader = (URLClassLoader) appLoader.getParent(); 117 URL[] urls = extLoader.getURLs(); 118 for (int i = 0; i < urls.length; i++) { 119 try { 120 URI uri = new URI(urls[i].toString()); 121 classPathSegments.insertElementAt(uri.getPath(), 0); 122 } catch (URISyntaxException e) { 123 } 124 } 125 126 String[] classList = (String[]) 127 java.security.AccessController.doPrivileged( 128 new java.security.PrivilegedAction() { 129 public Object run() { 130 return getClassList(packageName, ""); 131 } 132 }); 133 134 for (int i = 0; i < classList.length; i++) { 135 try { 136 Class clazz = Class.forName(packageName + "." + classList[i]); 137 Class superclazz = clazz.getSuperclass(); 138 while (superclazz != null && !superclazz.equals(Object.class)) { 139 if (superclazz.equals(Charset.class)) { 140 charsets.add(clazz); 141 break; 142 } else { 143 superclazz = superclazz.getSuperclass(); 144 } 145 } 146 } catch (ClassNotFoundException e) { 147 } 148 } 149 } 150 151 private static final char ZIPSEPARATOR = '/'; 152 153 /** 154 * Walk through CLASSPATH and find class list from a package. 155 * The class names start with prefix string 156 * @param package name, class name prefix 157 * @return class list in an array of String 158 */ 159 private static String[] getClassList(String pkgName, String prefix) { 160 Vector listBuffer = new Vector(); 161 String packagePath = pkgName.replace('.', File.separatorChar) 162 + File.separatorChar; 163 String zipPackagePath = pkgName.replace('.', ZIPSEPARATOR) 164 + ZIPSEPARATOR; 165 for (int i = 0; i < classPathSegments.size(); i++){ 166 String onePath = (String) classPathSegments.elementAt(i); 167 File f = new File(onePath); 168 if (!f.exists()) 169 continue; 170 if (f.isFile()) 171 scanFile(f, zipPackagePath, listBuffer, prefix); 172 else if (f.isDirectory()) { 173 String fullPath; 174 if (onePath.endsWith(File.separator)) 175 fullPath = onePath + packagePath; 176 else 177 fullPath = onePath + File.separatorChar + packagePath; 178 File dir = new File(fullPath); 179 if (dir.exists() && dir.isDirectory()) 180 scanDir(dir, listBuffer, prefix); 181 } 182 } 183 String[] classNames = new String[listBuffer.size()]; 184 listBuffer.copyInto(classNames); 185 return classNames; 186 } 187 188 private static void addClass (String className, Vector listBuffer, String prefix) { 189 if (className != null && className.startsWith(prefix) 190 && !listBuffer.contains(className)) 191 listBuffer.addElement(className); 192 } 193 194 private static String midString(String str, String pre, String suf) { 195 String midStr; 196 if (str.startsWith(pre) && str.endsWith(suf)) 197 midStr = str.substring(pre.length(), str.length() - suf.length()); 198 else 199 midStr = null; 200 return midStr; 201 } 202 203 private static void scanDir(File dir, Vector listBuffer, String prefix) { 204 String[] fileList = dir.list(); 205 for (int i = 0; i < fileList.length; i++) { 206 addClass(midString(fileList[i], "", ".class"), listBuffer, prefix); 207 } 208 } 209 210 private static void scanFile(File f, String packagePath, Vector listBuffer, 211 String prefix) { 212 try { 213 ZipInputStream zipFile = new ZipInputStream(new FileInputStream(f)); 214 ZipEntry entry; 215 while ((entry = zipFile.getNextEntry()) != null) { 216 String eName = entry.getName(); 217 if (eName.startsWith(packagePath)) { 218 if (eName.endsWith(".class")) { 219 addClass(midString(eName, packagePath, ".class"), 220 listBuffer, prefix); 221 } 222 } 223 } 224 } catch (FileNotFoundException e) { 225 System.out.println("file not found:" + e); 226 } catch (IOException e) { 227 System.out.println("file IO Exception:" + e); 228 } catch (Exception e) { 229 System.out.println("Exception:" + e); 230 } 231 } 232 }