/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Package /////////////// package jena.cmd; // Imports /////////////// import java.io.*; import java.lang.reflect.Method; import java.util.*; import java.util.regex.Pattern; import jena.schemagen; import jena.schemagen.SchemagenOptionsImpl; import junit.framework.TestCase; import org.apache.jena.rdf.model.* ; import org.apache.jena.util.FileUtils ; import org.junit.Test ; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <p> * Unit tests for schemagen * </p> */ public class Test_schemagen extends TestCase { // Constants ////////////////////////////////// String PREFIX = "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" + "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" + "@prefix owl: <http://www.w3.org/2002/07/owl#> .\n" + "@prefix ex: <http://example.com/sg#> .\n"; // Static variables ////////////////////////////////// private static Logger log = LoggerFactory.getLogger( Test_schemagen.class ); // Instance variables ////////////////////////////////// // Constructors ////////////////////////////////// // External signature methods ////////////////////////////////// /** This test used to fail with an abort, but we now guess the NS based on prevalence */ @Test public void testNoBaseURI0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {}, new String[] {".*public static final Resource A =.*"}, new String[] {} ); } @Test public void testClass0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {".*public static final Resource A.*"}, new String[] {} ); } @Test public void testClass1() throws Exception { String SOURCE = PREFIX + "ex:A a rdfs:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {}, new String[] {".*public static final Resource A.*"} ); } @Test public void testClass2() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {}, new String[] {".*public static final Resource A.*"} ); } @Test public void testClass3() throws Exception { String SOURCE = PREFIX + "ex:A a rdfs:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {".*public static final Resource A.*"}, new String[] {} ); } @Test public void testProperty0() throws Exception { String SOURCE = PREFIX + "ex:p a owl:ObjectProperty ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {".*public static final Property p.*"}, new String[] {} ); } @Test public void testProperty1() throws Exception { String SOURCE = PREFIX + "ex:p a rdf:Property ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, // in OWL mode we permit rdf:properties new String[] {".*public static final Property p.*"}, new String[] {} ); } @Test public void testProperty2() throws Exception { String SOURCE = PREFIX + "ex:p a owl:ObjectProperty ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {}, new String[] {".*public static final Property p.*"} ); } @Test public void testProperty3() throws Exception { String SOURCE = PREFIX + "ex:p a rdf:Property ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {".*public static final Property p.*"}, new String[] {} ); } @Test public void testInstance0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {".*public static final Resource i.*"}, new String[] {} ); } @Test public void testInstance1() throws Exception { String SOURCE = PREFIX + "ex:A a rdfs:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {".*public static final Resource i.*"}, new String[] {} ); } /* TODO this test fails, because the isInstance check in schemagen is quite weak. * Consider whether to fix the test or the code... * public void testInstance2() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {}, new String[] {".*public static final Resource i.*"} ); } */ @Test public void testInstance3() throws Exception { String SOURCE = PREFIX + "ex:A a rdfs:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {".*public static final Resource i.*"}, new String[] {} ); } @Test public void testInstance4() throws Exception { String SOURCE = PREFIX + "@prefix ex2: <http://example.org/otherNS#>. ex2:A a rdfs:Class . ex:i a ex2:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {".*public static final Resource i.*"}, new String[] {} ); } @Test public void testInstance5() throws Exception { String SOURCE = "@prefix : <http://ontology.earthster.org/eco/impact#> .\n" + "@prefix core: <http://ontology.earthster.org/eco/core#> .\n" + "@prefix ecoinvent: <http://ontology.earthster.org/eco/ecoinvent#> .\n" + "@prefix owl: <http://www.w3.org/2002/07/owl#> .\n" + "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" + "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" + "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" + "\n" + "<http://ontology.earthster.org/eco/impact>\n" + " rdf:type owl:Ontology ;\n" + " owl:imports <http://ontology.earthster.org/eco/ecoinvent> , <http://ontology.earthster.org/eco/core> ;\n" + " owl:versionInfo \"Created with TopBraid Composer\"^^xsd:string .\n" + "\n" + ":CD-CML2001-AbioticDepletion\n" + " rdf:type core:ImpactAssessmentMethodCategoryDescription ;\n" + " rdfs:label \"abiotic resource depletion\"^^xsd:string ;\n" + " core:hasImpactCategory\n" + " :abioticDepletion ."; testSchemagenOutput( SOURCE, null, new String[] {"--owl", "--inference"}, new String[] {".*public static final Resource CD_CML2001_AbioticDepletion.*"}, new String[] {".*valtype.*"} ); } @Test public void testDatatype0() throws Exception { String SOURCE = PREFIX + "ex:d a rdfs:Datatype . ex:d rdfs:comment \"custom datatype\" ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {".*public static final Resource d.*"}, new String[] {} ); } @Test public void testDatatype1() throws Exception { String SOURCE = PREFIX + "ex:d a rdfs:Datatype . ex:d rdfs:comment \"custom datatype\" ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--nodatatypes"}, new String[] {}, new String[] {".*public static final Resource d.*"} ); } @Test public void testRC0() throws Exception { String SOURCE = PREFIX + "ex:class a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {}, new String[] {".*public static final Resource class .*"} ); } @Test public void testComment0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ; rdfs:comment \"commentcomment\" ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {" */\\*\\* <p>commentcomment</p> \\*/ *"}, new String[] {} ); } @Test public void testComment1() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ; rdfs:comment \"commentcomment\" ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--nocomments"}, new String[] {}, new String[] {" */\\*\\* <p>commentcomment</p> \\*/ *"} ); } @Test public void testComment2() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ; rdfs:comment \"commentcomment\" ."; // we don't want the input fixed to be http://example.com/sg SchemaGenAux sga = new SchemaGenAux() { @Override protected void go( String[] args ) { go( new SchemagenOptionsImpl( args ) ); } }; testSchemagenOutput( SOURCE, sga, new String[] {"-a", "http://example.com/sg#", "--owl", "-i", "file:\\\\C:\\Users\\fubar/vocabs/test.ttl"}, new String[] {".*Vocabulary definitions from file:\\\\\\\\C:\\\\Users\\\\fubar/vocabs/test.ttl.*"}, new String[] {} ); } @Test public void testComment3() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ; rdfs:comment \"commentcomment\" ."; // we don't want the input fixed to be http://example.com/sg SchemaGenAux sga = new SchemaGenAux() { @Override protected void go( String[] args ) { go( new SchemagenOptionsImpl( args ) ); } }; testSchemagenOutput( SOURCE, sga, new String[] {"-a", "http://example.com/sg#", "--owl", "-i", "C:\\Users\\fubar/vocabs/test.ttl"}, new String[] {".*Vocabulary definitions from C:\\\\Users\\\\fubar/vocabs/test.ttl.*"}, new String[] {} ); } @Test public void testOntClass0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--ontology"}, new String[] {".*public static final OntClass A.*"}, new String[] {} ); } @Test public void testOntClass1() throws Exception { String SOURCE = PREFIX + "ex:A a rdfs:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--ontology"}, new String[] {}, new String[] {".*public static final OntClass A.*"} ); } @Test public void testOntClass2() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--ontology"}, new String[] {}, new String[] {".*public static final OntClass A.*"} ); } @Test public void testOntClass3() throws Exception { String SOURCE = PREFIX + "ex:A a rdfs:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--ontology"}, new String[] {".*public static final OntClass A.*"}, new String[] {} ); } @Test public void testOntProperty0() throws Exception { String SOURCE = PREFIX + "ex:p a owl:ObjectProperty ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--ontology"}, new String[] {".*public static final ObjectProperty p.*"}, new String[] {} ); } @Test public void testOntProperty1() throws Exception { String SOURCE = PREFIX + "ex:p a rdf:Property ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--ontology"}, // in OWL mode we permit rdf:properties new String[] {".*public static final OntProperty p.*"}, new String[] {} ); } @Test public void testOntProperty2() throws Exception { String SOURCE = PREFIX + "ex:p a owl:ObjectProperty ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--ontology"}, new String[] {}, new String[] {".*public static final ObjectProperty p.*"} ); } @Test public void testOntProperty3() throws Exception { String SOURCE = PREFIX + "ex:p a rdf:Property ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--ontology"}, new String[] {".*public static final OntProperty p.*"}, new String[] {} ); } @Test public void testHeader() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--ontology", "--header", "/* header */\n%package%\n%imports%\n"}, new String[] {"/\\* header \\*/"}, new String[] {} ); } @Test public void testFooter() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--ontology", "--footer", "/* footer */"}, new String[] {"/\\* footer \\*/"}, new String[] {} ); } @Test public void testPackage() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--ontology", "--package", "test.test"}, new String[] {"package test.test;\\s*"}, new String[] {} ); } @Test public void testClassname() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; SchemaGenAux fixture = new SchemaGenAux() { @Override protected void go( String[] args ) { SchemagenOptionsFixture sgf = new SchemagenOptionsFixture( args ) { @Override public Resource getInputOption() { return ResourceFactory.createResource( "http://example.org/soggy" ); } }; go( sgf ); } }; testSchemagenOutput( SOURCE, fixture, new String[] {"-a", "http://example.com/soggy#", "--ontology", "--package", "test.test", "-n", "Sg"}, new String[] {}, new String[] {} ); } @Test public void testClassdec() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--ontology", "--classdec", "\n implements java.lang.Cloneable\n"}, new String[] {"\\s*implements java.lang.Cloneable\\s*"}, new String[] {} ); } @Test public void testDeclarations() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--ontology", "--declarations", "protected String m_gnole = \"Fungle\";;\n"}, new String[] {".*Fungle.*"}, new String[] {} ); } @Test public void testNoClasses() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--ontology", "--noclasses"}, new String[] {}, new String[] {".*OntClass A.*"} ); } @Test public void testNoProperties() throws Exception { String SOURCE = PREFIX + "ex:p a owl:ObjectProperty ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--ontology", "--noproperties"}, new String[] {}, new String[] {".*Property p.*"} ); } @Test public void testNoIndividuals() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--noindividuals"}, new String[] {".*Resource A.*"}, new String[] {".*Resource i.*"} ); } @Test public void testNoHeader() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--noheader"}, new String[] {}, new String[] {"/\\*\\*.*"} ); } @Test public void testUCNames() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--uppercase"}, new String[] {".*Resource A.*",".*Resource I.*"}, new String[] {} ); } @Test public void testInference0() throws Exception { String SOURCE = PREFIX + "ex:p rdfs:domain ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl"}, new String[] {}, new String[] {".*Resource A.*",".*Property p.*"} ); } @Test public void testInference1() throws Exception { String SOURCE = PREFIX + "ex:p rdfs:domain ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--inference"}, new String[] {".*Resource A.*",".*Property p.*"}, new String[] {} ); } @Test public void testInference2() throws Exception { String SOURCE = PREFIX + "ex:p rdfs:domain ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--inference"}, new String[] {".*Resource A.*",".*Property p.*"}, new String[] {} ); } @Test public void testStrictIndividuals0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A . <http://example.com/different#j> a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs"}, new String[] {".*Resource i.*",".*Resource j.*"}, new String[] {} ); } @Test public void testStrictIndividuals1() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A . <http://example.com/different#j> a ex:A ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--strictIndividuals"}, new String[] {".*Resource i.*"}, new String[] {".*Resource j.*"} ); } @Test public void testLineEnd0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A . ex:p a rdf:Property ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--strictIndividuals"}, new String[] {}, new String[] {".*\r.*"} ); } @Test public void testLineEnd1() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A . ex:p a rdf:Property ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--dos"}, new String[] {".*\\r"}, new String[] {".*[^\r]"} ); } @Test public void testIncludeSource0() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class . ex:i a ex:A . ex:p a owl:ObjectProperty ."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--includeSource"}, new String[] {".*private static final String SOURCE.*", ".*ex:A *(a|rdf:type) *owl:Class.*"} , new String[] {} ); } @Test public void testIncludeSource1() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ; rdfs:comment \"comment\"."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--includeSource"}, new String[] {".*\\\\\"comment\\\\\".*\""}, new String[] {} ); } @Test public void testIncludeSource2() throws Exception { // had a report of the following not compiling .... String SOURCE = PREFIX + "@prefix skos: <http://www.w3.org/2004/02/skos/core#>.\n" + " <http://purl.org/dc/elements/1.1/relation> skos:note \"\"\"A second property with the same name as this property has been declared in the dcterms: namespace (http://purl.org/dc/terms/). See the Introduction to the document \"DCMI Metadata Terms\" (http://dublincore.org/documents/dcmi-terms/) for an explanation.\"\"\"."; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--owl", "--includeSource"}, new String[] {}, new String[] {} ); } @Test public void testIncludeSource3() throws Exception { // multiple literals on one line can cause double-quote issues String SOURCE = PREFIX + " ex:foo a ex:Foo; rdfs:label \"thing called foo\"@en, \"le foo\"@fr, \"das foo\"@de. "; testSchemagenOutput( SOURCE, null, new String[] {"-a", "http://example.com/sg#", "--rdfs", "--includeSource"}, new String[] {}, new String[] {} ); } @Test public void testConfigFile() throws Exception { String SOURCE = PREFIX + "ex:A a owl:Class ."; testSchemagenOutput( SOURCE, null, new String[] {"-c", "testing/cmd/sg-test-config.rdf"}, new String[] {".*OntClass.*"}, // if config is not processed, we will not get --ontology output new String[] {} ); } // Internal implementation methods ////////////////////////////////// /** * Test the output from schemagen by saving the output to a string, * then ensuring that every positive regex matches at least one line, and * every negative regex matches at most no lines. Also checks that * compiling the file does not cause any errors. * * @param source String defining the model, using N3 * @param sg The schemagen object to test, or null for a default * @param args list of args to pass to SG * @param posPatterns array of regexps that must match at least once in the output * @param negPatterns arrays of regexps that must not match the output * @return The string defining the java class */ protected String testSchemagenOutput( String source, SchemaGenAux sg, String[] args, String[] posPatterns, String[] negPatterns ) throws Exception { Model m = ModelFactory.createDefaultModel(); m.read( new StringReader( source ), "http://example.com/sg#", "N3" ); return testSchemagenOutput( m, sg, args, posPatterns, negPatterns ); } /** * Test the output from schemagen by saving the output to a string, * then ensuring that every positive regex matches at least one line, and * every negative regex matches at most no lines. Also checks that * compiling the file does not cause any errors. * * @param m Source model to read from * @param sg The schemagen object to test, or null for a default * @param args list of args to pass to SG * @param posPatterns array of regexps that must match at least once in the output * @param negPatterns arrays of regexps that must not match the output * @return The string defining the java class */ protected String testSchemagenOutput( Model m, SchemaGenAux sg, String[] args, String[] posPatterns, String[] negPatterns ) throws Exception { sg = (sg == null) ? new SchemaGenAux() : sg; sg.setSource( m ); ByteArrayOutputStream buf = new ByteArrayOutputStream(); sg.setOutput( new PrintStream( buf ) ); // run schemagen sg.testGo( args ); // now run the test pattern over the lines in the file String result = buf.toString(); // if (log.isDebugEnabled()) { // log.debug( result ); // } StringTokenizer tokens = new StringTokenizer( result, "\n" ); boolean[] foundPos = new boolean[posPatterns.length]; // look for any line that matches the patterns while (tokens.hasMoreTokens()) { String line = tokens.nextToken(); // try each positive pattern for (int i = 0; i < posPatterns.length; i++) { Pattern pat = Pattern.compile( posPatterns[i] ); foundPos[i] |= pat.matcher( line ).matches(); } // try each negative pattern for ( String negPattern : negPatterns ) { Pattern pat = Pattern.compile( negPattern ); assertFalse( "negative match pattern ||" + negPattern + "|| matched on line: " + line, pat.matcher( line ).matches() ); } } for (int i = 0; i < posPatterns.length; i++) { String msg = "Expecting a positive match to pattern: ||" + posPatterns[i] + "||"; assertTrue( msg + " in:\n" + result, foundPos[i] ); } // check that the file compiles with javac testCompile( result, "Sg" ); return result; } /** * Test the compilability of the generated output string by saving it to a * class file, and invoking javac on that file. * @param source * @param className * @throws Exception */ protected void testCompile( String source, String defaultClassName ) throws Exception { String className = defaultClassName; // ensure we use the right class name for the temp file // should do this with a regex, but java Pattern & Matcher is borked String key = "public class "; int i = source.indexOf( key ); if (i > 0) { i += key.length(); className = source.substring( i, source.indexOf( " ", i ) ); } // first write the source file to a temp dir File tmpDir = FileUtils.getScratchDirectory( "schemagen" ); File srcFile = new File( tmpDir, className + ".java" ); try ( FileWriter out = new FileWriter( srcFile ) ) { out.write( source ); } // now get ready to invoke javac using the new javax.tools package try { Class<?> tp = Class.forName( "javax.tools.ToolProvider" ); // static method to get the Java compiler tool Method gsjc = tp.getMethod( "getSystemJavaCompiler" ); Object sjc = gsjc.invoke( null ); // get the run method for the Java compiler tool Class<?> jc = Class.forName( "javax.tools.JavaCompiler" ); Method jcRun = jc.getMethod( "run", new Class[] {InputStream.class, OutputStream.class, OutputStream.class, String[].class} ); if (sjc != null && jcRun != null) { // build the args list for javac String[] args = new String[] {"-classpath", getClassPath( tmpDir ), "-d", tmpDir.getPath(), srcFile.getPath()}; int success = (Integer) jcRun.invoke( sjc, null, null, null, args ); assertEquals( "Errors reported from compilation of schemagen output", 0, success ); } else { log.debug( "Could not resolve javax.tools.JavaCompiler.run() method. Is the CLASSPATH defined correctly?" ); } } catch (ClassNotFoundException nf) { log.debug( "javax.tools not found (no tools.jar on classpath?). schemagen compilation test skipped." ); } catch (Exception e) { log.debug( e.getMessage(), e ); fail( e.getMessage() ); } // clean up List<File> toClean = new ArrayList<>(); toClean.add( tmpDir ); while (!toClean.isEmpty()) { File f = toClean.remove( 0 ); f.deleteOnExit(); if (f.isDirectory()) { for (File g: f.listFiles()) {toClean.add( g );} } } } /** * Return the classpath we can use to compile the sg output files * @param tmpDir * @return */ protected String getClassPath( File tmpDir ) { Properties pp = System.getProperties(); // if we're running under maven, use Special Secret Knowledge to identify the class path // otherwise, default to the CP that Java thinks it's using return pp.getProperty( "surefire.test.class.path", pp.getProperty( "java.class.path" ) ); } //============================================================================== // Inner class definitions //============================================================================== /** * An extension to standard schemagen to create a test fixture; we override the * input and output methods. */ static class SchemaGenAux extends schemagen { protected PrintStream m_auxOutput; protected Model m_auxSource; public void setOutput( PrintStream out ) { m_auxOutput = out; } public void setSource( Model m ) { m_auxSource = m; } // override the behaviours from schemagen @Override protected void selectInput() { m_source.add( m_auxSource ); m_source.setNsPrefixes( m_auxSource ); } @Override protected void selectOutput() { // call super to allow option processing super.selectOutput(); // then override the result m_output = m_auxOutput; } public void testGo( String[] args ) { go( args ); } @Override protected void go( String[] args ) { go( new SchemagenOptionsFixture( args ) ); } @Override protected void abort( String msg, Exception e ) { throw new RuntimeException( msg, e ); } } static class SchemagenOptionsFixture extends SchemagenOptionsImpl { public SchemagenOptionsFixture( String[] args ) { super( args ); } @Override public Resource getInputOption() { return ResourceFactory.createResource( "http://example.org/sg" ); } } }