2012-01-04 6 views
5

W tle eksperymentuję z pisaniem parsera DSL, używając tego wspaniałego example. Niestety, kiedy dostosować tę linię do użytku we własnej aplikacji:Jak utworzyć obiekt GroovyShell za pomocą ścieżki klas aplikacji kontekstowej

Script dslScript = new GroovyShell().parse(dsl.text) 

mam klasy rozwiązywaniu błędów w czasie wykonywania, jak moje pliki domen DSL mieć kod, który odwołuje się do innych klas zewnętrznych. Aplikacja kontekstowa ma dostęp do tych klas, ale nie wiem, jak udostępnić je do nowego obiektu GroovyShell, lub alternatywnie w jakiś sposób użyć środowiska wykonawczego aplikacji kontekstowej do przeanalizowania pliku.

Odpowiedz

6

Czy próbowali za pomocą następującego konstruktora: public GroovyShell(ClassLoader parent)

tak: Script dslScript = new GroovyShell(this.class.classLoader).parse(dsl.text)

nadzieję, że pomoże ...

+0

Tak. Właśnie doszło do podobnego rozwiązania, ponieważ w Grails: Skrypt dslScript = nowy GroovyShell (grailsApplication.classLoader) .parse (dsl.text) –

+0

Czy to rozwiązuje problemy z PermSpace, gdzie to zostawia informacje o klasie tam i można uruchomić ostatecznie z PermSpace? Zobacz tutaj: http://stackoverflow.com/questions/24169976/understanding-groovy-grails-classloader-leak https://issues.apache.org/jira/browse/GROOVY-2875 Tak więc zastanawiam się, czy to może być polecany do aplikacji serwerowych, czy nie, –

+0

Minęło trochę czasu, ale wyobrażam sobie, że to wciąż kompilacja nowej klasy. Jeśli tak jest, efekt będzie podobny do 'parseClass' – clmarquart

7

Oto fragment kodu, który pokazuje w jaki sposób wstrzyknąć obiektu kontekście konfiguracji właściwości i ścieżka klas.

Service parse(
String dslFile, List<String> classpath, 
Map<String, Object> properties, ServiceContext context) { 

// add POJO base class, and classpath 
CompilerConfiguration cc = new CompilerConfiguration(); 
cc.setScriptBaseClass(BaseDslScript.class.getName()); 
cc.setClasspathList(classpath); 

// inject default imports 
ic = new ImportCustomizer(); 
ic.addImports(ServiceUtils.class.getName()); 
cc.addCompilationCustomizers(ic); 

// inject context and properties 
Binding binding = new Binding(); 
binding.setVariable("context", context); 
for (prop: properties.entrySet()) { 
    binding.setVariable(prop.getKey(), prop.getValue()); 
} 

// parse the recipe text file 
ClassLoader classloader = this.class.getClassLoader(); 
GroovyShell gs = new GroovyShell(classloader, binding, cc); 
FileReader reader = new FileReader(dslFile); 
try { 
    return (Service) gs.evaluate(reader); 
} finally { 
    reader.close(); 
} 

Zauważ, że ten kod wstrzykuje również klasę bazową w celu uzyskania drobnoziarnistego kontrolę nad parsowania nieruchomości i wsparcia dla dziedziczenia pomiędzy różnymi plikami DSL. Aby uzyskać więcej informacji i działający kod źródłowy z projektu Cloudify, zobacz http://cloudifysource.tumblr.com/post/23046765169/parsing-complex-dsls-using-groovy