1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.xsdc.tests; 18 19 import com.android.xsdc.FileSystem; 20 import com.android.xsdc.XmlSchema; 21 import com.android.xsdc.XsdHandler; 22 import com.android.xsdc.java.JavaCodeGenerator; 23 24 import javax.tools.*; 25 import javax.xml.parsers.SAXParser; 26 import javax.xml.parsers.SAXParserFactory; 27 28 import java.io.*; 29 import java.net.URI; 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Locale; 34 import java.util.Map; 35 36 import static org.junit.Assert.fail; 37 38 class TestHelper { 39 static class InMemoryJavaFileObject extends SimpleJavaFileObject { 40 private final String contents; 41 InMemoryJavaFileObject(String className, String contents)42 InMemoryJavaFileObject(String className, String contents) { 43 super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), 44 Kind.SOURCE); 45 this.contents = contents; 46 } 47 48 @Override getCharContent(boolean ignoreEncodingErrors)49 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 50 return contents; 51 } 52 } 53 54 static class InMemoryJavaClassObject extends SimpleJavaFileObject { 55 private ByteArrayOutputStream baos; 56 private String name; 57 InMemoryJavaClassObject(String name, Kind kind)58 InMemoryJavaClassObject(String name, Kind kind) { 59 super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); 60 baos = new ByteArrayOutputStream(); 61 this.name = name; 62 } 63 getBytes()64 byte[] getBytes() { 65 return baos.toByteArray(); 66 } 67 68 @Override openOutputStream()69 public OutputStream openOutputStream() { 70 return baos; 71 } 72 getClassName()73 String getClassName() { 74 return name; 75 } 76 } 77 78 static class InMemoryClassManager extends ForwardingJavaFileManager<JavaFileManager> { 79 private List<InMemoryJavaClassObject> classObjects; 80 InMemoryClassManager(JavaFileManager fileManager)81 InMemoryClassManager(JavaFileManager fileManager) { 82 super(fileManager); 83 classObjects = new ArrayList<>(); 84 } 85 86 @Override getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject sibling)87 public JavaFileObject getJavaFileForOutput(Location location, String name, 88 JavaFileObject.Kind kind, FileObject sibling) { 89 InMemoryJavaClassObject object = new InMemoryJavaClassObject(name, kind); 90 classObjects.add(object); 91 return object; 92 } 93 getAllClasses()94 List<InMemoryJavaClassObject> getAllClasses() { 95 return classObjects; 96 } 97 } 98 99 final static String packageName = "test"; 100 parseXsdAndCompile(InputStream in)101 static TestCompilationResult parseXsdAndCompile(InputStream in) throws Exception { 102 SAXParserFactory factory = SAXParserFactory.newInstance(); 103 factory.setNamespaceAware(true); 104 SAXParser parser = factory.newSAXParser(); 105 XsdHandler xsdHandler = new XsdHandler(); 106 parser.parse(in, xsdHandler); 107 XmlSchema xmlSchema = xsdHandler.getSchema(); 108 Map<String, StringBuffer> fileOutputMap = new HashMap<>(); 109 FileSystem fs = new FileSystem(fileOutputMap); 110 JavaCodeGenerator javaCodeGenerator = new JavaCodeGenerator(xmlSchema, packageName); 111 javaCodeGenerator.print(fs); 112 List<JavaFileObject> javaFileObjects = new ArrayList<>(); 113 for (Map.Entry<String, StringBuffer> entry : fileOutputMap.entrySet()) { 114 String className = entry.getKey().split("\\.")[0]; 115 javaFileObjects.add( 116 new InMemoryJavaFileObject(className, entry.getValue().toString())); 117 } 118 return new TestCompilationResult(compile(javaFileObjects)); 119 } 120 compile(List<JavaFileObject> javaFileObjects)121 private static List<InMemoryJavaClassObject> compile(List<JavaFileObject> javaFileObjects) 122 throws IOException { 123 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 124 DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); 125 List<InMemoryJavaClassObject> ret = null; 126 127 try (InMemoryClassManager fileManager = new InMemoryClassManager( 128 compiler.getStandardFileManager(diagnostics, null, null))) { 129 JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, 130 null, null, javaFileObjects); 131 boolean success = task.call(); 132 133 if (!success) { 134 StringBuilder log = new StringBuilder(); 135 log.append("Compilation failed!\n\n"); 136 for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { 137 log.append("Code: ").append(diagnostic.getCode()).append("\n"); 138 log.append("Kind: " + diagnostic.getKind() + "\n"); 139 log.append("Line: " + diagnostic.getLineNumber() + "\n"); 140 log.append("Column: " + diagnostic.getColumnNumber() + "\n"); 141 log.append("Source: " + diagnostic.getSource() + "\n"); 142 log.append("Message: " + diagnostic.getMessage(Locale.getDefault()) + "\n"); 143 } 144 fail(log.toString()); 145 } 146 ret = fileManager.getAllClasses(); 147 } 148 return ret; 149 } 150 }