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