1/* 2 * Copyright (c) 2016, 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 24import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; 25 26import java.lang.module.ModuleDescriptor.Provides; 27import java.util.Arrays; 28import java.util.HashSet; 29import java.util.Set; 30import java.util.stream.Stream; 31 32import org.xml.sax.helpers.XMLReaderFactory; 33 34public class Main { 35 /* 36 * @param args, the names of provider modules, which have been loaded 37 */ 38 public static void main(String[] args) throws Exception { 39 Module xml = ModuleLayer.boot().findModule("java.xml").get(); 40 41 Set<String> allServices = new HashSet<>(Arrays.asList(expectedAllServices)); 42 if (!allServices.equals(xml.getDescriptor().uses())) 43 throw new AssertionError("Expect xml module uses: " + allServices + " But actually uses: " 44 + xml.getDescriptor().uses()); 45 46 long violationCount = Stream.of(args) 47 .map(xmlProviderName -> ModuleLayer.boot().findModule(xmlProviderName).get()) 48 .mapToLong( 49 // services provided by the implementation in provider module 50 provider -> provider.getDescriptor().provides().stream() 51 .map(Provides::service) 52 .filter(serviceName -> { 53 allServices.remove(serviceName); // remove service provided by 54 // customized module from allServices 55 return !belongToModule(serviceName, instantiateXMLService(serviceName), provider); 56 }).count()) 57 .sum(); 58 59 // the remaining services should be provided by the default implementation 60 violationCount += allServices.stream() 61 .filter(serviceName -> !belongToModule(serviceName, instantiateXMLService(serviceName), xml)) 62 .count(); 63 64 if (violationCount > 0) 65 throw new AssertionError(violationCount + " services are not provided by expected module"); 66 } 67 68 /* 69 * instantiate a xml factory by reflection e.g. 70 * DocumentBuilderFactory.newInstance() 71 */ 72 private static Object instantiateXMLService(String serviceName) { 73 try { 74 if (serviceName.equals("org.xml.sax.XMLReader")) 75 return XMLReaderFactory.createXMLReader(); 76 else if (serviceName.equals("javax.xml.validation.SchemaFactory")) 77 return Class.forName(serviceName).getMethod("newInstance", String.class) 78 .invoke(null, W3C_XML_SCHEMA_NS_URI); 79 else 80 return Class.forName(serviceName).getMethod("newInstance").invoke(null); 81 } catch (Exception e) { 82 e.printStackTrace(System.err); 83 throw new RuntimeException(e); 84 } 85 } 86 87 /* 88 * verify which module provides the xml factory 89 */ 90 private static boolean belongToModule(String factoryName, Object factory, Module expected) { 91 Module actual = factory.getClass().getModule(); 92 if (!actual.equals(expected)) { 93 System.err.println("Expect " + factoryName + " is provided by " + expected 94 + ", but actual implementation " + factory.getClass() + " is provided by " + actual); 95 return false; 96 } else { 97 System.out.println(factory.getClass() + " is provided by " + expected); 98 return true; 99 } 100 } 101 102 /* 103 * This list equals the declarations in java.xml module-info.java 104 */ 105 private static final String[] expectedAllServices = { "javax.xml.datatype.DatatypeFactory", 106 "javax.xml.parsers.DocumentBuilderFactory", "javax.xml.parsers.SAXParserFactory", 107 "javax.xml.stream.XMLEventFactory", "javax.xml.stream.XMLInputFactory", 108 "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", 109 "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory", 110 "org.xml.sax.XMLReader"}; 111 112} 113