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 / DefaultScriptingManager.java @ 724

History | View | Annotate | Download (20 KB)

1
package org.gvsig.scripting.impl;
2

    
3
import java.io.File;
4
import java.io.IOException;
5
import java.util.ArrayList;
6
import java.util.Collections;
7
import java.util.HashMap;
8
import java.util.Iterator;
9
import java.util.List;
10
import java.util.Map;
11

    
12
import javax.script.ScriptContext;
13
import javax.script.ScriptEngine;
14
import javax.script.ScriptEngineFactory;
15
import javax.script.ScriptEngineManager;
16
import javax.script.SimpleBindings;
17
import javax.swing.ImageIcon;
18

    
19
import org.apache.commons.io.FileUtils;
20
import org.apache.commons.io.FilenameUtils;
21
import org.gvsig.scripting.ScriptingBaseScript;
22
import org.gvsig.scripting.ScriptingDialog;
23
import org.gvsig.scripting.ScriptingExternalFile;
24
import org.gvsig.scripting.ScriptingFolder;
25
import org.gvsig.scripting.ScriptingHelpManager;
26
import org.gvsig.scripting.ScriptingManager;
27
import org.gvsig.scripting.ScriptingScript;
28
import org.gvsig.scripting.ScriptingUnit;
29
import org.gvsig.tools.script.Script;
30
import org.gvsig.tools.service.spi.ProviderFactory;
31
import org.python.jsr223.MyPyScriptEngine;
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35

    
36
public class DefaultScriptingManager implements ScriptingManager {
37

    
38
    public static class RegisterSystemFolder {
39

    
40
        public String name;
41
        public File folder;
42

    
43
        public RegisterSystemFolder(String name, File folder) {
44
            this.name = name;
45
            this.folder = folder;
46
        }
47
    }
48

    
49
    private static final Logger LOG = LoggerFactory
50
            .getLogger(DefaultScriptingManager.class);
51

    
52
    protected Map<String, ImageIcon> icons;
53
    protected List<RegisterSystemFolder> systemFolders = new ArrayList<>();
54
    protected ScriptEngineManager engineManager = null;
55
    private final SimpleBindings bindings = new SimpleBindings();
56
    private ScriptingHelpManager helpManager = null;
57
    private List<String> unitTypes = null;
58
    private ClassLoader classLoader = null;
59
    private List<File> libFolders = new ArrayList<>();
60
    private File home = null;
61
    private List<ScriptingFolder> alternativeUserFolders = new ArrayList<>();
62
    private Map<String, String> extensionOfLanguage = null;
63
    private Map<String, String> languageOfExtension = null;
64
    private File packagesFolder;
65
    private final Map properties = new HashMap();
66

    
67
    public DefaultScriptingManager() {
68
        this.classLoader = getClass().getClassLoader();
69
        this.setHomeFolder(null);
70
        this.bindings.put("ScriptingManager", this);
71
    }
72

    
73
    public DefaultScriptingManager(ClassLoader classLoader) {
74
        this();
75
        this.classLoader = classLoader;
76
    }
77

    
78
    @Override
79
    public Object getProperty(Object key) {
80
        return properties.get(key);
81
    }
82

    
83
    @Override
84
    public void setProperty(Object key, Object val) {
85
        properties.put(key, val);
86
    }
87

    
88
    @Override
89
    public Map getExtendedProperties() {
90
        return properties;
91
    }
92

    
93
    private void createFolder(File f) {
94
        if (!f.exists()) {
95
            try {
96
                FileUtils.forceMkdir(f);
97
                LOG.info("Created scripting folder '" + f.getAbsolutePath() + "'");
98
            } catch (Throwable e) {
99
                LOG.warn("Can't Create scripting folder '" + f.getAbsolutePath() + "'");
100
            }
101
        }
102
    }
103

    
104
    private void createDefaultFolders(File home) {
105
        createFolder(new File(home, "scripts"));
106
        createFolder(new File(home, "help"));
107
        createFolder(new File(home, "lib"));
108
    }
109

    
110
    @Override
111
    public File getHomeFolder() {
112
        if (!this.home.exists()) {
113
            createFolder(home);
114
            createDefaultFolders(home);
115
        }
116
        return this.home;
117
    }
118

    
119
    @Override
120
    public void setHomeFolder(File home) {
121
        if (home == null) {
122
            this.home = new File(System.getProperty("user.home"), ".gvsig-scripting");
123
        } else {
124
            this.home = home;
125
        }
126
        createDefaultFolders(this.home);
127
        LOG.info("Set scripting home to '" + this.home.getAbsolutePath() + "'");
128
        this.addLibFolder(new File(this.home, "lib"));
129
    }
130

    
131
    protected ScriptEngineManager getEngineManager() {
132
        if (this.engineManager == null) {
133
            this.engineManager
134
                    = classLoader == null ? new ScriptEngineManager()
135
                            : new ScriptEngineManager(classLoader);
136
            showEnginesInfo(engineManager);
137
        }
138
        return this.engineManager;
139
    }
140

    
141
    private void showEnginesInfo(ScriptEngineManager mgr) {
142
        if (LOG.isInfoEnabled()) {
143
            List<ScriptEngineFactory> factories = mgr.getEngineFactories();
144
            StringBuilder buffer = new StringBuilder();
145
            List<Object> values = new ArrayList<>();
146
            buffer.append("Scripting engines available:");
147
            for (ScriptEngineFactory factory : factories) {
148

    
149
                // Main engine info
150
                buffer
151
                        .append("\n- {}: version = {}, language = {}, langVersion = {}");
152
                values.add(factory.getEngineName());
153
                values.add(factory.getEngineVersion());
154
                values.add(factory.getLanguageName());
155
                values.add(factory.getLanguageVersion());
156

    
157
                // Aliases
158
                buffer.append("\n\t- Aliases: ");
159
                List<String> engNames = factory.getNames();
160
                int size = engNames.size();
161
                for (String name : engNames) {
162
                    size--;
163
                    buffer.append("{}");
164
                    if (size > 0) {
165
                        buffer.append(", ");
166
                    }
167
                    values.add(name);
168
                }
169
                buffer.append("\n\t- File extensions: ");
170
                List<String> extNames = factory.getExtensions();
171
                size = extNames.size();
172
                for (String name : extNames) {
173
                    size--;
174
                    buffer.append("{}");
175
                    if (size > 0) {
176
                        buffer.append(", ");
177
                    }
178
                    values.add(name);
179
                }
180
                buffer.append("\n\t- Mime types: ");
181
                List<String> mimeNames = factory.getMimeTypes();
182
                size = mimeNames.size();
183
                for (String name : mimeNames) {
184
                    size--;
185
                    buffer.append("{}");
186
                    if (size > 0) {
187
                        buffer.append(", ");
188
                    }
189
                    values.add(name);
190
                }
191

    
192
            }
193
            LOG.info(buffer.toString(), values.toArray());
194
        }
195
    }
196

    
197
    public void loadEngines() {
198
        this.getEngineManager();
199
    }
200
    
201
    private ScriptEngine getJythonEngine() {
202
        ScriptEngineFactory factory = this.getEngineFactoryByLanguage("python");
203
        ScriptEngine engine = new MyPyScriptEngine(factory);
204
        return engine;
205
    }
206
    
207
    public ImageIcon getIcon(String name) {
208
        return this.icons.get(name);
209
    }
210

    
211
    @Override
212
    public String getEngineNameByLanguage(String langName) {
213
        ScriptEngineFactory factory = this.getEngineFactoryByLanguage(langName);
214
        if( factory == null ) {
215
            return null;
216
        }
217
        return factory.getEngineName();
218
    }
219

    
220
    public ScriptEngine createEngineByLanguage(String langName) {
221
        return this.getEngineByLanguage(langName);
222
    }
223

    
224
    public ScriptEngine getEngineByLanguage(String langName) {
225
        ScriptEngine engine;
226
        if( "python".equalsIgnoreCase(langName) ) {
227
            engine = getJythonEngine();
228
        } else {
229
            ScriptEngineFactory factory = this.getEngineFactoryByLanguage(langName);
230
            if( factory == null ) {
231
                return null;
232
            }
233
            engine = factory.getScriptEngine();
234
        }
235
        engine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(bindings);
236
        return engine;
237
    }
238

    
239
    public ScriptEngineFactory getEngineFactoryByLanguage(String langName) {
240
        List<ScriptEngineFactory> factories
241
                = getEngineManager().getEngineFactories();
242

    
243
        for (ScriptEngineFactory factory : factories) {
244
            if (factory.getLanguageName().equalsIgnoreCase(langName)) {
245
                return factory;
246
            }
247
        }
248
        return null;
249
    }
250

    
251
    @Override
252
    public boolean validateUnitId(ScriptingFolder folder, String id) {
253
        File f = new File(folder.getFile(),id+".inf");
254
        if( f.exists() ) {
255
            return false;
256
        }
257
        return true;
258
//        List<ScriptingUnit> units = folder.getUnits();
259
//        String fileName;
260
//        for (ScriptingUnit unit : units) {
261
//            fileName = unit.getId();
262
//            fileName = FilenameUtils.getBaseName(fileName);
263
//            if (fileName.equals(id)) {
264
//                return false;
265
//            }
266
//        }
267
//        return true;
268
    }
269

    
270
    public ScriptingScript createScript(ScriptingFolder folder, String id) {
271
        return this.createScript(folder, id, null);
272
    }
273
    
274
    public Script createScript(String name, String code, String languaje) {
275
        ScriptingScript script = new DefaultScriptingScript(this.getUserFolder(), this, name);
276
        script.setCode(code);
277
        script.setSaved(true);
278
        return script;        
279
    }
280

    
281
    private ScriptingScript createScript(ScriptingFolder folder, String id, String language) {
282
        DefaultScriptingScript script = new DefaultScriptingScript(folder, this, id);
283
        if (!script.getFile().exists()) {
284
            script.create(folder, id, language);
285
        } else {
286
            script.load(folder, id);
287
        }
288
        return script;
289
    }
290

    
291
    public ScriptingDialog createDialog(ScriptingFolder folder, String id) {
292
        return this.createDialog(folder, id, null);
293
    }
294

    
295
    private ScriptingDialog createDialog(ScriptingFolder folder, String id, String language) {
296
        DefaultScriptingDialog dialog = new DefaultScriptingDialog(folder, this, id);
297
        if (!dialog.getFile().exists()) {
298
            dialog.create(folder, id, language);
299
        } else {
300
            dialog.load(folder, id);
301
        }
302
        return dialog;
303
    }
304

    
305
    public ScriptingFolder createFolder(ScriptingFolder folder, String id) {
306
        DefaultScriptingFolder unit = new DefaultScriptingFolder(folder, this, new File(folder.getFile(), id));
307
        unit.load(folder, id);
308
        if (!unit.getFile().exists()) {
309
            unit.create(folder, id);
310
        }
311
        return unit;
312
    }
313

    
314
    public ScriptingExternalFile createExternalFile(ScriptingFolder folder, String id) {
315
        DefaultScriptingExternalFile unit = new DefaultScriptingExternalFile(folder, this, id);
316
        return unit;
317
    }
318
    
319
    @Override
320
    public ScriptingBaseScript getScript(File file) {
321
        ScriptingBaseScript script = (ScriptingBaseScript) this.getUnit(file);
322
        if (script == null) {
323
            throw new ScriptNotFoundException(file);
324
        }
325
        return script;
326
    }
327

    
328
    @Override
329
    public ScriptingFolder getFolder(File file) {
330
        ScriptingFolder folder = (ScriptingFolder) this.getUnit(file);
331
        if (folder == null) {
332
            throw new RuntimeException(file.getAbsolutePath());
333
        }
334
        return folder;
335
    }
336

    
337
    public ScriptingUnit getUnit(File file) {
338
        ScriptingFolder folder;
339
        ScriptingUnit unit;
340

    
341
        if (file.isAbsolute()) {
342
            folder = new DefaultScriptingFolder(null, this, file.getParentFile());
343
            unit = folder.getUnit(file);
344
            return unit;
345
        } else {
346
            folder = this.getUserFolder();
347
            unit = folder.getUnit(file);
348
            if (unit != null) {
349
                return unit;
350
            }
351

    
352
            folder = this.getSystemFolder();
353
            unit = folder.getUnit(file);
354
            if (unit != null) {
355
                return unit;
356
            }
357
        }
358
        return null;
359
    }
360

    
361
    @Override
362
    public ScriptingFolder getSystemFolder() {
363
        return new SystemFolder(this);
364
    }
365

    
366
    @Override
367
    public ScriptingFolder getUserFolder() {
368
        return new UserFolder(this, this.getRootUserFolder());
369
    }
370

    
371
    @Override
372
    public ScriptingBaseScript getScript(String name) {
373
        return (ScriptingBaseScript) findScript(null, name);
374
    }
375

    
376
    private ScriptingUnit findScript(ScriptingFolder folder, String name) {
377
        if (name == null) {
378
            return null;
379
        }
380
        if (name.trim().length() == 0) {
381
            return null;
382
        }
383
        ScriptingUnit unit;
384
        if (folder == null) {
385
            unit = findScript(this.getUserFolder(), name);
386
            if (unit != null) {
387
                return unit;
388
            }
389
            unit = findScript(this.getSystemFolder(), name);
390
            return unit;
391
        }
392
        List<ScriptingUnit> units = folder.getUnits();
393
        Iterator<ScriptingUnit> it = units.iterator();
394
        while (it.hasNext()) {
395
            unit = it.next();
396
            if (unit instanceof ScriptingFolder) {
397
                unit = findScript((ScriptingFolder) unit, name);
398
                if (unit != null) {
399
                    return unit;
400
                }
401
            } else if (unit instanceof ScriptingBaseScript) {
402
                if (name.equalsIgnoreCase(unit.getId())) {
403
                    return unit;
404
                }
405
            }
406
        }
407
        return null;
408
    }
409

    
410
    @Override
411
    public File getRootUserFolder() {
412
        return new File(this.getHomeFolder(), "scripts");
413
    }
414

    
415
    @Override
416
    public void registerSystemFolder(String name, File folder) {
417
        this.systemFolders.add(new RegisterSystemFolder(name, folder));
418
        LOG.info("Register system folder name '" + name + "' folder " + folder.getAbsolutePath() + "'");
419

    
420
    }
421

    
422
    public List<RegisterSystemFolder> getSystemFolders() {
423
        return this.systemFolders;
424
    }
425

    
426
    @Override
427
    public List<ScriptingFolder> getAlternativeUserFolders() {
428
        return this.alternativeUserFolders;
429
    }
430

    
431
    @Override
432
    public void addAlternativeUserFolder(File f, String name, String description) {
433
        UserFolder x = new UserFolder(this, f);
434
        x.setName(name);
435
        x.setDescription(description);
436
        x.setId("UserFolder_" + this.alternativeUserFolders.size() + 1);
437
        this.alternativeUserFolders.add(x);
438
    }
439
    
440
    private void initLanguages() {
441
        if (this.extensionOfLanguage == null) {
442
            Map<String, String> extensionOfLanguage = new HashMap<>();
443
            List<ScriptEngineFactory> factories = getEngineManager().getEngineFactories();
444
            for (ScriptEngineFactory factory : factories) {
445
                if( "ognl".equals(factory.getLanguageName()) ) {
446
                    continue;
447
                }
448
                List<String> extensions = factory.getExtensions();
449
                if (extensions != null && !extensions.isEmpty()) {
450
                    extensionOfLanguage.put(
451
                            factory.getLanguageName().toLowerCase(),
452
                            extensions.get(0).toLowerCase()
453
                    );
454
                }
455
            }
456
            this.extensionOfLanguage = extensionOfLanguage;
457
        }
458
        if (this.languageOfExtension == null) {
459
            Map<String, String> languageOfExtension = new HashMap<>();
460
            List<ScriptEngineFactory> factories = getEngineManager().getEngineFactories();
461
            for (ScriptEngineFactory factory : factories) {
462
                if( "ognl".equals(factory.getLanguageName()) ) {
463
                    continue;
464
                }
465
                List<String> extensions = factory.getExtensions();
466
                if (extensions != null) {
467
                    for (String extension1 : extensions) {
468
                        languageOfExtension.put(
469
                                extension1.toLowerCase(),
470
                                factory.getLanguageName().toLowerCase()
471
                        );
472
                    }
473
                }
474
            }
475
            this.languageOfExtension = languageOfExtension;
476
        }
477
    }
478

    
479
    @Override
480
    public String getExtensionOfLanguage(String langName) {
481
        if (langName == null) {
482
            return null;
483
        }
484
        langName = langName.toLowerCase();
485
        initLanguages();
486
        return this.extensionOfLanguage.get(langName);
487
    }
488

    
489
    @Override
490
    public List<String> getSupportedLanguages() {
491
        List<String> languages = new ArrayList<>();
492

    
493
        initLanguages();
494
        languages.addAll(this.extensionOfLanguage.keySet());
495
        Collections.sort(languages);
496
        return languages;
497
    }
498

    
499
    public String getLanguageOfExtension(String extension) {
500
        if (extension == null) {
501
            return null;
502
        }
503
        extension = extension.toLowerCase();
504
        if (extension.startsWith(".")) {
505
            extension = extension.substring(1);
506
        }
507
        initLanguages();
508
        return this.languageOfExtension.get(extension);
509
    }
510

    
511
    public Object get(String key) {
512
        return this.bindings.get(key);
513
    }
514

    
515
    public void put(String key, Object value) {
516
        this.bindings.put(key, value);
517

    
518
    }
519

    
520
    @Override
521
    public ScriptingHelpManager getHelpManager() {
522
        if (this.helpManager == null) {
523
            this.helpManager = new DefaultScriptingHelpManager(this);
524
        }
525
        return this.helpManager;
526
    }
527

    
528
    @Override
529
    public ScriptingUnit createUnit(String unitType, ScriptingFolder folder, String id) {
530
        return createUnit(unitType, folder, id, null);
531
    }
532

    
533
    @Override
534
    public ScriptingUnit createUnit(String unitType, ScriptingFolder folder, String id, String language) {
535
        if (unitType.equals(UNIT_SCRIPT)) {
536
            return this.createScript(folder, id, language);
537
        }
538
        if (unitType.equals(UNIT_DIALOG)) {
539
            return this.createDialog(folder, id, language);
540
        }
541
        if (unitType.equals(UNIT_FOLDER)) {
542
            return this.createFolder(folder, id);
543
        }
544
        if (unitType.equals(UNIT_EXTERNALFILE)) {
545
            return this.createExternalFile(folder, id);
546
        }
547
        return null;
548
    }
549

    
550
    @Override
551
    public List<String> getUnitTypes() {
552
        if (this.unitTypes == null) {
553
            this.unitTypes = new ArrayList<>();
554
            this.unitTypes.add(UNIT_SCRIPT);
555
            this.unitTypes.add(UNIT_DIALOG);
556
            this.unitTypes.add(UNIT_FOLDER);
557
            this.unitTypes.add(UNIT_EXTERNALFILE);
558
        }
559
        return this.unitTypes;
560
    }
561

    
562
    @Override
563
    public void addLibFolder(File lib) {
564
        if (lib.exists()) {
565
            LOG.info("Add scripting lib folder '" + lib.getAbsolutePath() + "'");
566
            this.libFolders.add(lib);
567
        } else {
568
            LOG.info("Skip add scripting lib folder '" + lib.getAbsolutePath() + "', folder don't exist");
569
        }
570
    }
571

    
572
    @Override
573
    public List<File> getLibFolders() {
574
        return new ArrayList(this.libFolders);
575
    }
576

    
577
    @Override
578
    public Map<String, String> getLibFoldersVersions() {
579
        Map<String, String>versions = new HashMap<>();
580
        List<File> folders = this.getLibFolders();
581
        for (File folder : folders) {
582
            File parent = folder.getParentFile();
583
            File libVersions = new File(parent,folder.getName()+".versions");
584
            if( libVersions.exists() ) {
585
                this.loadLibVersions(versions, libVersions);
586
            }
587
        }
588
        if( versions.isEmpty() ) {
589
            return null;
590
        }
591
        return versions;
592
    }
593

    
594
    private void loadLibVersions(Map<String,String>versions, File file) {
595
        List<String> lines;
596
        try {
597
            lines = FileUtils.readLines(file);
598
        } catch (IOException ex) {
599
            LOG.warn("Can't load lib versions from '"+file+".",ex);
600
            return;
601
        }
602
        for (String line : lines) {
603
            String[] x = line.split("=");
604
            if( x.length==2 ) {
605
                versions.put(x[0], x[1]);
606
            } 
607
        }
608
    }
609
    
610
    @Override
611
    public ProviderFactory getInstallerFactory() {
612
        return new ScriptingInstallerProviderFactory();
613
    }
614

    
615
    public ProviderFactory getHelpInstallerFactory() {
616
        return new ScriptingHelpInstallerProviderFactory();
617
    }
618

    
619
    @Override
620
    public File getPackagesFolder() {
621
        return this.packagesFolder;
622
    }
623

    
624
    @Override
625
    public void setPackagesFolder(File folder) {
626
        this.packagesFolder = folder;
627
    }
628

    
629
}