Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / java / org / gvsig / scripting / app / extension / ScriptingUtils.java @ 1086

History | View | Annotate | Download (23.1 KB)

1
package org.gvsig.scripting.app.extension;
2

    
3
import java.awt.event.ActionEvent;
4
import java.awt.event.ActionListener;
5
import java.io.File;
6
import java.io.IOException;
7
import java.nio.file.FileVisitOption;
8
import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
9
import java.nio.file.FileVisitResult;
10
import java.nio.file.Files;
11
import java.nio.file.Path;
12
import java.nio.file.Paths;
13
import java.nio.file.SimpleFileVisitor;
14
import java.nio.file.attribute.BasicFileAttributes;
15
import java.text.MessageFormat;
16
import java.util.ArrayList;
17
import java.util.Arrays;
18
import java.util.Collections;
19
import java.util.Comparator;
20
import java.util.EnumSet;
21
import java.util.List;
22
import java.util.function.Predicate;
23
import javax.swing.JOptionPane;
24
import javax.swing.SwingUtilities;
25
import org.apache.commons.io.FileUtils;
26
import org.apache.commons.io.FilenameUtils;
27
import org.apache.commons.io.IOCase;
28
import org.apache.commons.lang3.BooleanUtils;
29
import org.gvsig.scripting.DataFolderFound;
30
import org.gvsig.scripting.ScriptingBaseScript;
31
import org.gvsig.scripting.ScriptingFolder;
32
import org.gvsig.scripting.ScriptingLocator;
33
import org.gvsig.scripting.ScriptingManager;
34
import org.gvsig.scripting.ScriptingScript;
35
import org.gvsig.scripting.ScriptingUnit;
36
import org.gvsig.scripting.app.extension.messagewait.MessageWait;
37
import org.gvsig.scripting.swing.api.JScriptingComposer;
38
import org.gvsig.scripting.swing.api.ScriptingSwingLocator;
39
import org.gvsig.scripting.swing.api.ScriptingUIManager;
40
import static org.gvsig.scripting.swing.api.ScriptingUIManager.SCRIPT_COMPOSER_AUTORUN;
41
import org.gvsig.tools.ToolsLocator;
42
import org.gvsig.tools.exception.BaseException;
43
import org.gvsig.tools.i18n.I18nManager;
44
import org.gvsig.tools.packageutils.PackageManager;
45
import org.gvsig.tools.packageutils.Version;
46
import org.gvsig.tools.swing.api.ToolsSwingLocator;
47
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
48
import org.gvsig.tools.swing.api.windowmanager.Dialog;
49
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
50
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
51
import org.gvsig.tools.task.SimpleTaskStatus;
52
import org.gvsig.tools.visitor.VisitCanceledException;
53
import org.gvsig.tools.visitor.Visitor;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56
import org.gvsig.tools.util.FolderSet;
57
import org.gvsig.tools.util.impl.DefaultFolderSet;
58
/**
59
 *
60
 * @author jjdelcerro
61
 */
62
@SuppressWarnings("UseSpecificCatch")
63
public class ScriptingUtils {
64
    
65
    public static final String SKIP_AUTORUNS = "skipAutoruns";
66
    
67
    private static final Logger LOGGER = LoggerFactory.getLogger(ScriptingExtension.class);
68

    
69
    private boolean executingAutorunScripts = false;
70
    private static boolean composer_initialized = false;
71
    private final MessageWait message;
72

    
73
    /*
74
     * la funcion log y las constantes estan pensadas para usarlas desde los scripts.
75
     */
76
    public static final int INFO = 0;
77
    public static final int TRACE = 1;
78
    public static final int WARN = 2;
79
    public static final int ERROR = 3;
80

    
81
    public static void log(String message) {
82
        log(INFO, message, null);
83
    }
84

    
85
    public static void log(int level, String message) {
86
        log(level, message, null);
87
    }
88

    
89
    public static void log(int level, String message, Throwable th) {
90
        switch( level ) {
91
        case TRACE:
92
            LOGGER.trace(message, th);
93
            break;
94
        case ERROR:
95
            LOGGER.error(message, th);
96
            break;
97
        case WARN:
98
            LOGGER.warn(message, th);
99
            break;
100
        default:
101
        case INFO:
102
            LOGGER.info(message, th);
103
            break;
104
        }
105
    }
106
    private String appversion;
107
    private File pluginHomeFolder;
108

    
109
    public ScriptingUtils() {
110
        message = new MessageWait();
111
    }
112
    
113
    public static File getScriptsHomeFolder(File pluginHomeFolder, String appversion) {
114
        File scriptsHomeFolder;
115
        File f = FileUtils.getFile(pluginHomeFolder, "scripts-folder.txt");
116
        if( f.exists() ) {
117
            try {
118
                List<String> lines = FileUtils.readLines(f);
119
                for( String line : lines ) {
120
                    line = line.trim();
121
                    if( !line.startsWith("#") ) {
122
                        scriptsHomeFolder = new File(line);
123
                        if( !scriptsHomeFolder.isAbsolute() ) {
124
                            scriptsHomeFolder = new File(pluginHomeFolder, line);
125
                        }
126
                        scriptsHomeFolder = new File(
127
                            FilenameUtils.normalizeNoEndSeparator(
128
                                scriptsHomeFolder.getAbsolutePath(),
129
                                true
130
                            )
131
                        );
132
                        if( scriptsHomeFolder.exists() ) {
133
                            return scriptsHomeFolder;
134
                        }
135
                    }
136
                }
137
            } catch (IOException ex) {
138
            }
139
        } else {
140
            try {
141
                FileUtils.touch(f);
142
            } catch (IOException ex) {
143
            }
144
        }
145
        scriptsHomeFolder = FileUtils.getFile(pluginHomeFolder, appversion) ;
146
        return scriptsHomeFolder;
147
    }
148
    
149
    public void initializaPaths(List<File> pluginsFolder, File installFolder, File pluginHoneFolder, String appversion) {
150

    
151
        this.appversion = appversion;
152
        this.pluginHomeFolder = pluginHoneFolder;
153
        ScriptingManager manager = ScriptingLocator.getManager();
154
        manager.setHomeFolder(getScriptsHomeFolder(pluginHoneFolder, appversion));
155

    
156
        ScriptingFolder folder = manager.createLink(
157
            "Common",
158
            manager.getUserFolder(), 
159
            "../../scripts"
160
        );
161
        folder.setProperty(ScriptingUtils.SKIP_AUTORUNS, BooleanUtils.toStringTrueFalse(true));
162
        folder.save();
163
//        manager.createLink(
164
//            "Previous version",
165
//            manager.getUserFolder(), 
166
//            "../../../org.gvsig.scripting.app.extension/scripts"
167
//        );
168

    
169
        List<File> pluginsFolders = new ArrayList<>();
170
        for( File f : pluginsFolder ) {
171
            pluginsFolders.addAll(Arrays.asList(f.listFiles()));
172
        }
173

    
174
        for( File pluginFolder : pluginsFolders ) {
175
            File scriptsFolder = new File(pluginFolder, "scripting/scripts");
176
            if( scriptsFolder.exists() ) {
177
                manager.registerSystemFolder(pluginFolder.getName(), scriptsFolder);
178
            }
179
            File libFolder = new File(pluginFolder, "scripting/lib");
180
            if( libFolder.exists() ) {
181
                manager.addLibFolder(libFolder);
182
            }
183
        }
184
        manager.setPackagesFolder(installFolder);
185

    
186
        File localAddonRepositoryFolder = new File(manager.getRootUserFolder(), "addons");
187
        if( !localAddonRepositoryFolder.exists() ) {
188
            try {
189
                FileUtils.forceMkdir(localAddonRepositoryFolder);
190
            } catch (IOException ex) {
191
                LOGGER.info("Can't create addons folder in '" + localAddonRepositoryFolder.getAbsolutePath() + "'.", ex);
192
            }
193
        }
194
        File initAddonFile = new File(localAddonRepositoryFolder, "__init__.py");
195
        if( !initAddonFile.exists() ) {
196
            try {
197
                FileUtils.touch(initAddonFile);
198
            } catch (IOException ex) {
199
                LOGGER.info("Can't create addons __init__ file in '" + localAddonRepositoryFolder.getAbsolutePath() + "'.", ex);
200
            }
201
        }
202
    }
203
    
204
    
205
    public void runScript(String name, Object[] args) {
206
        ScriptingUIManager uimanager = ScriptingSwingLocator.getUIManager();
207
        WindowManager winmanager = ToolsSwingLocator.getWindowManager();        
208

    
209
        ScriptingBaseScript script = uimanager.getManager().getScript(name);
210
        if( script != null ) {
211
            script.run(args);
212
        } else {
213
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
214
            dialogs.messageDialog(
215
                    "Can't locate script '" + name + "'.", 
216
                    "ScriptLaunch", 
217
                    JOptionPane.OK_OPTION
218
            );
219
        }
220
    }
221
    
222
    public void runLauncher() {
223
        ScriptingUIManager uimanager = ScriptingSwingLocator.getUIManager();
224
        WindowManager winmanager = ToolsSwingLocator.getWindowManager();        
225
        winmanager.showWindow(uimanager.createLauncher().asJComponent(), uimanager.getTranslation("Scripting_Launcher"), WindowManager.MODE.TOOL);        
226
    }
227
    
228
    public void runComposer() {
229
        I18nManager i18n = ToolsLocator.getI18nManager();
230
        message.showMessage(
231
                i18n.getTranslation("_notice"),
232
                i18n.getTranslation("_Initializing_the_scripting_plugin_Xhorizontal_ellipsisX") + "\n"
233
                + i18n.getTranslation("_Waiting_to_terminate"),
234
                new MessageWait.WaitingCondition() {
235
            private Thread th = null;
236

    
237
            @Override
238
            public boolean stopWaiting() {
239
                if (executingAutorunScripts) {
240
                    return false;
241
                }
242
                if (composer_initialized) {
243
                    return true;
244
                }
245
                if (th == null) {
246
                    th = new Thread(new ExecuteScriptsFromScriptingFolders(null, "scautorun", SCRIPT_COMPOSER_AUTORUN), "StartupScriptingComposer");
247
                    th.start();
248
                }
249
                return false;
250
            }
251
        },
252
                new Runnable() {
253
            @Override
254
            public void run() {
255
                showScriptingComposer();
256
            }
257
        }
258
        );
259

    
260
    }
261
    
262
    public Runnable getAutorunScriptsOnStartup(List<File> pluginsFolders) {
263
        return new ExecuteAutorunScriptsOnStartup(pluginsFolders);
264
    }
265
    
266
    private void showScriptingComposer() {
267
        ScriptingUIManager uimanager = ScriptingSwingLocator.getUIManager();
268
        JScriptingComposer composer = uimanager.createComposer();
269
        uimanager.showWindow(
270
            composer.asJComponent(),
271
            uimanager.getTranslation("Scripting_Composer")
272
        );
273
    }
274

    
275
    private class ExecuteScriptsFromScriptingFolders extends AbstractExecuteScripts {
276
        
277
        public ExecuteScriptsFromScriptingFolders(List<File> pluginsFolders, String title, String patternName) {
278
            super(pluginsFolders, title, patternName);
279
        }
280
        
281
        @Override
282
        public void run() {            
283
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
284
            SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Scripts startup");
285
            status.setIndeterminate();
286
            status.setAutoremove(true);
287
            status.add();
288
            final I18nManager i18nManager = ToolsLocator.getI18nManager();            
289
            try {
290
                LOGGER.info("Searching "+title+" scripts...");
291
                dialogs.message(
292
                    i18nManager.getTranslation("_Searching_autorun_scripts_Xhorizontal_ellipsisX"),
293
                    JOptionPane.INFORMATION_MESSAGE
294
                );
295
                ScriptingManager manager = ScriptingLocator.getManager();
296
                final List<ScriptingScript> scripts = new ArrayList<>();
297
                
298
                Visitor visitor = new Visitor() {
299
                    @Override
300
                    public void visit(Object o) throws VisitCanceledException, BaseException {
301
                        ScriptingUnit unit = (ScriptingUnit) o;
302
                        if( unit instanceof ScriptingScript && 
303
                            FilenameUtils.wildcardMatch(unit.getName(), patternName, IOCase.INSENSITIVE) ) {
304
                            ScriptingScript script = (ScriptingScript) unit;
305
                            if( script.isEnabled() ) {
306
                                scripts.add(script);
307
                            } else {
308
                                LOGGER.info("Skip "+title+" script '" + script.getFile().getAbsolutePath() + "'.");
309
                            }
310
                        }
311
                    }
312
                };
313
                Predicate<ScriptingUnit> includeFilter = new Predicate<ScriptingUnit>() {
314
                    @Override
315
                    public boolean test(ScriptingUnit unit) {
316
                        if( unit instanceof ScriptingFolder ) {
317
                            return !BooleanUtils.toBoolean(unit.getProperty(SKIP_AUTORUNS));
318
                        }
319
                        return false;
320
                    }
321
                };
322
                manager.getSystemFolder().accept(visitor, includeFilter);
323
                manager.getUserFolder().accept(visitor, includeFilter);
324
                sortScripts(scripts);
325
                executeScripts(scripts, status);
326
            } catch(Throwable th) {
327
                
328
            } finally {
329
                composer_initialized = true;
330
                LOGGER.info("Running "+title+" scripts terminated.");
331
                dialogs.message("", JOptionPane.INFORMATION_MESSAGE);
332
                status.terminate();
333
            }
334
        }
335
    }
336

    
337
    public class ExecuteAutorunScriptsOnStartup implements Runnable {
338

    
339
        private final List<File> pluginsFolders;
340

    
341
        public ExecuteAutorunScriptsOnStartup(List<File> pluginsFolders) {
342
            this.pluginsFolders = pluginsFolders;
343
        }
344
        
345
        @Override
346
        public void run() {
347
            Runnable process = new ExecuteScriptsFromFilesystem(
348
                    this.pluginsFolders,
349
                    "autotun", 
350
                    "autorun.inf"
351
            );
352
            process.run();
353
        }
354
    }
355

    
356
    private abstract class AbstractExecuteScripts implements Runnable {
357

    
358
        protected String patternName;
359
        protected String title;
360
        private final List<File> pluginsFolders;
361

    
362
        public AbstractExecuteScripts(List<File> pluginsFolders, String title, String patternName) {
363
            if( pluginsFolders==null ) {
364
                this.pluginsFolders = Collections.EMPTY_LIST;
365
            } else {
366
                this.pluginsFolders = pluginsFolders;
367
            }
368
            this.patternName = patternName;
369
            this.title = title;
370
        }
371
        
372
        protected List<File> getPluginsFolders() {
373
            return this.pluginsFolders;
374
        }
375
        
376
        private String getScriptOrderKey(ScriptingBaseScript o) {
377
            int groupOrder = 500;
378
            String groupName = "default";
379
            int scriptOrder = 500;
380
            String s = o.getProperty("autorun.group.order");
381
            if (s != null) {
382
                try {
383
                    groupOrder = Integer.parseInt(s);
384
                } catch (Exception ex) {
385
                    // Do nothing.
386
                }
387
            }
388
            s = o.getProperty("autorun.group.name");
389
            if (s != null) {
390
                groupName = s;
391
            }
392
            s = o.getProperty("autorun.order");
393
            if (s != null) {
394
                try {
395
                    scriptOrder = Integer.parseInt(s);
396
                } catch (Exception ex) {
397
                    // Do nothing.
398
                }
399
            }
400
            String key = MessageFormat.format(
401
                    "{0,number,000000}.{1}.{2,number,000000}",
402
                    groupOrder,
403
                    groupName,
404
                    scriptOrder
405
            );
406
            return key;
407
        }
408

    
409
        protected void sortScripts(List<ScriptingScript> scripts) {
410
            Collections.sort(scripts, new Comparator<ScriptingBaseScript>() {
411

    
412
                @Override
413
                public int compare(ScriptingBaseScript o1, ScriptingBaseScript o2) {
414
                    return getScriptOrderKey(o2).compareToIgnoreCase(getScriptOrderKey(o1));
415
                }
416
            });
417
        }
418

    
419
        protected void executeScripts(List<ScriptingScript> scripts, SimpleTaskStatus status) {
420
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
421
            final I18nManager i18nManager = ToolsLocator.getI18nManager();
422
            if (scripts != null && !scripts.isEmpty()) {
423
                if (status != null) {
424
                    status.setRangeOfValues(0, scripts.size());
425
                }
426
                int n = 0;
427
                for (ScriptingBaseScript script : scripts) {
428
                    if (status != null) {
429
                        status.setCurValue(n++);
430
                    }
431
                    try {
432
                        LOGGER.info("running " + title + " script '" + script.getFile().getAbsolutePath() + "' (" + getScriptOrderKey(script) + ", " + script.getIsolationGroup() + ").");
433
                        dialogs.message(
434
                                i18nManager.getTranslation(
435
                                        "_Running_autorun_script_from_XnameX",
436
                                        new String[]{
437
                                            script.getFile().getParentFile().getName()}
438
                                ),
439
                                JOptionPane.INFORMATION_MESSAGE
440
                        );
441
                    } catch (Exception ex) {
442
                        // Ignore it
443
                    }
444
                    try {
445
                        script.run();
446
                    } catch (Exception ex) {
447
                        LOGGER.warn("Can't execute " + title + " from '" + script.getFile().getAbsolutePath() + "'.", ex);
448
                    }
449
                }
450
            }
451

    
452
        }
453
    }
454

    
455
    private class ExecuteScriptsFromFilesystem extends AbstractExecuteScripts {
456

    
457
        public ExecuteScriptsFromFilesystem(List<File> pluginsFolder, String title, String patternName) {
458
            super(pluginsFolder, title, patternName);
459
        }
460

    
461
        @Override
462
        public void run() {
463
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
464
            executingAutorunScripts = true;
465
            try {
466
                final ScriptingManager manager = ScriptingLocator.getManager();
467
                manager.loadEngines();
468

    
469
//                final PluginsManager pluginManager = PluginsLocator.getManager();
470
                final I18nManager i18nManager = ToolsLocator.getI18nManager();
471

    
472
                final List<ScriptingScript> scripts = new ArrayList<>();
473

    
474
                List<File> pluginsFolders = new ArrayList<>();
475
                for (File pluginsFolders2 : this.getPluginsFolders()) {
476
                    for (File pluginFolder : pluginsFolders2.listFiles()) {
477
                        File f = FileUtils.getFile(pluginFolder, "scripting", "scripts");
478
                        if (f.exists()) {
479
                            pluginsFolders.add(f);
480
                        }
481
                    }
482
                }
483

    
484
                dialogs.message(
485
                        i18nManager.getTranslation("_Searching_autorun_scripts_Xhorizontal_ellipsisX"),
486
                        JOptionPane.INFORMATION_MESSAGE
487
                );
488

    
489
                SimpleFileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
490
                    @Override
491
                    public FileVisitResult visitFile(Path path, BasicFileAttributes bfa) throws IOException {
492
                        File file = path.toFile();
493
                        if (FilenameUtils.wildcardMatch(file.getName(), patternName, IOCase.INSENSITIVE)) {
494
                            if (file.exists()) {
495
                                ScriptingScript script = (ScriptingScript) manager.getScript(file);
496
                                if (script.isEnabled()) {
497
                                    scripts.add(script);
498
                                } else {
499
                                    LOGGER.info("Skip " + title + " script '" + file.getAbsolutePath() + "'.");
500
                                }
501
                            }
502
                        }
503
                        return FileVisitResult.CONTINUE;
504
                    }
505
                };
506
                try {
507
                    EnumSet<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS);
508
                    for (File pluginFolder : pluginsFolders) {
509
                        Files.walkFileTree(Paths.get(pluginFolder.toURI()), opts, Integer.MAX_VALUE, visitor);
510
                    }
511
                    Files.walkFileTree(Paths.get(manager.getRootUserFolder().toURI()), opts, Integer.MAX_VALUE, visitor);
512
                    List<ScriptingFolder> folders = manager.getAlternativeUserFolders();
513
                    for (ScriptingFolder folder : folders) {
514
                        Files.walkFileTree(Paths.get(folder.getFile().toURI()), opts, Integer.MAX_VALUE, visitor);
515
                    }
516
                } catch (Exception ex) {
517
                    LOGGER.warn("Can't execute " + title + " in home.", ex);
518
                }
519
                sortScripts(scripts);
520
                executeScripts(scripts, null);
521

    
522
            } finally {
523
                LOGGER.info("Running " + title + " scripts terminated.");
524
                dialogs.message("", JOptionPane.INFORMATION_MESSAGE);
525
                executingAutorunScripts = false;
526
            }
527
            checkDataFoldersVersions();
528
        }
529

    
530
    }
531
    
532
    private void checkDataFoldersVersions() {
533
        final ScriptingManager manager = ScriptingLocator.getManager();
534
        PackageManager versionFactory = ToolsLocator.getPackageManager();
535
        Version currentVersion = versionFactory.createVersion(this.appversion);
536
        FolderSet folders = new DefaultFolderSet();
537
        folders.add(this.pluginHomeFolder);
538
        final List<DataFolderFound> dataFoldersFound = manager.searchOldVersions(currentVersion, folders);
539
        if( dataFoldersFound == null || dataFoldersFound.isEmpty() ) {
540
            return;
541
        }
542
        Runnable askUser = new Runnable() {
543
            @Override
544
            public void run() {
545
                WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
546
                final DataFoldersRecoverPanel panel = new DataFoldersRecoverPanel(dataFoldersFound);
547
                final Dialog dialog = winManager.createDialog(
548
                        panel,
549
                        "Recuperacion de preferencias",
550
                        null,
551
                        WindowManager_v2.BUTTONS_OK_CANCEL
552
                );
553
                dialog.addActionListener(new ActionListener() {
554
                    @Override
555
                    public void actionPerformed(ActionEvent e) {
556
                        if (dialog.getAction() == WindowManager_v2.BUTTON_OK) {
557
                            List<DataFolderFound> toRestore = panel.getSelectedDataFolders();
558
                            for (DataFolderFound dataFolderFound : dataFoldersFound) {
559
                                if (toRestore.contains(dataFolderFound)) {
560
                                    dataFolderFound.restore();
561
                                } else {
562
                                    dataFolderFound.leave();
563
                                }
564
                            }
565
                        }
566
                    }
567
                });
568
                dialog.show(WindowManager.MODE.WINDOW);
569
            }
570
        };
571
        if( SwingUtilities.isEventDispatchThread() ) {
572
            askUser.run();
573
        } else {
574
            SwingUtilities.invokeLater(askUser);
575
        }
576
    }
577
}