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

History | View | Annotate | Download (18.7 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
import java.util.logging.Level;
12

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

    
20
import org.apache.commons.io.FileUtils;
21
import org.apache.commons.io.FilenameUtils;
22
import org.gvsig.scripting.ScriptingBaseScript;
23
import org.gvsig.scripting.ScriptingDialog;
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.slf4j.Logger;
32
import org.slf4j.LoggerFactory;
33

    
34

    
35
public class DefaultScriptingManager implements ScriptingManager {
36

    
37
    public static class RegisterSystemFolder {
38

    
39
        public String name;
40
        public File folder;
41

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

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

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

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

    
71
    public DefaultScriptingManager(ClassLoader classLoader) {
72
        this();
73
        this.classLoader = classLoader;
74
    }
75

    
76
    private void createFolder(File f) {
77
        if (!f.exists()) {
78
            try {
79
                FileUtils.forceMkdir(f);
80
                LOG.info("Created scripting folder '" + f.getAbsolutePath() + "'");
81
            } catch (Throwable e) {
82
                LOG.warn("Can't Create scripting folder '" + f.getAbsolutePath() + "'");
83
            }
84
        }
85
    }
86

    
87
    private void createDefaultFolders(File home) {
88
        createFolder(new File(home, "scripts"));
89
        createFolder(new File(home, "help"));
90
        createFolder(new File(home, "lib"));
91
    }
92

    
93
    @Override
94
    public File getHomeFolder() {
95
        if (!this.home.exists()) {
96
            createFolder(home);
97
            createDefaultFolders(home);
98
        }
99
        return this.home;
100
    }
101

    
102
    @Override
103
    public void setHomeFolder(File home) {
104
        if (home == null) {
105
            this.home = new File(System.getProperty("user.home"), ".gvsig-scripting");
106
        } else {
107
            this.home = home;
108
        }
109
        createDefaultFolders(this.home);
110
        LOG.info("Set scripting home to '" + this.home.getAbsolutePath() + "'");
111
        this.addLibFolder(new File(this.home, "lib"));
112
    }
113

    
114
    protected ScriptEngineManager getEngineManager() {
115
        if (this.engineManager == null) {
116
            this.engineManager
117
                    = classLoader == null ? new ScriptEngineManager()
118
                            : new ScriptEngineManager(classLoader);
119
            showEnginesInfo(engineManager);
120
        }
121
        return this.engineManager;
122
    }
123

    
124
    private void showEnginesInfo(ScriptEngineManager mgr) {
125
        if (LOG.isInfoEnabled()) {
126
            List<ScriptEngineFactory> factories = mgr.getEngineFactories();
127
            StringBuilder buffer = new StringBuilder();
128
            List<Object> values = new ArrayList<>();
129
            buffer.append("Scripting engines available:");
130
            for (ScriptEngineFactory factory : factories) {
131

    
132
                // Main engine info
133
                buffer
134
                        .append("\n- {}: version = {}, language = {}, langVersion = {}");
135
                values.add(factory.getEngineName());
136
                values.add(factory.getEngineVersion());
137
                values.add(factory.getLanguageName());
138
                values.add(factory.getLanguageVersion());
139

    
140
                // Aliases
141
                buffer.append("\n\t- Aliases: ");
142
                List<String> engNames = factory.getNames();
143
                int size = engNames.size();
144
                for (String name : engNames) {
145
                    size--;
146
                    buffer.append("{}");
147
                    if (size > 0) {
148
                        buffer.append(", ");
149
                    }
150
                    values.add(name);
151
                }
152
                buffer.append("\n\t- File extensions: ");
153
                List<String> extNames = factory.getExtensions();
154
                size = extNames.size();
155
                for (String name : extNames) {
156
                    size--;
157
                    buffer.append("{}");
158
                    if (size > 0) {
159
                        buffer.append(", ");
160
                    }
161
                    values.add(name);
162
                }
163
                buffer.append("\n\t- Mime types: ");
164
                List<String> mimeNames = factory.getMimeTypes();
165
                size = mimeNames.size();
166
                for (String name : mimeNames) {
167
                    size--;
168
                    buffer.append("{}");
169
                    if (size > 0) {
170
                        buffer.append(", ");
171
                    }
172
                    values.add(name);
173
                }
174

    
175
            }
176
            LOG.info(buffer.toString(), values.toArray());
177
        }
178
    }
179

    
180
    public void loadEngines() {
181
        this.getEngineManager();
182
    }
183
    
184
    protected ScriptEngine getEngine(String langName) {
185
        ScriptEngineManager manager = this.getEngineManager();
186
        ScriptEngine engine = manager.getEngineByName(langName);
187
        engine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(bindings);
188
        return engine;
189
    }
190

    
191
    public ImageIcon getIcon(String name) {
192
        return this.icons.get(name);
193
    }
194

    
195
    @Override
196
    public String getEngineNameByLanguage(String langName) {
197
        List<ScriptEngineFactory> factories
198
                = getEngineManager().getEngineFactories();
199

    
200
        for (ScriptEngineFactory factory : factories) {
201
            if (factory.getLanguageName().equalsIgnoreCase(langName)) {
202
                return factory.getEngineName();
203
            }
204
        }
205
        return null;
206
    }
207

    
208
    public ScriptEngine getEngineByLanguage(String langName) {
209
        List<ScriptEngineFactory> factories
210
                = getEngineManager().getEngineFactories();
211

    
212
        for (ScriptEngineFactory factory : factories) {
213
            if (factory.getLanguageName().equalsIgnoreCase(langName)) {
214
                return factory.getScriptEngine();
215
            }
216
        }
217
        return null;
218
    }
219

    
220
    @Override
221
    public boolean validateUnitId(ScriptingFolder folder, String id) {
222
        List<ScriptingUnit> units = folder.getUnits();
223
        String fileName;
224
        for (ScriptingUnit unit : units) {
225
            fileName = unit.getId();
226
            fileName = FilenameUtils.getBaseName(fileName);
227
            if (fileName.equals(id)) {
228
                return false;
229
            }
230
        }
231
        return true;
232
    }
233

    
234
    public ScriptingScript createScript(ScriptingFolder folder, String id) {
235
        return this.createScript(folder, id, null);
236
    }
237
    
238
    public Script createScript(String name, String code, String languaje) {
239
        ScriptingScript script = new DefaultScriptingScript(this.getUserFolder(), this, name);
240
        script.setCode(code);
241
        script.setSaved(true);
242
        return script;        
243
    }
244

    
245
    private ScriptingScript createScript(ScriptingFolder folder, String id, String language) {
246
        DefaultScriptingScript script = new DefaultScriptingScript(folder, this, id);
247
        if (!script.getFile().exists()) {
248
            script.create(folder, id, language);
249
        } else {
250
            script.load(folder, id);
251
        }
252
        return script;
253
    }
254

    
255
    public ScriptingDialog createDialog(ScriptingFolder folder, String id) {
256
        return this.createDialog(folder, id, null);
257
    }
258

    
259
    private ScriptingDialog createDialog(ScriptingFolder folder, String id, String language) {
260
        DefaultScriptingDialog dialog = new DefaultScriptingDialog(folder, this, id);
261
        if (!dialog.getFile().exists()) {
262
            dialog.create(folder, id, language);
263
        } else {
264
            dialog.load(folder, id);
265
        }
266
        return dialog;
267
    }
268

    
269
    public ScriptingFolder createFolder(ScriptingFolder folder, String id) {
270
        DefaultScriptingFolder unit = new DefaultScriptingFolder(folder, this, new File(folder.getFile(), id));
271
        unit.load(folder, id);
272
        if (!unit.getFile().exists()) {
273
            unit.create(folder, id);
274
        }
275
        return unit;
276
    }
277

    
278
    @Override
279
    public ScriptingBaseScript getScript(File file) {
280
        ScriptingBaseScript script = (ScriptingBaseScript) this.getUnit(file);
281
        if (script == null) {
282
            throw new ScriptNotFoundException(file);
283
        }
284
        return script;
285
    }
286

    
287
    @Override
288
    public ScriptingFolder getFolder(File file) {
289
        ScriptingFolder folder = (ScriptingFolder) this.getUnit(file);
290
        if (folder == null) {
291
            throw new RuntimeException(file.getAbsolutePath());
292
        }
293
        return folder;
294
    }
295

    
296
    public ScriptingUnit getUnit(File file) {
297
        ScriptingFolder folder;
298
        ScriptingUnit unit;
299

    
300
        if (file.isAbsolute()) {
301
            folder = new DefaultScriptingFolder(null, this, file.getParentFile());
302
            unit = folder.getUnit(file);
303
            return unit;
304
        } else {
305
            folder = this.getUserFolder();
306
            unit = folder.getUnit(file);
307
            if (unit != null) {
308
                return unit;
309
            }
310

    
311
            folder = this.getSystemFolder();
312
            unit = folder.getUnit(file);
313
            if (unit != null) {
314
                return unit;
315
            }
316
        }
317
        return null;
318
    }
319

    
320
    @Override
321
    public ScriptingFolder getSystemFolder() {
322
        return new SystemFolder(this);
323
    }
324

    
325
    @Override
326
    public ScriptingFolder getUserFolder() {
327
        return new UserFolder(this, this.getRootUserFolder());
328
    }
329

    
330
    @Override
331
    public ScriptingBaseScript getScript(String name) {
332
        return (ScriptingBaseScript) findScript(null, name);
333
    }
334

    
335
    private ScriptingUnit findScript(ScriptingFolder folder, String name) {
336
        if (name == null) {
337
            return null;
338
        }
339
        if (name.trim().length() == 0) {
340
            return null;
341
        }
342
        ScriptingUnit unit;
343
        if (folder == null) {
344
            unit = findScript(this.getUserFolder(), name);
345
            if (unit != null) {
346
                return unit;
347
            }
348
            unit = findScript(this.getSystemFolder(), name);
349
            return unit;
350
        }
351
        List<ScriptingUnit> units = folder.getUnits();
352
        Iterator<ScriptingUnit> it = units.iterator();
353
        while (it.hasNext()) {
354
            unit = it.next();
355
            if (unit instanceof ScriptingFolder) {
356
                unit = findScript((ScriptingFolder) unit, name);
357
                if (unit != null) {
358
                    return unit;
359
                }
360
            } else if (unit instanceof ScriptingBaseScript) {
361
                if (name.equalsIgnoreCase(unit.getId())) {
362
                    return unit;
363
                }
364
            }
365
        }
366
        return null;
367
    }
368

    
369
    @Override
370
    public File getRootUserFolder() {
371
        return new File(this.getHomeFolder(), "scripts");
372
    }
373

    
374
    @Override
375
    public void registerSystemFolder(String name, File folder) {
376
        this.systemFolders.add(new RegisterSystemFolder(name, folder));
377
        LOG.info("Register system folder name '" + name + "' folder " + folder.getAbsolutePath() + "'");
378

    
379
    }
380

    
381
    public List<RegisterSystemFolder> getSystemFolders() {
382
        return this.systemFolders;
383
    }
384

    
385
    @Override
386
    public List<ScriptingFolder> getAlternativeUserFolders() {
387
        return this.alternativeUserFolders;
388
    }
389

    
390
    @Override
391
    public void addAlternativeUserFolder(File f, String name, String description) {
392
        UserFolder x = new UserFolder(this, f);
393
        x.setName(name);
394
        x.setDescription(description);
395
        x.setId("UserFolder_" + this.alternativeUserFolders.size() + 1);
396
        this.alternativeUserFolders.add(x);
397
    }
398
    
399
    private void initLanguages() {
400
        if (this.extensionOfLanguage == null) {
401
            Map<String, String> extensionOfLanguage = new HashMap<>();
402
            List<ScriptEngineFactory> factories = getEngineManager().getEngineFactories();
403
            for (ScriptEngineFactory factory : factories) {
404
                if( "ognl".equals(factory.getLanguageName()) ) {
405
                    continue;
406
                }
407
                List<String> extensions = factory.getExtensions();
408
                if (extensions != null && !extensions.isEmpty()) {
409
                    extensionOfLanguage.put(
410
                            factory.getLanguageName().toLowerCase(),
411
                            extensions.get(0).toLowerCase()
412
                    );
413
                }
414
            }
415
            this.extensionOfLanguage = extensionOfLanguage;
416
        }
417
        if (this.languageOfExtension == null) {
418
            Map<String, String> languageOfExtension = new HashMap<>();
419
            List<ScriptEngineFactory> factories = getEngineManager().getEngineFactories();
420
            for (ScriptEngineFactory factory : factories) {
421
                if( "ognl".equals(factory.getLanguageName()) ) {
422
                    continue;
423
                }
424
                List<String> extensions = factory.getExtensions();
425
                if (extensions != null) {
426
                    for (String extension1 : extensions) {
427
                        languageOfExtension.put(
428
                                extension1.toLowerCase(),
429
                                factory.getLanguageName().toLowerCase()
430
                        );
431
                    }
432
                }
433
            }
434
            this.languageOfExtension = languageOfExtension;
435
        }
436
    }
437

    
438
    @Override
439
    public String getExtensionOfLanguage(String langName) {
440
        if (langName == null) {
441
            return null;
442
        }
443
        langName = langName.toLowerCase();
444
        initLanguages();
445
        return this.extensionOfLanguage.get(langName);
446
    }
447

    
448
    @Override
449
    public List<String> getSupportedLanguages() {
450
        List<String> languages = new ArrayList<>();
451

    
452
        initLanguages();
453
        languages.addAll(this.extensionOfLanguage.keySet());
454
        Collections.sort(languages);
455
        return languages;
456
    }
457

    
458
    public String getLanguageOfExtension(String extension) {
459
        if (extension == null) {
460
            return null;
461
        }
462
        extension = extension.toLowerCase();
463
        if (extension.startsWith(".")) {
464
            extension = extension.substring(1);
465
        }
466
        initLanguages();
467
        return this.languageOfExtension.get(extension);
468
    }
469

    
470
    public Object get(String key) {
471
        return this.bindings.get(key);
472
    }
473

    
474
    public void put(String key, Object value) {
475
        this.bindings.put(key, value);
476

    
477
    }
478

    
479
    @Override
480
    public ScriptingHelpManager getHelpManager() {
481
        if (this.helpManager == null) {
482
            this.helpManager = new DefaultScriptingHelpManager(this);
483
        }
484
        return this.helpManager;
485
    }
486

    
487
    @Override
488
    public ScriptingUnit createUnit(String unitType, ScriptingFolder folder, String id) {
489
        return createUnit(unitType, folder, id, null);
490
    }
491

    
492
    @Override
493
    public ScriptingUnit createUnit(String unitType, ScriptingFolder folder, String id, String language) {
494
        if (unitType.equals(UNIT_SCRIPT)) {
495
            return this.createScript(folder, id, language);
496
        }
497
        if (unitType.equals(UNIT_DIALOG)) {
498
            return this.createDialog(folder, id, language);
499
        }
500
        if (unitType.equals(UNIT_FOLDER)) {
501
            return this.createFolder(folder, id);
502
        }
503
        return null;
504
    }
505

    
506
    @Override
507
    public List<String> getUnitTypes() {
508
        if (this.unitTypes == null) {
509
            this.unitTypes = new ArrayList<>();
510
            this.unitTypes.add(UNIT_SCRIPT);
511
            this.unitTypes.add(UNIT_DIALOG);
512
            this.unitTypes.add(UNIT_FOLDER);
513
        }
514
        return this.unitTypes;
515
    }
516

    
517
    @Override
518
    public void addLibFolder(File lib) {
519
        if (lib.exists()) {
520
            LOG.info("Add scripting lib folder '" + lib.getAbsolutePath() + "'");
521
            this.libFolders.add(lib);
522
        } else {
523
            LOG.info("Skip add scripting lib folder '" + lib.getAbsolutePath() + "', folder don't exist");
524
        }
525
    }
526

    
527
    @Override
528
    public List<File> getLibFolders() {
529
        return new ArrayList(this.libFolders);
530
    }
531

    
532
    @Override
533
    public Map<String, String> getLibFoldersVersions() {
534
        Map<String, String>versions = new HashMap<>();
535
        List<File> folders = this.getLibFolders();
536
        for (File folder : folders) {
537
            File parent = folder.getParentFile();
538
            File libVersions = new File(parent,folder.getName()+".versions");
539
            if( libVersions.exists() ) {
540
                this.loadLibVersions(versions, libVersions);
541
            }
542
        }
543
        if( versions.isEmpty() ) {
544
            return null;
545
        }
546
        return versions;
547
    }
548

    
549
    private void loadLibVersions(Map<String,String>versions, File file) {
550
        List<String> lines;
551
        try {
552
            lines = FileUtils.readLines(file);
553
        } catch (IOException ex) {
554
            LOG.warn("Can't load lib versions from '"+file+".",ex);
555
            return;
556
        }
557
        for (String line : lines) {
558
            String[] x = line.split("=");
559
            if( x.length==2 ) {
560
                versions.put(x[0], x[1]);
561
            } 
562
        }
563
    }
564
    
565
    @Override
566
    public ProviderFactory getInstallerFactory() {
567
        return new ScriptingInstallerProviderFactory();
568
    }
569

    
570
    public ProviderFactory getHelpInstallerFactory() {
571
        return new ScriptingHelpInstallerProviderFactory();
572
    }
573

    
574
    @Override
575
    public File getPackagesFolder() {
576
        return this.packagesFolder;
577
    }
578

    
579
    @Override
580
    public void setPackagesFolder(File folder) {
581
        this.packagesFolder = folder;
582
    }
583

    
584
}