Statistics
| Revision:

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 @ 724

History | View | Annotate | Download (26.6 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.io.PrintStream;
7
import java.io.Writer;
8
import java.nio.charset.Charset;
9
import java.util.ArrayList;
10
import java.util.HashSet;
11
import java.util.List;
12
import java.util.Set;
13

    
14
import javax.script.Compilable;
15
import javax.script.CompiledScript;
16
import javax.script.Invocable;
17
import javax.script.ScriptEngine;
18
import javax.script.ScriptException;
19

    
20
import org.apache.commons.io.FileUtils;
21
import org.apache.commons.io.FilenameUtils;
22
import org.apache.commons.io.IOUtils;
23
import org.apache.commons.lang3.StringUtils;
24
import org.apache.commons.lang3.exception.ExceptionUtils;
25
import org.gvsig.scripting.CompileErrorException;
26
import org.gvsig.scripting.ExecuteErrorException;
27
import org.gvsig.scripting.Main;
28
import org.gvsig.scripting.ScriptingBaseScript;
29
import org.gvsig.scripting.ScriptingFolder;
30
import org.gvsig.scripting.ScriptingManager;
31
import org.gvsig.scripting.ScriptingScript;
32
import org.gvsig.scripting.ScriptingUnit;
33
import org.gvsig.tools.dispose.Disposable;
34
import org.gvsig.tools.observer.Observer;
35
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
36
import org.gvsig.tools.task.AbstractMonitorableTask;
37
import org.ini4j.Ini;
38
import org.python.core.PyException;
39
import org.python.core.PyString;
40
import org.python.core.PyTraceback;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

    
44
public class DefaultScriptingScript extends AbstractScript implements
45
        ScriptingScript {
46

    
47
    private static final Logger logger = LoggerFactory.getLogger(DefaultScriptingScript.class);
48
    protected String langName;
49
    protected String extension = null;
50
    protected String librarySuffix = null;
51
    protected ScriptEngine engine = null;
52
    protected CompiledScript compiledCode;
53

    
54
    private String code = null;
55
    private String mainName = "main";
56
    private final DelegateWeakReferencingObservable delegatedObservable;
57
    private OutputWriter stdout;
58
    private OutputWriter stderr;
59

    
60
    public static class OutputWriter extends Writer {
61

    
62
        private final Set<Writer> writers = new HashSet<>();
63
        private final PrintStream out;
64

    
65
        private OutputWriter(PrintStream out) {
66
            this.out = out;
67
        }
68

    
69
        @Override
70
        public void write(char[] cbuf, int off, int len) throws IOException {
71
            try {
72
                byte[] buf = new String(cbuf).getBytes(Charset.forName("UTF-8"));
73
                out.write(buf, off, len);
74
            } catch (Exception ex) {
75
                logger.warn("Can't output",ex);
76
            }
77
            for (Writer writer : writers) {
78
                try {
79
                    writer.write(cbuf, off, len);
80
                } catch (Exception ex) {
81
                    logger.warn("Can't output",ex);
82
                }
83
            }
84
        }
85

    
86
        @Override
87
        public void flush() throws IOException {
88
            try {
89
                out.flush();
90
            } catch (Exception ex) {
91
                logger.warn("Can't flush",ex);
92
            }
93
            for (Writer writer : writers) {
94
                try {
95
                    writer.flush();
96
                } catch (Exception ex) {
97
                    logger.warn("Can't flush",ex);
98
                }
99
            }
100
        }
101

    
102
        @Override
103
        public void close() throws IOException {
104
        }
105

    
106
        private void addWriter(Writer out) {
107
            this.writers.add(out);
108
        }
109

    
110
        private void removeWriter(Writer out) {
111
            this.writers.remove(out);
112
        }
113

    
114
    }
115

    
116
    protected DefaultScriptingScript(ScriptingFolder parent, String typename, ScriptingManager manager, String id) {
117
        super(parent, typename, manager, id);
118
        this.setLangName("python");
119
        this.setSaved(true);
120
        this.delegatedObservable = new DelegateWeakReferencingObservable(this);
121
        this.stdout = new OutputWriter(System.out);
122
        this.stderr = new OutputWriter(System.err);
123
    }
124

    
125
    public DefaultScriptingScript(ScriptingFolder parent, ScriptingManager manager, String id) {
126
        this(parent, ScriptingManager.UNIT_SCRIPT, manager, id);
127
    }
128

    
129
    @Override
130
    public void addStdoutWriter(Writer out) {
131
        this.stdout.addWriter(out);
132
    }
133
    
134
    @Override
135
    public void addStderrWriter(Writer err) {
136
        this.stderr.addWriter(err);
137
    }
138
    
139
    @Override
140
    public void removeStdoutWriter(Writer out) {
141
        this.stdout.removeWriter(out);
142
    }
143
    
144
    @Override
145
    public void removeStderrWriter(Writer err) {
146
        this.stdout.removeWriter(err);
147
    }
148
    
149
    public Object __getattr__(String name) {
150
        ScriptEngine engine = this.getEngine();
151
        this.compile();
152
        return engine.get(name);
153
    }
154

    
155
    public void __setattr__(String name, Object value) {
156
        ScriptEngine engine = this.getEngine();
157
        this.compile();
158
        engine.put(name, value);
159
    }
160

    
161
    public Object __call__() {
162
        return this.run();
163
    }
164

    
165
    public Object __call__(Object[] args) {
166
        return this.run(args);
167
    }
168

    
169
    public OutputWriter getStdout() {
170
        return this.stdout;
171
    }
172
    
173
    public OutputWriter getStderr() {
174
        return this.stderr;
175
    }
176
    
177
    protected void notifyErrors(Exception exception, String command) {
178
        this.delegatedObservable.notifyObservers(new BaseScriptingNotifycation(
179
                this, BaseScriptingNotifycation.RUNTIME_ERROR_NOTIFICATION,
180
                command, exception));
181
    }
182

    
183

    
184
    @Override
185
    public String getCode() {
186
        if (this.code == null) {
187
            File f = null;
188
            try {
189
                f = this.getFileResource(this.extension);
190
                this.code = FileUtils.readFileToString(f);
191
            } catch (IOException e) {
192
                String fname = (f == null) ? "(null)" : f.getAbsolutePath();
193
                logger.warn("Can't load code from file '" + fname + "'.");
194
            }
195
        }
196
        return this.code;
197
    }
198

    
199
    @Override
200
    public void setCode(String code) {
201
        this.code = code;
202
        this.engine = null;
203
        this.compiledCode = null;
204
        this.setSaved(false);
205
    }
206
    
207
    @Override
208
    public String getLibrarySuffix() {
209
        return this.librarySuffix;
210
    }
211

    
212
    @Override
213
    public void setLibrarySuffix(String librarySuffix) {
214
        this.librarySuffix = librarySuffix;
215
    }
216
    
217
    public List<File> getLibFolders() {
218
        List<File> folders = this.manager.getLibFolders();
219
        String suffix = this.getLibrarySuffix();
220
        if( suffix == null ) {
221
            return folders;
222
        }
223
        for( int i=0; i<folders.size(); i++) {
224
            File folder = folders.get(i);
225
            File f = new File(folder.getParentFile(),folder.getName()+suffix);
226
            if( f.exists() ) {
227
                folders.set(i, f);
228
            }
229
        }
230
        return folders;
231
    }
232
    
233
    protected String getCodeToInitializeEngine() {
234
        String name = "org/gvsig/scripting/langs/"+this.getLangName().toLowerCase()+"/init.txt";
235
        try {
236
            InputStream template = this.getClass().getClassLoader().getResourceAsStream(name);
237
            if( template == null ) {
238
                return null;
239
            }
240
            List<String> lines = IOUtils.readLines(template);
241
            return StringUtils.join(lines, "\n");
242
        } catch (Exception ex) {
243
            logger.warn("Can't load code to initialize the script from '"+name+".",ex);
244
            return null;
245
        }
246
    }
247

    
248
    public ScriptEngine getEngine() {
249
        if (this.engine == null) {
250
            ScriptEngine scriptEngine;
251
            if( this.getIsolation() == ISOLATION_HIGH) {
252
                scriptEngine = this.manager.createEngineByLanguage(langName);            
253
            } else {
254
                scriptEngine = this.manager.getEngineByLanguage(langName);
255
            }
256
            if( "scala".equalsIgnoreCase(langName) ) {
257
                try {
258
                    // https://gist.github.com/takawitter/5479445
259
                    Object settings = scriptEngine.getClass().getMethod("settings", new Class[0]).invoke(scriptEngine, new Object[0]);
260
                    settings.getClass().getMethod("processArgumentString", new Class[] { String.class }).invoke(settings, new String[] { "-usejavacp"});
261
                } catch(Throwable th) {
262
                    logger.warn("Can't initialice scala setting -usejavacp",th);
263
                }
264
            }
265
            scriptEngine.put("script", this);
266
            scriptEngine.put("Main", Main.class);
267
            scriptEngine.getContext().setWriter(stdout);
268
            scriptEngine.getContext().setErrorWriter(stderr);
269
            
270
            this.engine = scriptEngine;
271
            String code = this.getCodeToInitializeEngine();
272
            if (code != null) {
273
                try {
274
                    this.engine.eval(code);
275
                } catch (Exception ex) {
276
                    logger.warn("Can't initialize engine with the code:\n" + code, ex);
277
                }
278
            }
279
        }
280
        return this.engine;
281
    }
282

    
283
    @Override
284
    protected void loadInf(Ini prefs) {
285
        super.loadInf(prefs);
286

    
287
        this.setMainName((String) getInfValue(prefs, "Script", "main", "main"));
288
        this.setLangName((String) getInfValue(prefs, "Script", "Lang",this.getLangName()));
289
        this.setLibrarySuffix((String) getInfValue(prefs, "Script", "LibraryVersion",null));
290
    }
291

    
292
    @Override
293
    public void load(ScriptingFolder folder, String id) {
294
        this.setId(id);
295
        this.setParent(folder);
296

    
297
        String extension = FilenameUtils.getExtension(id);
298
        if( extension != null ) {
299
            String language = this.manager.getLanguageOfExtension(extension);
300
            if( language != null ) {
301
                this.setLangName(language);
302
            }
303
            this.setExtension(extension);
304
        }
305
        File f = getFileResource(".inf");
306
        if (f.isFile()) {
307
            Ini prefs = null;
308
            try {
309
                prefs = new Ini(f);
310
            } catch (Exception e) {
311
                logger.warn("Can't load 'inf' file '" + f.getAbsolutePath() + "'.", e);
312
            }
313
            loadInf(prefs);
314
        }
315
        this.setSaved(true);
316
    }
317

    
318
    @Override
319
    public void save() {
320
        this.saveInfo();
321
        // Guardo el codigo en el fichero
322
        File fcode = this.getFileResource(this.getExtension());
323
        try {
324
            FileUtils.write(fcode, this.getCode());
325
        } catch (Exception e) {
326
            logger.warn("Can't write code to file '" + fcode.getAbsolutePath() + "'.", e);
327
        }
328
        this.setSaved(true);
329
    }
330

    
331
    private void saveInfo() {
332
        File f = getFileResource(".inf");
333
        if (!f.isFile()) {
334
            try {
335
                f.createNewFile();
336
            } catch (Exception e) {
337
                logger.warn("Can't create 'inf' file '" + f.getAbsolutePath() + "'.", e);
338
            }
339
        }
340
        Ini prefs = null;
341
        try {
342
            prefs = new Ini(f);
343
        } catch (Exception e) {
344
            logger.warn("Can't load 'inf' file '" + f.getAbsolutePath() + "'.", e);
345
        }
346
        save(prefs);
347
    }
348
    
349
    @Override
350
    protected void save(Ini prefs) {
351
        super.save(prefs);
352
        prefs.put("Script", "main", this.getMainName());
353
        prefs.put("Script", "Lang", this.getLangName());
354
        try {
355
            prefs.store();
356
        } catch (IOException e) {
357
            String fname = (prefs.getFile() == null) ? "(null)" : prefs.getFile().getAbsolutePath();
358
            logger.warn("Can't save inf file (" + fname + ").", e);
359
        }
360

    
361
    }
362

    
363
    @Override
364
    public String getLangName() {
365
        return this.langName;
366
    }
367

    
368
    protected void setLangName(final String langName) {
369
        if( langName == null ) {
370
            return;
371
        }
372
        this.langName = langName;
373
        this.setExtension(this.manager.getExtensionOfLanguage(this.langName));
374
    }
375

    
376
    @Override
377
    public String[] getIconNames() {
378
        return new String[]{
379
            "scripting_" + this.getLangName().toLowerCase(),
380
            "scripting_" + this.getLangName().toLowerCase() + "_open"
381
        };
382
    }
383

    
384
    @Override
385
    public String getMainName() {
386
        return this.mainName;
387
    }
388

    
389
    @Override
390
    public void setMainName(final String mainName) {
391
        this.mainName = mainName;
392
    }
393
    
394
    @Override
395
    public List<File> getFiles() {
396
        List<File> l = new ArrayList<>();
397
        l.add(this.getScriptFile());
398
        return l;
399
    }
400

    
401
    public String getExtension() {
402
        return this.extension;
403
    }
404

    
405
    public void setExtension(final String extension) {
406
        if (!extension.startsWith(".")) {
407
            this.extension = "." + extension;
408
        } else {
409
            this.extension = extension;
410
        }
411
    }
412

    
413
    @Override
414
    public void addObserver(final Observer o) {
415
        this.delegatedObservable.addObserver(o);
416
    }
417

    
418
    @Override
419
    public void deleteObserver(final Observer o) {
420
        this.delegatedObservable.deleteObserver(o);
421
    }
422

    
423
    @Override
424
    public void deleteObservers() {
425
        this.delegatedObservable.deleteObservers();
426
    }
427

    
428
    @Override
429
    public void put(final String name, final Object value) {
430
        this.getEngine().put(name, value);
431
    }
432

    
433
    @Override
434
    public void compile() {
435
        if (this.compiledCode == null) {
436
            ScriptEngine engine = this.getEngine();
437
            if (engine instanceof Compilable) {
438
                try {
439
                    Compilable compilable = (Compilable) engine;
440
                    String code = this.getCode();
441
                    if( "python".equalsIgnoreCase(this.getLangName()) ) {
442
                        // If a Unicode string with a coding declaration is passed to compile(),
443
                        // a SyntaxError will be raised, but this is necessary to import from 
444
                        // another module, so we remove it.
445
                        // http://bugs.jython.org/issue1696
446
                        code = code.replaceFirst("^\\s*#([^:\\n]*)coding:","#$1 c-o-d-i-n-g:");
447
                    }
448
                    this.compiledCode = compilable.compile(code);
449
                    if( engine instanceof Invocable) {
450
                        this.compiledCode.eval();
451
                    }
452
                } catch (ScriptException e) {
453
                    Object[] location = this.getLocation(e);
454
                    CompileErrorException ce = new CompileErrorException(
455
                            e.getMessage(), 
456
                            (File) location[0], 
457
                            (int) location[1], 
458
                            (int) location[2], 
459
                            e
460
                    );
461
                    notifyErrors(ce, "compile");
462
                    throw ce;
463
                } catch (Throwable e) {
464
                    CompileErrorException ce = new CompileErrorException(e.getMessage(), this.getScriptFile(), e);
465
                    notifyErrors(new Exception(e), "compile");
466
                    throw ce;
467
                }
468
            } else {
469
                String code = this.getCode();
470
                try {
471
                    engine.eval(code);
472
                } catch (ScriptException e) {
473
                    Object[] location = this.getLocation(e);
474
                    CompileErrorException ce = new CompileErrorException(
475
                            e.getMessage(), 
476
                            (File) location[0], 
477
                            (int) location[1], 
478
                            (int) location[2], 
479
                            e
480
                    );                    
481
                    notifyErrors(ce, "compile");
482
                    throw ce;
483
                }
484
            }
485
        }
486
    }
487

    
488
    public void addDisposable(Disposable disposable) {
489
        //pass
490
    }
491

    
492
    /**
493
     * Run the main function of this script.
494
     * This method is created by familiarity when running the script from another script.
495
     * @return 
496
     */
497
    public Object main() {
498
        return this.run(null);
499
    }
500

    
501
    /**
502
     * Run the main function of this script.
503
     * This method is created by familiarity when running the script from another script.
504
     * @param args
505
     * @return 
506
     */
507
    public Object main(Object... args) {
508
        return this.run(args);
509
    }
510

    
511
        
512
    @Override
513
    public Object run() {
514
        return this.run(null);
515
    }
516

    
517
    @Override
518
    public Object run(Object args[]) {
519
        if( !this.isEnabled() ) {
520
            System.err.printf("The script '"+this.getName()+"' is not enabled, see properties page to change.\n");
521
            return null;
522
        }
523
        if (args == null) {
524
            args = new Object[]{};
525
        }
526
        this.compile();
527
        return this.invokeFunction(this.getMainName(), args);
528
    }
529

    
530
    @Override
531
    public Object invokeFunction(final String name, Object args[]) {
532
        try {
533
            if (this.getEngine() instanceof Invocable) {
534
                Invocable invocable = (Invocable) this.getEngine();
535
                this.compile();
536
                if (args == null) {
537
                    args = new Object[]{};
538
                }
539
                return invocable.invokeFunction(name, args);
540
            } else {
541
                if (this.compiledCode != null) {
542
                    Object x = this.compiledCode.eval();
543
                    if( x instanceof Main ) {
544
                        return ((Main) x).main(args);
545
                    } else if(x instanceof Runnable) {
546
                        ((Runnable) x).run();
547
                    }
548
                }
549
                return null;
550
            }
551
        } catch (ScriptException e) {
552
            Object[] location = this.getLocation(e);
553
            ExecuteErrorException ee = new ExecuteErrorException(
554
                    e.getMessage(), 
555
                    (File) location[0], 
556
                    (int) location[1], 
557
                    (int) location[2], 
558
                    e
559
            );
560
            notifyErrors(ee, "invoke");
561
            throw ee;
562

    
563
        } catch (Error | Exception e) {
564
            ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getScriptFile(), e);
565
            notifyErrors(ee, "invoke");
566
            throw ee;
567
        }
568
    }
569

    
570
    @Override
571
    public File getScriptFile() {
572
        return this.getFileResource(extension);
573
    }
574

    
575
    private Object[] getLocation(ScriptException e) {
576
        Throwable[] es = ExceptionUtils.getThrowables(e);
577
        Exception dbgex; // Para debug con mas comodidad
578
        for( Throwable t : es) {
579
            if( t instanceof PyException ) {
580
                try {
581
                    PyException pyex = (PyException)t;
582
                    PyTraceback tb = pyex.traceback;
583
                    if( tb!=null ) {
584
                        while( tb.tb_next!=null ) {
585
                            tb = (PyTraceback) tb.tb_next;
586
                        }
587
                        String s = tb.tb_frame.f_globals.__getitem__(new PyString("__file__")).asString();
588
                        if( s.endsWith("$py.class") ) {
589
                            s = s.substring(0, s.length()-9) + ".py";
590
                            File resource = new File(s);
591
                            return new Object[] { resource, tb.tb_lineno, 0};
592
                        }
593
                        return new Object[] { this.getScriptFile(), tb.tb_lineno, 0};
594
                    }
595
                } catch(Exception ex) {
596
                    // Pass
597
                    dbgex = ex;
598
                }
599
            }
600
        }        
601
        int column = e.getColumnNumber();
602
        if( column < 0 ) {
603
            column = 0;
604
        }
605
        return new Object[] { this.getScriptFile(), e.getLineNumber(), column };
606
    }
607
    
608
    
609
    @Override
610
    public Object invokeMethod(final Object obj, final String name, Object[] args)
611
            throws NoSuchMethodException {
612

    
613
        if (this.getEngine() instanceof Invocable) {
614
            Invocable invocable = (Invocable) this.getEngine();
615
            this.compile();
616
            if (args == null) {
617
                args = new Object[]{};
618
            }
619
            try {
620
                return invocable.invokeMethod(obj, name, args);
621
            } catch (ScriptException e) {
622
                ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getScriptFile(), e.getLineNumber(), e.getColumnNumber(), e);
623
                notifyErrors(ee, "invoke");
624
                throw ee;
625
            } catch (Throwable e) {
626
                ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getScriptFile(), e);
627
                notifyErrors(ee, "invoke");
628
                throw ee;
629
            }
630
        } else {
631
            return null;
632
        }
633
    }
634

    
635
    @Override
636
    public File getResource(String filename) {
637
        return new File(this.getParent().getFile(), filename);
638
    }
639

    
640
    @Override
641
    public String getMimeType() {
642
        return "text/"+ this.getLangName();
643
    }
644

    
645
    @Override
646
    protected void console_println(String s) {
647
        super.console_println(s);
648
        try {
649
            this.stdout.write(s+"\n");
650
        } catch (IOException ex) {
651
        }
652
    }
653

    
654
    class ScriptTask extends AbstractMonitorableTask {
655

    
656
        ScriptingBaseScript script = null;
657
        Object[] args = null;
658

    
659
        protected ScriptTask(ScriptingBaseScript script, Object[] args) {
660
            super(script.getName(), false);
661
            this.args = args;
662
            this.script = script;
663
            this.script.put("task", this);
664
            this.script.put("taskStatus", this.getTaskStatus());
665
        }
666

    
667
        @Override
668
        public void run() {
669
            try {
670
                console_println("Running script " + this.script.getName() + ".");
671
                script.run(this.args);
672
                console_println("Script " + this.script.getName() + " terminated.");
673
            } catch (Throwable e) {
674
                console_println("Stript " + this.script.getName() + " aborted.");
675
            } finally {
676
                this.taskStatus.terminate();
677
                try {
678
                    Thread.sleep(3000);
679
                } catch (InterruptedException e) {
680
                    // Ignore
681
                }
682
                this.taskStatus.remove();
683
            }
684
        }
685

    
686
        public void showTaskStatus() {
687
            this.taskStatus.add();
688
        }
689
    }
690

    
691
    @Override
692
    public void runAsTask(Object[] args) {
693
        if( !this.isEnabled() ) {
694
            System.err.printf("The script '"+this.getName()+"' is not enabled, see properties page to change.\n");
695
            return;
696
        }
697
        ScriptTask task = new ScriptTask(this, args);
698
        task.start();
699
    }
700

    
701
    @Override
702
    public boolean remove() {
703
        boolean r = true;
704
        File folder = this.getParent().getFile();
705
        File f = new File(folder, this.getId() + ".inf");
706
        try {
707
            FileUtils.forceDelete(f);
708
        } catch (IOException e) {
709
            logger.warn("Can't remove inf file '" + f.getAbsolutePath() + "'.", e);
710
            r = false;
711
        }
712
        try {
713
            f = new File(folder, this.getId() + this.getExtension());
714
            FileUtils.forceDelete(f);
715
        } catch (IOException e) {
716
            logger.warn("Can't remove code file '" + f.getAbsolutePath() + "'.", e);
717
            r = false;
718
        }
719
        return r;
720
    }
721

    
722
    @Override
723
    public void create(ScriptingFolder folder, String id, String language) {
724
        this.setParent(folder);
725
        this.setId(id);
726
        if (language == null) {
727
            this.setLangName("python");
728
        } else {
729
            this.setLangName(language);
730
        }
731
        this.setExtension(this.manager.getExtensionOfLanguage(getLangName()));
732

    
733
        File file = new File(folder.getFile(), id + ".inf");
734
        try {
735
            file.createNewFile();
736
        } catch (IOException e) {
737
            logger.warn("Can't create file of the dialog in '" + file.getAbsolutePath() + "'.", e);
738
        }
739
        File fcode = this.getFileResource(this.getExtension());
740
        if( fcode.exists() ) {
741
            this.saveInfo();
742
        } else {
743
            String template = this.getNewTemplate();
744
            if( template != null ) {
745
                this.setCode(template);
746
            }
747
            this.save();
748
        }
749
    }
750

    
751
    public String getNewTemplate() {
752
        String name = "org/gvsig/scripting/langs/"+this.getLangName().toLowerCase()+"/new_template.txt";
753
        try {
754
            InputStream template = this.getClass().getClassLoader().getResourceAsStream(name);
755
            if( template == null ) {
756
                return null;
757
            }
758
            List<String> lines = IOUtils.readLines(template);
759
            return StringUtils.join(lines, "\n");
760
        } catch (Exception ex) {
761
            logger.warn("Can't load new-template from '"+name+"'.",ex);
762
            return null;
763
        }
764
    }
765
    
766
    public ScriptingUnit get(String name) {
767
        return this.manager.getScript(name);
768
    }
769

    
770
    public ScriptingUnit get(File file) {
771
        return this.manager.getScript(file);
772
    }
773

    
774
    @Override
775
    public boolean move(ScriptingFolder target) {
776
        if (! manager.validateUnitId(target, this.getId()) ) {
777
            logger.info("Can't move script '"+this.getId()+"' to '"+target.getFile().getAbsolutePath()+"', is not valid.");
778
            return false;
779
        }
780
        if( !this.isSaved() ) {
781
            logger.info("Can't move script '"+this.getId()+"', is not saved.");
782
            return false;
783
        }
784
        try {
785
            File codefile = this.getFileResource(this.extension);
786
            FileUtils.moveFileToDirectory(this.getFile(), target.getFile(),true);
787
            FileUtils.moveFileToDirectory(codefile, target.getFile(), true);
788
            this.parent = target;
789
            this.load(target, id);
790
        } catch (IOException ex) {
791
            logger.info("Can't move script '"+this.getId()+"' to '"+target.getFile().getAbsolutePath()+"', "+ex.getMessage(),ex);
792
            return false;
793
        }
794
        return true;
795
    }
796

    
797
    @Override
798
    public boolean rename(String newId) {
799
        if (! manager.validateUnitId(this.getParent(), newId) ) {
800
            logger.info("Can't rename script '"+this.getId()+"', target id '"+newId+"' is not valid.");
801
            return false;
802
        }
803
        if( !this.isSaved() ) {
804
            logger.info("Can't rename script '"+this.getId()+"', is not saved.");
805
            return false;
806
        }
807
        try {
808
            ScriptingFolder target = this.getParent();
809
            File codefile = this.getFileResource(this.extension);
810
            FileUtils.moveFile(this.getFile(),  new File(target.getFile(),newId+".inf") );
811
            FileUtils.moveFile(codefile, new File(target.getFile(),newId+this.extension));
812
            this.setId(newId);
813
            this.saveInfo();
814
            this.load(target, id);
815
        } catch (IOException ex) {
816
            logger.info("Can't rename script '"+this.getId()+"' to '"+newId+"', "+ex.getMessage(),ex);
817
            return false;
818
        }        
819
        return true;
820
    }
821

    
822
}