Revision 1023 org.gvsig.scripting/trunk/org.gvsig.scripting/org.gvsig.scripting.lib/org.gvsig.scripting.lib.impl/src/main/java/org/gvsig/scripting/impl/DefaultScriptingScript.java
DefaultScriptingScript.java | ||
---|---|---|
1 | 1 |
package org.gvsig.scripting.impl; |
2 | 2 |
|
3 |
import groovy.lang.GroovyClassLoader; |
|
4 |
import groovy.util.GroovyScriptEngine; |
|
3 | 5 |
import java.io.File; |
4 | 6 |
import java.io.IOException; |
5 | 7 |
import java.io.InputStream; |
6 | 8 |
import java.io.PrintStream; |
7 | 9 |
import java.io.Writer; |
10 |
import java.net.URL; |
|
8 | 11 |
import java.nio.charset.Charset; |
9 | 12 |
import java.util.ArrayList; |
13 |
import java.util.Arrays; |
|
10 | 14 |
import java.util.HashSet; |
15 |
import java.util.LinkedHashSet; |
|
11 | 16 |
import java.util.List; |
12 | 17 |
import java.util.Set; |
18 |
import java.util.concurrent.locks.ReentrantLock; |
|
13 | 19 |
|
14 | 20 |
import javax.script.Compilable; |
15 | 21 |
import javax.script.CompiledScript; |
... | ... | |
35 | 41 |
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable; |
36 | 42 |
import org.gvsig.tools.task.AbstractMonitorableTask; |
37 | 43 |
import org.ini4j.Ini; |
44 |
import org.python.core.Py; |
|
38 | 45 |
import org.python.core.PyException; |
39 | 46 |
import org.python.core.PyString; |
47 |
import org.python.core.PySystemState; |
|
40 | 48 |
import org.python.core.PyTraceback; |
49 |
import org.python.core.imp; |
|
50 |
import org.python.jsr223.MyPyScriptEngine; |
|
41 | 51 |
import org.slf4j.Logger; |
42 | 52 |
import org.slf4j.LoggerFactory; |
43 | 53 |
|
44 | 54 |
public class DefaultScriptingScript extends AbstractScript implements |
45 | 55 |
ScriptingScript { |
46 | 56 |
|
57 |
@SuppressWarnings("FieldNameHidesFieldInSuperclass") |
|
47 | 58 |
private static final Logger logger = LoggerFactory.getLogger(DefaultScriptingScript.class); |
48 | 59 |
protected String langName; |
49 | 60 |
protected String extension = null; |
50 | 61 |
protected String librarySuffix = null; |
51 | 62 |
protected ScriptEngine engine = null; |
52 | 63 |
protected CompiledScript compiledCode; |
64 |
protected boolean useSysPath; |
|
53 | 65 |
|
54 | 66 |
private String code = null; |
55 | 67 |
private String mainName = "main"; |
... | ... | |
113 | 125 |
|
114 | 126 |
} |
115 | 127 |
|
128 |
@SuppressWarnings("OverridableMethodCallInConstructor") |
|
116 | 129 |
protected DefaultScriptingScript(ScriptingFolder parent, String typename, ScriptingManager manager, String id) { |
117 | 130 |
super(parent, typename, manager, id); |
131 |
this.useSysPath = false; |
|
118 | 132 |
this.setLangName("python"); |
119 | 133 |
this.setSaved(true); |
120 | 134 |
this.delegatedObservable = new DelegateWeakReferencingObservable(this); |
... | ... | |
148 | 162 |
|
149 | 163 |
public Object __getattr__(String name) { |
150 | 164 |
try { |
151 |
ScriptEngine engine = this.getEngine();
|
|
165 |
ScriptEngine theEngine = this.getEngine();
|
|
152 | 166 |
this.compile(); |
153 |
return engine.get(name);
|
|
167 |
return theEngine.get(name);
|
|
154 | 168 |
} catch(Exception ex) { |
155 | 169 |
return null; |
156 | 170 |
} |
157 | 171 |
} |
158 | 172 |
|
159 | 173 |
public void __setattr__(String name, Object value) { |
160 |
ScriptEngine engine = this.getEngine();
|
|
174 |
ScriptEngine theEngine = this.getEngine();
|
|
161 | 175 |
this.compile(); |
162 |
engine.put(name, value);
|
|
176 |
theEngine.put(name, value);
|
|
163 | 177 |
} |
164 | 178 |
|
165 | 179 |
public Object __call__() { |
... | ... | |
235 | 249 |
} |
236 | 250 |
|
237 | 251 |
protected String getCodeToInitializeEngine() { |
238 |
String name = "org/gvsig/scripting/langs/"+this.getLangName().toLowerCase()+"/init.txt";
|
|
252 |
String initName = "org/gvsig/scripting/langs/"+this.getLangName().toLowerCase()+"/init.txt";
|
|
239 | 253 |
try { |
240 |
InputStream template = this.getClass().getClassLoader().getResourceAsStream(name);
|
|
254 |
InputStream template = this.getClass().getClassLoader().getResourceAsStream(initName);
|
|
241 | 255 |
if( template == null ) { |
242 | 256 |
return null; |
243 | 257 |
} |
244 | 258 |
List<String> lines = IOUtils.readLines(template); |
245 | 259 |
return StringUtils.join(lines, "\n"); |
246 | 260 |
} catch (Exception ex) { |
247 |
logger.warn("Can't load code to initialize the script from '"+name+".",ex);
|
|
261 |
logger.warn("Can't load code to initialize the script from '"+initName+".",ex);
|
|
248 | 262 |
return null; |
249 | 263 |
} |
250 | 264 |
} |
251 | 265 |
|
266 |
private List<URL> getClassPath() { |
|
267 |
Set<URL> classPath = new HashSet<>(); |
|
268 |
|
|
269 |
try { |
|
270 |
// ClassLoader myloader = this.getClass().getClassLoader(); |
|
271 |
// if( myloader instanceof URLClassLoader) { |
|
272 |
// classPath.addAll(Arrays.asList(((URLClassLoader) myloader).getURLs())); |
|
273 |
// } |
|
274 |
URL url; |
|
275 |
if( StringUtils.isEmpty(this.getIsolationGroup()) ) { |
|
276 |
url = this.getFile().getParentFile().getCanonicalFile().toURI().toURL(); |
|
277 |
classPath.add(url); |
|
278 |
} |
|
279 |
|
|
280 |
url = this.getManager().getUserFolder().getFile().getCanonicalFile().toURI().toURL(); |
|
281 |
classPath.add(url); |
|
282 |
|
|
283 |
List<File> folders = getLibFolders(); |
|
284 |
if( folders!=null ) { |
|
285 |
for (File folder : folders) { |
|
286 |
url = folder.getAbsoluteFile().toURI().toURL(); |
|
287 |
classPath.add(url); |
|
288 |
} |
|
289 |
} |
|
290 |
|
|
291 |
ScriptingFolder folders2 = getManager().getSystemFolder(); |
|
292 |
if( folders2!=null ) { |
|
293 |
for (ScriptingUnit folder : folders2.getUnits()) { |
|
294 |
url = folder.getFile().getCanonicalFile().toURI().toURL(); |
|
295 |
classPath.add(url); |
|
296 |
} |
|
297 |
} |
|
298 |
} catch(Exception ex) { |
|
299 |
|
|
300 |
} |
|
301 |
return new ArrayList<>(classPath); |
|
302 |
} |
|
303 |
|
|
304 |
private void addClassPathToEngine(ScriptEngine engine, List<URL> classPath) { |
|
305 |
if( engine instanceof MyPyScriptEngine ) { |
|
306 |
PySystemState sys = Py.getSystemState(); |
|
307 |
if( this.useSysPath ) { |
|
308 |
// logger.info("Running without sys.classLoader, "+ this.getFile().getAbsolutePath()+"."); |
|
309 |
// ReentrantLock importLock =sys.getImportLock(); |
|
310 |
// importLock.lock(); |
|
311 |
// try { |
|
312 |
Set<String> paths = new LinkedHashSet<>(); |
|
313 |
for( int i=0; i<sys.path.size(); i++) { |
|
314 |
String path = (String) sys.path.get(i); |
|
315 |
paths.add(path); |
|
316 |
} |
|
317 |
for (URL url : classPath) { |
|
318 |
String path = FileUtils.toFile(url).getAbsolutePath(); |
|
319 |
if( !paths.contains(path) ) { |
|
320 |
sys.path.add( Py.newString(path)); |
|
321 |
} |
|
322 |
} |
|
323 |
// } finally { |
|
324 |
// importLock.unlock(); |
|
325 |
// } |
|
326 |
} else { |
|
327 |
ClassLoader loader = sys.getClassLoader(); |
|
328 |
if( loader == null ) { |
|
329 |
ClassLoader parentClassLoader = imp.getParentClassLoader(); |
|
330 |
loader = new MutableURLClassLoader(classPath, parentClassLoader); |
|
331 |
sys.setClassLoader(loader); |
|
332 |
} else if( loader instanceof MutableURLClassLoader ) { |
|
333 |
((MutableURLClassLoader) loader).addUrls(classPath); |
|
334 |
} |
|
335 |
} |
|
336 |
|
|
337 |
} else if( engine instanceof GroovyScriptEngine ) { |
|
338 |
GroovyClassLoader loader = ((GroovyScriptEngine)engine).getGroovyClassLoader(); |
|
339 |
Set<URL> urls = new HashSet(); |
|
340 |
urls.addAll(Arrays.asList(loader.getURLs())); |
|
341 |
for (URL url : classPath) { |
|
342 |
if( ! urls.contains(url) ) { |
|
343 |
loader.addURL(url); |
|
344 |
} |
|
345 |
} |
|
346 |
} |
|
347 |
} |
|
348 |
|
|
252 | 349 |
public ScriptEngine getEngine() { |
253 | 350 |
if (this.engine == null) { |
254 | 351 |
synchronized(this.getManager()) { |
255 | 352 |
ScriptEngine scriptEngine = this.manager.getEngineByLanguage(langName, this.getIsolationGroup()); |
256 |
|
|
353 |
addClassPathToEngine(scriptEngine,getClassPath()); |
|
354 |
|
|
257 | 355 |
scriptEngine.put("script", this); |
258 | 356 |
scriptEngine.put("Main", Main.class); |
259 | 357 |
scriptEngine.getContext().setWriter(stdout); |
260 | 358 |
scriptEngine.getContext().setErrorWriter(stderr); |
261 | 359 |
|
262 | 360 |
this.engine = scriptEngine; |
263 |
String code = this.getCodeToInitializeEngine();
|
|
264 |
if (code != null) {
|
|
361 |
String theCode = this.getCodeToInitializeEngine();
|
|
362 |
if (theCode != null) {
|
|
265 | 363 |
try { |
266 |
this.engine.eval(code);
|
|
364 |
this.engine.eval(theCode);
|
|
267 | 365 |
} catch (Exception ex) { |
268 |
logger.warn("Can't initialize engine with the code:\n" + code, ex);
|
|
366 |
logger.warn("Can't initialize engine with the code:\n" + theCode, ex);
|
|
269 | 367 |
} |
270 | 368 |
} |
271 | 369 |
} |
... | ... | |
280 | 378 |
this.setMainName((String) getInfValue(prefs, "Script", "main", "main")); |
281 | 379 |
this.setLangName((String) getInfValue(prefs, "Script", "Lang",this.getLangName())); |
282 | 380 |
this.setLibrarySuffix((String) getInfValue(prefs, "Script", "LibraryVersion",null)); |
381 |
this.useSysPath = getInfBoolean(prefs, "Script", "useSysPath", false); |
|
283 | 382 |
} |
284 | 383 |
|
285 | 384 |
@Override |
... | ... | |
287 | 386 |
this.setId(id); |
288 | 387 |
this.setParent(folder); |
289 | 388 |
|
290 |
String extension = FilenameUtils.getExtension(id);
|
|
291 |
if( extension != null ) {
|
|
292 |
String language = this.manager.getLanguageOfExtension(extension);
|
|
389 |
String theExtension = FilenameUtils.getExtension(id);
|
|
390 |
if( theExtension != null ) {
|
|
391 |
String language = this.manager.getLanguageOfExtension(theExtension);
|
|
293 | 392 |
if( language != null ) { |
294 | 393 |
this.setLangName(language); |
295 | 394 |
} |
296 |
this.setExtension(extension);
|
|
395 |
this.setExtension(theExtension);
|
|
297 | 396 |
} |
298 | 397 |
File f = getFileResource(".inf"); |
299 | 398 |
if (f.isFile()) { |
... | ... | |
345 | 444 |
super.save(prefs); |
346 | 445 |
prefs.put("Script", "main", this.getMainName()); |
347 | 446 |
prefs.put("Script", "Lang", this.getLangName()); |
447 |
if( this.useSysPath ) { |
|
448 |
prefs.put("Script", "useSysPath", this.useSysPath); |
|
449 |
} |
|
348 | 450 |
try { |
349 | 451 |
prefs.store(); |
350 | 452 |
} catch (IOException e) { |
... | ... | |
427 | 529 |
@Override |
428 | 530 |
public void compile() { |
429 | 531 |
if (this.compiledCode == null) { |
430 |
ScriptEngine engine = this.getEngine();
|
|
431 |
if (engine instanceof Compilable) {
|
|
532 |
ScriptEngine theEngine = this.getEngine();
|
|
533 |
if (theEngine instanceof Compilable) {
|
|
432 | 534 |
try { |
433 |
Compilable compilable = (Compilable) engine;
|
|
434 |
String code = this.getCode();
|
|
535 |
Compilable compilable = (Compilable) theEngine;
|
|
536 |
String theCode = this.getCode();
|
|
435 | 537 |
if( "python".equalsIgnoreCase(this.getLangName()) ) { |
436 | 538 |
// If a Unicode string with a coding declaration is passed to compile(), |
437 | 539 |
// a SyntaxError will be raised, but this is necessary to import from |
438 | 540 |
// another module, so we remove it. |
439 | 541 |
// http://bugs.jython.org/issue1696 |
440 |
code = code.replaceFirst("^\\s*#([^:\\n]*)coding:","#$1 c-o-d-i-n-g:");
|
|
542 |
theCode = theCode.replaceFirst("^\\s*#([^:\\n]*)coding:","#$1 c-o-d-i-n-g:");
|
|
441 | 543 |
} |
442 |
this.compiledCode = compilable.compile(code);
|
|
443 |
if( engine instanceof Invocable) {
|
|
544 |
this.compiledCode = compilable.compile(theCode);
|
|
545 |
if( theEngine instanceof Invocable) {
|
|
444 | 546 |
this.compiledCode.eval(); |
445 | 547 |
} |
446 | 548 |
} catch (ScriptException e) { |
... | ... | |
460 | 562 |
throw ce; |
461 | 563 |
} |
462 | 564 |
} else { |
463 |
String code = this.getCode();
|
|
565 |
String theCode = this.getCode();
|
|
464 | 566 |
try { |
465 |
engine.eval(code);
|
|
567 |
theEngine.eval(theCode);
|
|
466 | 568 |
} catch (ScriptException e) { |
467 | 569 |
Object[] location = this.getLocation(e); |
468 | 570 |
CompileErrorException ce = new CompileErrorException( |
... | ... | |
743 | 845 |
} |
744 | 846 |
|
745 | 847 |
public String getNewTemplate() { |
746 |
String name = "org/gvsig/scripting/langs/"+this.getLangName().toLowerCase()+"/new_template.txt";
|
|
848 |
String theTemplateName = "org/gvsig/scripting/langs/"+this.getLangName().toLowerCase()+"/new_template.txt";
|
|
747 | 849 |
try { |
748 |
InputStream template = this.getClass().getClassLoader().getResourceAsStream(name);
|
|
850 |
InputStream template = this.getClass().getClassLoader().getResourceAsStream(theTemplateName);
|
|
749 | 851 |
if( template == null ) { |
750 | 852 |
return null; |
751 | 853 |
} |
752 | 854 |
List<String> lines = IOUtils.readLines(template); |
753 | 855 |
return StringUtils.join(lines, "\n"); |
754 | 856 |
} catch (Exception ex) { |
755 |
logger.warn("Can't load new-template from '"+name+"'.",ex);
|
|
857 |
logger.warn("Can't load new-template from '"+theTemplateName+"'.",ex);
|
|
756 | 858 |
return null; |
757 | 859 |
} |
758 | 860 |
} |
Also available in: Unified diff