gvsig-scripting / 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 @ 453
History | View | Annotate | Download (12.5 KB)
1 |
package org.gvsig.scripting.impl; |
---|---|
2 |
|
3 |
import java.io.File; |
4 |
import java.io.IOException; |
5 |
import java.util.List; |
6 |
import java.util.Map; |
7 |
|
8 |
import javax.script.Compilable; |
9 |
import javax.script.CompiledScript; |
10 |
import javax.script.Invocable; |
11 |
import javax.script.ScriptEngine; |
12 |
import javax.script.ScriptException; |
13 |
|
14 |
import org.apache.commons.io.FileUtils; |
15 |
import org.apache.commons.io.FilenameUtils; |
16 |
import org.gvsig.scripting.CompileErrorException; |
17 |
import org.gvsig.scripting.ExecuteErrorException; |
18 |
import org.gvsig.scripting.ScriptingBaseScript; |
19 |
import org.gvsig.scripting.ScriptingFolder; |
20 |
import org.gvsig.scripting.ScriptingManager; |
21 |
import org.gvsig.scripting.ScriptingScript; |
22 |
import org.gvsig.scripting.ScriptingUnit; |
23 |
import org.gvsig.tools.dispose.Disposable; |
24 |
import org.gvsig.tools.observer.Observer; |
25 |
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable; |
26 |
import org.gvsig.tools.task.AbstractMonitorableTask; |
27 |
import org.ini4j.Ini; |
28 |
import org.slf4j.Logger; |
29 |
import org.slf4j.LoggerFactory; |
30 |
|
31 |
public class DefaultScriptingScript extends AbstractScript implements |
32 |
ScriptingScript { |
33 |
|
34 |
private static final Logger logger = LoggerFactory.getLogger(DefaultScriptingScript.class); |
35 |
protected String langName; |
36 |
protected String extension = null; |
37 |
protected ScriptEngine engine = null; |
38 |
protected CompiledScript compiledCode;
|
39 |
|
40 |
private String code = null; |
41 |
private String mainName = "main"; |
42 |
private boolean saved; |
43 |
private final DelegateWeakReferencingObservable delegatedObservable; |
44 |
|
45 |
protected DefaultScriptingScript(ScriptingFolder parent, String typename, ScriptingManager manager, String id) { |
46 |
super(parent, typename, manager, id);
|
47 |
this.setLangName("python"); |
48 |
this.setSaved(true); |
49 |
this.delegatedObservable = new DelegateWeakReferencingObservable(this); |
50 |
} |
51 |
|
52 |
public DefaultScriptingScript(ScriptingFolder parent, ScriptingManager manager, String id) { |
53 |
this(parent, ScriptingManager.UNIT_SCRIPT, manager, id);
|
54 |
} |
55 |
|
56 |
public ScriptingUnit load(String name) { |
57 |
ScriptingUnit script = null;
|
58 |
File f = null; |
59 |
String scname = name;
|
60 |
if (!scname.endsWith(".inf")) { |
61 |
scname = scname + ".inf";
|
62 |
} |
63 |
if (scname.startsWith("/")) { |
64 |
f = new File(scname.substring(1)); |
65 |
} else {
|
66 |
f = new File(this.getParent().getFile(), scname); |
67 |
if (!f.exists()) {
|
68 |
return null; |
69 |
} |
70 |
} |
71 |
try {
|
72 |
script = this.getManager().getScript(f);
|
73 |
} catch (ScriptNotFoundException ex) {
|
74 |
return null; |
75 |
} |
76 |
if (script != null) { |
77 |
this.getEngine().put(script.getId(), script);
|
78 |
} |
79 |
return script;
|
80 |
} |
81 |
|
82 |
public Object __getattr__(String name) { |
83 |
ScriptEngine engine = this.getEngine();
|
84 |
this.compile();
|
85 |
return engine.get(name);
|
86 |
} |
87 |
|
88 |
public void __setattr__(String name, Object value) { |
89 |
ScriptEngine engine = this.getEngine();
|
90 |
this.compile();
|
91 |
engine.put(name,value); |
92 |
} |
93 |
|
94 |
public Object __call__() { |
95 |
return this.run(); |
96 |
} |
97 |
|
98 |
public Object __call__(Object[] args) { |
99 |
return this.run(args); |
100 |
} |
101 |
|
102 |
protected void notifyErrors(Exception exception, String command) { |
103 |
this.delegatedObservable.notifyObservers(new BaseScriptingNotifycation( |
104 |
this, BaseScriptingNotifycation.RUNTIME_ERROR_NOTIFICATION,
|
105 |
command, exception)); |
106 |
} |
107 |
|
108 |
public void setSaved(boolean saved) { |
109 |
this.saved = saved;
|
110 |
} |
111 |
|
112 |
public String getCode() { |
113 |
if (this.code == null) { |
114 |
File f=null; |
115 |
try {
|
116 |
f = this.getFileResource(this.extension); |
117 |
this.code = FileUtils.readFileToString(f);
|
118 |
} catch (IOException e) { |
119 |
String fname = (f==null)? "(null)":f.getAbsolutePath(); |
120 |
logger.warn("Can't load code from file '"+fname+"'."); |
121 |
} |
122 |
} |
123 |
return this.code; |
124 |
} |
125 |
|
126 |
public void setCode(String code) { |
127 |
this.code = code;
|
128 |
this.engine = null; |
129 |
this.compiledCode = null; |
130 |
this.setSaved(false); |
131 |
} |
132 |
|
133 |
private String getPreparedCode() { |
134 |
return this.getCode(); |
135 |
} |
136 |
|
137 |
protected String getCodeToInitializeEngine() { |
138 |
if( "python".equalsIgnoreCase(this.getLangName()) ) { |
139 |
List<File> libFolders = this.manager.getLibFolders(); |
140 |
if (libFolders == null || libFolders.size() < 1) { |
141 |
return null; |
142 |
} |
143 |
StringBuffer buffer = new StringBuffer(); |
144 |
buffer.append("import sys\n");
|
145 |
for (File file : libFolders) { |
146 |
buffer.append("sys.path.append(r'");
|
147 |
buffer.append(file.getAbsolutePath()); |
148 |
buffer.append("')\n");
|
149 |
} |
150 |
buffer.append("load = script.load\n");
|
151 |
return buffer.toString();
|
152 |
} |
153 |
return null; |
154 |
} |
155 |
|
156 |
protected ScriptEngine getEngine() {
|
157 |
if (this.engine == null) { |
158 |
ScriptEngine scriptEngine = this.manager.getEngine(this |
159 |
.getLangName()); |
160 |
scriptEngine.put("script", this); |
161 |
this.engine = scriptEngine;
|
162 |
try {
|
163 |
String code = this.getCodeToInitializeEngine(); |
164 |
if( code != null ) { |
165 |
this.engine.eval(code);
|
166 |
} |
167 |
} catch(Exception ex) { |
168 |
logger.warn("Can't initialize engine with the code:\n"+code);
|
169 |
} |
170 |
} |
171 |
return this.engine; |
172 |
} |
173 |
|
174 |
protected void loadInf(Ini prefs) { |
175 |
super.loadInf(prefs);
|
176 |
|
177 |
this.setMainName((String) getInfValue(prefs, "Script", "main", "main")); |
178 |
this.setLangName((String) getInfValue(prefs, "Script", "Lang", |
179 |
this.getLangName()));
|
180 |
} |
181 |
|
182 |
public void load(ScriptingFolder folder, String id) { |
183 |
this.setId(id);
|
184 |
this.setParent(folder);
|
185 |
|
186 |
Map<String, String> languages = this.manager |
187 |
.getSupportedLanguagesByExtension(); |
188 |
String extension = FilenameUtils.getExtension(id);
|
189 |
String langName = languages.get(extension);
|
190 |
this.setLangName(langName);
|
191 |
this.setExtension(extension);
|
192 |
|
193 |
File f = getFileResource(".inf"); |
194 |
if (f.isFile()) {
|
195 |
Ini prefs = null;
|
196 |
try {
|
197 |
prefs = new Ini(f);
|
198 |
} catch (Exception e) { |
199 |
logger.warn("Can't load 'inf' file '"+f.getAbsolutePath()+"'.",e); |
200 |
} |
201 |
loadInf(prefs); |
202 |
} |
203 |
this.setSaved(true); |
204 |
} |
205 |
|
206 |
public void save() { |
207 |
File f = getFileResource(".inf"); |
208 |
if (!f.isFile()) {
|
209 |
try {
|
210 |
f.createNewFile(); |
211 |
} catch (Exception e) { |
212 |
logger.warn("Can't create 'inf' file '"+f.getAbsolutePath()+"'.",e); |
213 |
} |
214 |
} |
215 |
Ini prefs = null;
|
216 |
try {
|
217 |
prefs = new Ini(f);
|
218 |
} catch (Exception e) { |
219 |
logger.warn("Can't load 'inf' file '"+f.getAbsolutePath()+"'.",e); |
220 |
} |
221 |
save(prefs); |
222 |
// Guardo el codigo en el fichero
|
223 |
File fcode = null; |
224 |
try {
|
225 |
fcode = this.getFileResource(this.getExtension()); |
226 |
FileUtils.write(fcode, this.getCode());
|
227 |
} catch (Exception e) { |
228 |
logger.warn("Can't write code to file '"+fcode.getAbsolutePath()+"'.",e); |
229 |
} |
230 |
this.setSaved(true); |
231 |
} |
232 |
|
233 |
protected void save(Ini prefs) { |
234 |
super.save(prefs);
|
235 |
prefs.put("Script", "main", this.getMainName()); |
236 |
prefs.put("Script", "Lang", this.getLangName()); |
237 |
try {
|
238 |
prefs.store(); |
239 |
} catch (IOException e) { |
240 |
String fname = (prefs.getFile()==null)? "(null)" : prefs.getFile().getAbsolutePath(); |
241 |
logger.warn("Can't save inf file ("+fname+").",e); |
242 |
} |
243 |
|
244 |
} |
245 |
|
246 |
public String getLangName() { |
247 |
return this.langName; |
248 |
} |
249 |
|
250 |
protected void setLangName(final String langName) { |
251 |
this.langName = langName;
|
252 |
this.extension = this.manager.getExtensionByLanguage(this.langName); |
253 |
} |
254 |
|
255 |
public String[] getIconNames() { |
256 |
return new String[] { |
257 |
"scripting_" + this.getLangName().toLowerCase(), |
258 |
"scripting_" + this.getLangName().toLowerCase() + "_open" |
259 |
}; |
260 |
} |
261 |
|
262 |
public String getMainName() { |
263 |
return this.mainName; |
264 |
} |
265 |
|
266 |
public void setMainName(final String mainName) { |
267 |
this.mainName = mainName;
|
268 |
} |
269 |
|
270 |
public String getExtension() { |
271 |
return this.extension; |
272 |
} |
273 |
|
274 |
public void setExtension(final String extension) { |
275 |
if( !extension.startsWith(".") ) { |
276 |
this.extension = "." + extension; |
277 |
} else {
|
278 |
this.extension = extension;
|
279 |
} |
280 |
} |
281 |
|
282 |
public boolean isSaved() { |
283 |
return this.saved; |
284 |
} |
285 |
|
286 |
public void addObserver(final Observer o) { |
287 |
this.delegatedObservable.addObserver(o);
|
288 |
} |
289 |
|
290 |
public void deleteObserver(final Observer o) { |
291 |
this.delegatedObservable.deleteObserver(o);
|
292 |
} |
293 |
|
294 |
public void deleteObservers() { |
295 |
this.delegatedObservable.deleteObservers();
|
296 |
} |
297 |
|
298 |
public void put(final String name, final Object value) { |
299 |
this.getEngine().put(name, value);
|
300 |
} |
301 |
|
302 |
public void compile() { |
303 |
if (this.compiledCode == null) { |
304 |
ScriptEngine engine = this.getEngine();
|
305 |
if (engine instanceof Compilable) { |
306 |
try {
|
307 |
Compilable compilable = (Compilable) engine; |
308 |
this.compiledCode = compilable.compile(this.getPreparedCode()); |
309 |
this.compiledCode.eval();
|
310 |
} catch (ScriptException e) {
|
311 |
CompileErrorException ce = new CompileErrorException(e.getMessage(), this.getName(), e.getLineNumber(), e.getColumnNumber(), e); |
312 |
notifyErrors(ce, "compile");
|
313 |
throw ce;
|
314 |
} catch (Throwable e) { |
315 |
CompileErrorException ce = new CompileErrorException(e.getMessage(), this.getName(), e); |
316 |
notifyErrors(new Exception(e), "compile"); |
317 |
throw ce;
|
318 |
} |
319 |
} |
320 |
} |
321 |
} |
322 |
|
323 |
public Object run() { |
324 |
return this.run(null); |
325 |
} |
326 |
|
327 |
public void addDisposable(Disposable disposable){ |
328 |
//pass
|
329 |
} |
330 |
|
331 |
public Object run(Object args[]) { |
332 |
if (args == null) { |
333 |
args = new Object[] {}; |
334 |
} |
335 |
this.compile();
|
336 |
return this.invokeFunction(this.getMainName(), args); |
337 |
} |
338 |
|
339 |
public Object invokeFunction(final String name, Object args[]) { |
340 |
if (this.getEngine() instanceof Invocable) { |
341 |
Invocable invocable = (Invocable) this.getEngine();
|
342 |
this.compile();
|
343 |
if( args == null ) { |
344 |
args = new Object[] {}; |
345 |
} |
346 |
try {
|
347 |
return invocable.invokeFunction(name, args);
|
348 |
} catch (ScriptException e) {
|
349 |
ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getName(), e.getLineNumber(), e.getColumnNumber(), e); |
350 |
notifyErrors(ee, "invoke");
|
351 |
throw ee;
|
352 |
} catch (Throwable e) { |
353 |
ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getName(), e); |
354 |
notifyErrors(ee, "invoke");
|
355 |
throw ee;
|
356 |
} |
357 |
} else {
|
358 |
return null; |
359 |
} |
360 |
} |
361 |
|
362 |
public Object invokeMethod(final Object obj, final String name, Object[] args) |
363 |
throws NoSuchMethodException { |
364 |
|
365 |
if (this.getEngine() instanceof Invocable) { |
366 |
Invocable invocable = (Invocable) this.getEngine();
|
367 |
this.compile();
|
368 |
if( args == null ) { |
369 |
args = new Object[] {}; |
370 |
} |
371 |
try {
|
372 |
return invocable.invokeMethod(obj, name, args);
|
373 |
} catch (ScriptException e) {
|
374 |
ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getName(), e.getLineNumber(), e.getColumnNumber(), e); |
375 |
notifyErrors(ee, "invoke");
|
376 |
throw ee;
|
377 |
} catch (Throwable e) { |
378 |
ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getName(), e); |
379 |
notifyErrors(ee, "invoke");
|
380 |
throw ee;
|
381 |
} |
382 |
} else {
|
383 |
return null; |
384 |
} |
385 |
} |
386 |
|
387 |
public File getResource(String filename) { |
388 |
return new File( this.getParent().getFile(), filename); |
389 |
} |
390 |
|
391 |
class ScriptTask extends AbstractMonitorableTask { |
392 |
|
393 |
ScriptingBaseScript script = null;
|
394 |
Object[] args = null; |
395 |
|
396 |
protected ScriptTask(ScriptingBaseScript script, Object[] args) { |
397 |
super(script.getName(),false); |
398 |
this.args = args;
|
399 |
this.script = script;
|
400 |
this.script.put("task",this); |
401 |
this.script.put("taskStatus",this.getTaskStatus()); |
402 |
} |
403 |
|
404 |
public void run() { |
405 |
try {
|
406 |
console_println("Running script "+ this.script.getName()+"."); |
407 |
script.run(this.args);
|
408 |
console_println("Script "+ this.script.getName()+ " terminated."); |
409 |
} catch(Throwable e) { |
410 |
console_println("Stript "+ this.script.getName()+ " aborted."); |
411 |
} finally {
|
412 |
this.taskStatus.terminate();
|
413 |
try {
|
414 |
Thread.sleep(3000); |
415 |
} catch (InterruptedException e) { |
416 |
// Ignore
|
417 |
} |
418 |
this.taskStatus.remove();
|
419 |
} |
420 |
} |
421 |
|
422 |
public void showTaskStatus() { |
423 |
this.taskStatus.add();
|
424 |
} |
425 |
} |
426 |
|
427 |
public void runAsTask(Object[] args) { |
428 |
ScriptTask task = new ScriptTask(this, args); |
429 |
task.start(); |
430 |
} |
431 |
|
432 |
public boolean remove() { |
433 |
boolean r = true; |
434 |
File folder = this.getParent().getFile(); |
435 |
File f = null; |
436 |
try {
|
437 |
f = new File(folder,this.getId()+".inf"); |
438 |
FileUtils.forceDelete(f); |
439 |
} catch (IOException e) { |
440 |
logger.warn("Can't remove inf file '"+f.getAbsolutePath()+"'.",e); |
441 |
r = false;
|
442 |
} |
443 |
try {
|
444 |
f = new File(folder,this.getId()+this.getExtension()); |
445 |
FileUtils.forceDelete(f); |
446 |
} catch (IOException e) { |
447 |
logger.warn("Can't remove code file '"+f.getAbsolutePath()+"'.",e); |
448 |
r = false;
|
449 |
} |
450 |
return r;
|
451 |
} |
452 |
|
453 |
public void create(ScriptingFolder folder, String id, String language) { |
454 |
this.setParent(folder);
|
455 |
this.setId(id);
|
456 |
if( language==null ) { |
457 |
this.setLangName("python"); |
458 |
} else {
|
459 |
this.setLangName(language);
|
460 |
} |
461 |
this.setExtension(this.manager.getExtensionByLanguage(getLangName())); |
462 |
|
463 |
File file = new File(folder.getFile(),id +".inf"); |
464 |
try {
|
465 |
file.createNewFile(); |
466 |
} catch (IOException e) { |
467 |
logger.warn("Can't create file of the dialog in '"+file.getAbsolutePath()+"'.",e); |
468 |
} |
469 |
|
470 |
if( "python".equalsIgnoreCase(this.getLangName()) ) { |
471 |
this.setCode("\nfrom gvsig import *\n\ndef main(*args):\n #Remove this lines and add here your code\n\n print \"hola mundo\"\n pass\n\n"); |
472 |
} |
473 |
this.save();
|
474 |
} |
475 |
|
476 |
public ScriptingUnit get(String name) { |
477 |
return this.manager.getScript(name); |
478 |
} |
479 |
} |