1 /*
   2  * Copyright (c) 2010, 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  * @bug 4777124 6920545 6911753 8073924
  27  * @summary Verify that all Charset subclasses are available through the API
  28  */
  29 
  30 import java.net.URI;
  31 import java.nio.charset.Charset;
  32 import java.nio.file.FileSystem;
  33 import java.nio.file.FileSystems;
  34 import java.nio.file.Files;
  35 import java.nio.file.Path;
  36 import java.util.HashSet;
  37 import java.util.Set;
  38 import java.util.stream.Collectors;
  39 import java.util.stream.Stream;
  40 
  41 public class NIOCharsetAvailabilityTest {
  42 
  43     public static void main(String[] args) throws Exception {
  44 
  45         // build the set of all Charset subclasses in the
  46         // two known charset implementation packages
  47         FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
  48         Set<Class> charsets =
  49             Stream.concat(Files.walk(fs.getPath("/modules/java.base/sun/nio/cs/")),
  50                           Files.walk(fs.getPath("/modules/jdk.charsets/sun/nio/cs/ext/")))
  51                  .map( p -> p.subpath(2, p.getNameCount()).toString())
  52                  .filter( s ->  s.indexOf("$") == -1 && s.endsWith(".class"))
  53                  .map( s -> {
  54                      try {
  55                          return Class.forName(s.substring(0, s.length() - 6)
  56                                                .replace('/', '.'));
  57                      } catch (Exception x) {
  58                          throw new RuntimeException(x);
  59                      }
  60                   })
  61                  .filter( clz -> {
  62                      Class superclazz = clz.getSuperclass();
  63                      while (superclazz != null && !superclazz.equals(Object.class)) {
  64                          if (superclazz.equals(Charset.class)) {
  65                              return true;
  66                          } else {
  67                              superclazz = superclazz.getSuperclass();
  68                          }
  69                      }
  70                      return false;
  71                   })
  72                  .collect(Collectors.toCollection(HashSet::new));
  73         // remove the charsets that the API says are available
  74         Charset.availableCharsets()
  75                .values()
  76                .stream()
  77                .forEach(cs -> {
  78                    if (!charsets.contains(cs.getClass())) {
  79                        System.out.println(" missing -> " + cs.getClass());
  80                    }
  81                    charsets.remove(cs.getClass());
  82                 });
  83 
  84         // remove the known pseudo-charsets that serve only to implement
  85         // other charsets, but shouldn't be known to the public
  86         charsets.remove(Class.forName("sun.nio.cs.Unicode"));
  87         charsets.remove(Class.forName("sun.nio.cs.ext.ISO2022"));
  88         charsets.remove(Class.forName("sun.nio.cs.ext.ISO2022_CN_GB"));
  89         charsets.remove(Class.forName("sun.nio.cs.ext.ISO2022_CN_CNS"));
  90         charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0208_MS932"));
  91         charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0212_MS5022X"));
  92         charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0208_MS5022X"));
  93         try {
  94             charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0208_Solaris"));
  95             charsets.remove(Class.forName("sun.nio.cs.ext.JIS_X_0212_Solaris"));
  96         } catch (ClassNotFoundException x) {
  97             // these two might be moved into stdcs
  98             charsets.remove(Class.forName("sun.nio.cs.JIS_X_0208_Solaris"));
  99             charsets.remove(Class.forName("sun.nio.cs.JIS_X_0212_Solaris"));
 100         }
 101         // report the charsets that are implemented but not available
 102         if (charsets.size() > 0) {
 103             charsets.stream()
 104                     .forEach( clz ->
 105                         System.out.println("Unused Charset subclass: " + clz));
 106             throw new RuntimeException();
 107         }
 108     }
 109 }