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

History | View | Annotate | Download (26.1 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
        try {
151
            ScriptEngine engine = this.getEngine();
152
            this.compile();
153
            return engine.get(name);
154
        } catch(Exception ex) {
155
            return null;
156
        }
157
    }
158

    
159
    public void __setattr__(String name, Object value) {
160
        ScriptEngine engine = this.getEngine();
161
        this.compile();
162
        engine.put(name, value);
163
    }
164

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

    
169
    public Object __call__(Object[] args) {
170
        return this.run(args);
171
    }
172

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

    
187

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

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

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

    
252
    public ScriptEngine getEngine() {
253
        if (this.engine == null) {
254
            synchronized(this.getManager()) {
255
                ScriptEngine scriptEngine = this.manager.getEngineByLanguage(langName, this.getIsolationGroup());
256

    
257
                scriptEngine.put("script", this);
258
                scriptEngine.put("Main", Main.class);
259
                scriptEngine.getContext().setWriter(stdout);
260
                scriptEngine.getContext().setErrorWriter(stderr);
261

    
262
                this.engine = scriptEngine;
263
                String code = this.getCodeToInitializeEngine();
264
                if (code != null) {
265
                    try {
266
                        this.engine.eval(code);
267
                    } catch (Exception ex) {
268
                        logger.warn("Can't initialize engine with the code:\n" + code, ex);
269
                    }
270
                }
271
            }
272
        }
273
        return this.engine;
274
    }
275

    
276
    @Override
277
    protected void loadInf(Ini prefs) {
278
        super.loadInf(prefs);
279

    
280
        this.setMainName((String) getInfValue(prefs, "Script", "main", "main"));
281
        this.setLangName((String) getInfValue(prefs, "Script", "Lang",this.getLangName()));
282
        this.setLibrarySuffix((String) getInfValue(prefs, "Script", "LibraryVersion",null));
283
    }
284

    
285
    @Override
286
    public void load(ScriptingFolder folder, String id) {
287
        this.setId(id);
288
        this.setParent(folder);
289

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

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

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

    
355
    }
356

    
357
    @Override
358
    public String getLangName() {
359
        return this.langName;
360
    }
361

    
362
    protected void setLangName(final String langName) {
363
        if( langName == null ) {
364
            return;
365
        }
366
        this.langName = langName;
367
        this.setExtension(this.manager.getExtensionOfLanguage(this.langName));
368
    }
369

    
370
    @Override
371
    public String[] getIconNames() {
372
        return new String[]{
373
            "scripting_" + this.getLangName().toLowerCase(),
374
            "scripting_" + this.getLangName().toLowerCase() + "_open"
375
        };
376
    }
377

    
378
    @Override
379
    public String getMainName() {
380
        return this.mainName;
381
    }
382

    
383
    @Override
384
    public void setMainName(final String mainName) {
385
        this.mainName = mainName;
386
    }
387
    
388
    @Override
389
    public List<File> getFiles() {
390
        List<File> l = new ArrayList<>();
391
        l.add(this.getScriptFile());
392
        return l;
393
    }
394

    
395
    public String getExtension() {
396
        return this.extension;
397
    }
398

    
399
    public void setExtension(final String extension) {
400
        if (!extension.startsWith(".")) {
401
            this.extension = "." + extension;
402
        } else {
403
            this.extension = extension;
404
        }
405
    }
406

    
407
    @Override
408
    public void addObserver(final Observer o) {
409
        this.delegatedObservable.addObserver(o);
410
    }
411

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

    
417
    @Override
418
    public void deleteObservers() {
419
        this.delegatedObservable.deleteObservers();
420
    }
421

    
422
    @Override
423
    public void put(final String name, final Object value) {
424
        this.getEngine().put(name, value);
425
    }
426

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

    
482
    public void addDisposable(Disposable disposable) {
483
        //pass
484
    }
485

    
486
    /**
487
     * Run the main function of this script.
488
     * This method is created by familiarity when running the script from another script.
489
     * @return 
490
     */
491
    public Object main() {
492
        return this.run(null);
493
    }
494

    
495
    /**
496
     * Run the main function of this script.
497
     * This method is created by familiarity when running the script from another script.
498
     * @param args
499
     * @return 
500
     */
501
    public Object main(Object... args) {
502
        return this.run(args);
503
    }
504

    
505
        
506
    @Override
507
    public Object run() {
508
        return this.run(null);
509
    }
510

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

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

    
557
        } catch (Error | Exception e) {
558
            ExecuteErrorException ee = new ExecuteErrorException(e.getMessage(), this.getScriptFile(), e);
559
            notifyErrors(ee, "invoke");
560
            throw ee;
561
        }
562
    }
563

    
564
    @Override
565
    public File getScriptFile() {
566
        return this.getFileResource(extension);
567
    }
568

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

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

    
629
    @Override
630
    public File getResource(String filename) {
631
        return new File(this.getParent().getFile(), filename);
632
    }
633

    
634
    @Override
635
    public String getMimeType() {
636
        return "text/"+ this.getLangName();
637
    }
638

    
639
    @Override
640
    protected void console_println(String s) {
641
        super.console_println(s);
642
        try {
643
            this.stdout.write(s+"\n");
644
        } catch (IOException ex) {
645
        }
646
    }
647

    
648
    class ScriptTask extends AbstractMonitorableTask {
649

    
650
        ScriptingBaseScript script = null;
651
        Object[] args = null;
652

    
653
        protected ScriptTask(ScriptingBaseScript script, Object[] args) {
654
            super(script.getName(), false);
655
            this.args = args;
656
            this.script = script;
657
            this.script.put("task", this);
658
            this.script.put("taskStatus", this.getTaskStatus());
659
        }
660

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

    
680
        public void showTaskStatus() {
681
            this.taskStatus.add();
682
        }
683
    }
684

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

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

    
716
    @Override
717
    public void create(ScriptingFolder folder, String id, String language) {
718
        this.setParent(folder);
719
        this.setId(id);
720
        if (language == null) {
721
            this.setLangName("python");
722
        } else {
723
            this.setLangName(language);
724
        }
725
        this.setExtension(this.manager.getExtensionOfLanguage(getLangName()));
726

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

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

    
764
    public ScriptingUnit get(File file) {
765
        return this.manager.getScript(file);
766
    }
767

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

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

    
816
}