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

History | View | Annotate | Download (23.6 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.Set;
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.lang3.StringUtils;
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.ScriptingManager;
26
import org.gvsig.scripting.ScriptingScript;
27
import org.gvsig.scripting.ScriptingUnit;
28
import org.gvsig.tools.script.Script;
29
import org.gvsig.tools.service.spi.ProviderFactory;
30
import org.python.jsr223.MyPyScriptEngine;
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
    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 List<String> unitTypes = null;
56
    private ClassLoader classLoader = null;
57
    private final List<File> libFolders = new ArrayList<>();
58
    private File home = null;
59
    private final List<ScriptingFolder> alternativeUserFolders = new ArrayList<>();
60
    private Map<String, String> extensionOfLanguage = null;
61
    private Map<String, String> languageOfExtension = null;
62
    private File packagesFolder;
63
    private final Map properties = new HashMap();
64
    private final Map<String,ScriptEngine> engineGroups = new HashMap<>();
65
    
66
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
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, "lib"));
107
        createFolder(new File(home, "data"));
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
    @Override
132
    public File getDataFolder(String id) {
133
        File f = FileUtils.getFile(getHomeFolder(), "data",id);
134
        createFolder(f);
135
        return f;
136
    }
137

    
138
    protected synchronized ScriptEngineManager getEngineManager() {
139
        if (this.engineManager == null) {
140
            this.engineManager
141
                    = classLoader == null ? new ScriptEngineManager()
142
                            : new ScriptEngineManager(classLoader);
143
            showEnginesInfo(engineManager);
144
        }
145
        return this.engineManager;
146
    }
147

    
148
    private void showEnginesInfo(ScriptEngineManager mgr) {
149
        if (LOG.isInfoEnabled()) {
150
            List<ScriptEngineFactory> factories = mgr.getEngineFactories();
151
            StringBuilder buffer = new StringBuilder();
152
            List<Object> values = new ArrayList<>();
153
            buffer.append("Scripting engines available:");
154
            for (ScriptEngineFactory factory : factories) {
155

    
156
                // Main engine info
157
                buffer
158
                        .append("\n- {}: version = {}, language = {}, langVersion = {}");
159
                values.add(factory.getEngineName());
160
                values.add(factory.getEngineVersion());
161
                values.add(factory.getLanguageName());
162
                values.add(factory.getLanguageVersion());
163

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

    
199
            }
200
            LOG.info(buffer.toString(), values.toArray());
201
        }
202
    }
203

    
204
    @Override
205
    public synchronized void loadEngines() {
206
        this.getEngineManager();
207
    }
208
    
209
    private ScriptEngine createJythonEngine() {
210
        ScriptEngineFactory factory = this.getEngineFactoryByLanguage(PYTHON_LANGUAGE_NAME);
211
        ScriptEngine engine = new MyPyScriptEngine(factory);
212
        return engine;
213
    }
214
    
215
    public ImageIcon getIcon(String name) {
216
        return this.icons.get(name);
217
    }
218

    
219
    @Override
220
    public String getEngineNameByLanguage(String langName) {
221
        ScriptEngineFactory factory = this.getEngineFactoryByLanguage(langName);
222
        if( factory == null ) {
223
            return null;
224
        }
225
        return factory.getEngineName();
226
    }
227
    
228
    public ScriptEngine getEngineByLanguage(String langName) {
229
        return this.getEngineByLanguage(langName, null);
230
    }
231
    
232
    public synchronized ScriptEngine getEngineByLanguage(String langName, String isolationGroup) {
233
        ScriptEngine engine = null;
234
        if( !StringUtils.isEmpty(isolationGroup) ) {
235
            isolationGroup += "-" + langName;
236
            engine = this.engineGroups.get(isolationGroup.toLowerCase());
237
        } 
238
        if( engine == null ) {
239
            if( PYTHON_LANGUAGE_NAME.equalsIgnoreCase(langName) ) {
240
                engine = createJythonEngine();
241
            } else {
242
                ScriptEngineFactory factory = this.getEngineFactoryByLanguage(langName);
243
                if( factory == null ) {
244
                    return null;
245
                }
246
                engine = factory.getScriptEngine();
247
            }
248
//            if( SCALA_LANGUAGE_NAME.equalsIgnoreCase(langName) ) {
249
//                try {
250
//                    // https://gist.github.com/takawitter/5479445
251
//                    Object settings = engine.getClass().getMethod("settings", new Class[0]).invoke(engine, new Object[0]);
252
//                    settings.getClass().getMethod("processArgumentString", new Class[] { String.class }).invoke(settings, new String[] { "-usejavacp"});
253
//                } catch(Throwable th) {
254
//                    LOG.warn("Can't initialice scala setting -usejavacp",th);
255
//                }
256
//            }            
257
            if( !StringUtils.isEmpty(isolationGroup) ) {
258
                this.engineGroups.put(isolationGroup.toLowerCase(), engine);
259
            }
260
        }
261
        engine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(bindings);
262
        return engine;
263
    }
264

    
265
    @Override
266
    public synchronized Set<String> getEnginesIsolationGroups() {
267
        return this.engineGroups.keySet();
268
    }
269
    
270
    public ScriptEngineFactory getEngineFactoryByLanguage(String langName) {
271
        List<ScriptEngineFactory> factories
272
                = getEngineManager().getEngineFactories();
273

    
274
        for (ScriptEngineFactory factory : factories) {
275
            if (factory.getLanguageName().equalsIgnoreCase(langName)) {
276
                return factory;
277
            }
278
        }
279
        return null;
280
    }
281

    
282
    @Override
283
    public boolean validateUnitId(ScriptingFolder folder, String id) {
284
        File f = new File(folder.getFile(),id+".inf");
285
        return !f.exists();
286
    }
287

    
288
    public ScriptingScript createScript(ScriptingFolder folder, String id) {
289
        return this.createScript(folder, id, null);
290
    }
291
    
292
    @Override
293
    public Script createScript(String name, String code, String languaje) {
294
        ScriptingScript script = new DefaultScriptingScript(this.getUserFolder(), this, name);
295
        script.setCode(code);
296
        script.setSaved(true);
297
        return script;        
298
    }
299

    
300
    private ScriptingScript createScript(ScriptingFolder folder, String id, String language) {
301
        DefaultScriptingScript script = new DefaultScriptingScript(folder, this, id);
302
        if (!script.getFile().exists()) {
303
            script.create(folder, id, language);
304
        } else {
305
            script.load(folder, id);
306
        }
307
        return script;
308
    }
309

    
310
    public ScriptingDialog createDialog(ScriptingFolder folder, String id) {
311
        return this.createDialog(folder, id, null);
312
    }
313

    
314
    private ScriptingDialog createDialog(ScriptingFolder folder, String id, String language) {
315
        DefaultScriptingDialog dialog = new DefaultScriptingDialog(folder, this, id);
316
        if (!dialog.getFile().exists()) {
317
            dialog.create(folder, id, language);
318
        } else {
319
            dialog.load(folder, id);
320
        }
321
        return dialog;
322
    }
323

    
324
    public ScriptingFolder createFolder(ScriptingFolder folder, String id) {
325
        DefaultScriptingFolder unit = new DefaultScriptingFolder(folder, this, new File(folder.getFile(), id));
326
        unit.load(folder, id);
327
        if (!unit.getFile().exists()) {
328
            unit.create(folder, id);
329
        }
330
        return unit;
331
    }
332

    
333
    public ScriptingExternalFile createExternalFile(ScriptingFolder folder, String id) {
334
        DefaultScriptingExternalFile unit = new DefaultScriptingExternalFile(folder, this, id);
335
        if( unit.getExternalFile()!=null && !unit.getExternalFile().exists() ) {
336
            unit.create(folder, id);
337
        }
338
        return unit;
339
    }
340
    
341
    @Override
342
    public ScriptingBaseScript getScript(File file) {
343
        ScriptingBaseScript script = (ScriptingBaseScript) this.getUnit(file);
344
        if (script == null) {
345
            throw new ScriptNotFoundException(file);
346
        }
347
        return script;
348
    }
349

    
350
    
351
    @Override
352
    public ScriptingFolder getFolder(File file) {
353
        if( file == null ) {
354
            throw new IllegalArgumentException("file argument can't be null");
355
        }
356
        file = this.getLinkSource(file);
357
        if( FileUtils.isSameFile(this.getRootUserFolder(),file) ) {
358
            return this.getUserFolder();
359
        }
360
        
361
        ScriptingFolder folder = (ScriptingFolder) this.getUnit(file);
362
        if (folder == null) {
363
            throw new IllegalArgumentException("Can't get ScriptFolder from '"+file.getAbsolutePath()+"'.");
364
        }
365
        return folder;
366
    }
367

    
368
    public ScriptingUnit getUnit(File file) {
369
        ScriptingFolder folder;
370
        ScriptingUnit unit;
371

    
372
        if (file.isAbsolute()) {
373
            folder = new DefaultScriptingFolder(null, this, file.getParentFile());
374
            unit = folder.getUnit(file);
375
            return unit;
376
        } else {
377
            folder = this.getUserFolder();
378
            unit = folder.getUnit(file);
379
            if (unit != null) {
380
                return unit;
381
            }
382

    
383
            folder = this.getSystemFolder();
384
            unit = folder.getUnit(file);
385
            if (unit != null) {
386
                return unit;
387
            }
388
        }
389
        return null;
390
    }
391

    
392
    @Override
393
    public ScriptingFolder getSystemFolder() {
394
        return new SystemFolder(this);
395
    }
396

    
397
    @Override
398
    public ScriptingFolder getUserFolder() {
399
        return new UserFolder(this, this.getRootUserFolder());
400
    }
401

    
402
    @Override
403
    public ScriptingBaseScript getScript(String name) {
404
        return (ScriptingBaseScript) findScript(null, name);
405
    }
406

    
407
    @Override
408
    public Script locateScript(String name) {
409
        ScriptingUnit script = findScript(null, name);
410
        if( script instanceof Script ) {
411
            return (Script) script;
412
        }
413
        return null;
414
    }
415
    
416
    private ScriptingUnit findScript(ScriptingFolder folder, String name) {
417
        if (name == null) {
418
            return null;
419
        }
420
        if (name.trim().length() == 0) {
421
            return null;
422
        }
423
        ScriptingUnit unit;
424
        if (folder == null) {
425
            unit = findScript(this.getUserFolder(), name);
426
            if (unit != null) {
427
                return unit;
428
            }
429
            unit = findScript(this.getSystemFolder(), name);
430
            return unit;
431
        }
432
        List<ScriptingUnit> units = folder.getUnits();
433
        Iterator<ScriptingUnit> it = units.iterator();
434
        while (it.hasNext()) {
435
            unit = it.next();
436
            if (unit instanceof ScriptingFolder) {
437
                unit = findScript((ScriptingFolder) unit, name);
438
                if (unit != null) {
439
                    return unit;
440
                }
441
            } else if (unit instanceof ScriptingBaseScript) {
442
                if (name.equalsIgnoreCase(unit.getId())) {
443
                    return unit;
444
                }
445
            }
446
        }
447
        return null;
448
    }
449

    
450
    @Override
451
    public File getRootUserFolder() {
452
        return new File(this.getHomeFolder(), "scripts");
453
    }
454

    
455
    @Override
456
    public void registerSystemFolder(String name, File folder) {
457
        this.systemFolders.add(new RegisterSystemFolder(name, folder));
458
        LOG.info("Register system folder name '" + name + "' folder " + folder.getAbsolutePath() + "'");
459

    
460
    }
461

    
462
    public List<RegisterSystemFolder> getSystemFolders() {
463
        return this.systemFolders;
464
    }
465

    
466
    @Override
467
    public List<ScriptingFolder> getAlternativeUserFolders() {
468
        return this.alternativeUserFolders;
469
    }
470

    
471
    @Override
472
    public void addAlternativeUserFolder(File f, String name, String description) {
473
        UserFolder x = new UserFolder(this, f);
474
        x.setName(name);
475
        x.setDescription(description);
476
        x.setId("UserFolder_" + this.alternativeUserFolders.size() + 1);
477
        this.alternativeUserFolders.add(x);
478
    }
479
    
480
    private void initLanguages() {
481
        if (this.extensionOfLanguage == null) {
482
            Map<String, String> theExtensionOfLanguage = new HashMap<>();
483
            List<ScriptEngineFactory> factories = getEngineManager().getEngineFactories();
484
            for (ScriptEngineFactory factory : factories) {
485
                if( "ognl".equals(factory.getLanguageName()) ) {
486
                    continue;
487
                }
488
                List<String> extensions = factory.getExtensions();
489
                if (extensions != null && !extensions.isEmpty()) {
490
                    theExtensionOfLanguage.put(
491
                            factory.getLanguageName().toLowerCase(),
492
                            extensions.get(0).toLowerCase()
493
                    );
494
                }
495
            }
496
            this.extensionOfLanguage = theExtensionOfLanguage;
497
        }
498
        if (this.languageOfExtension == null) {
499
            Map<String, String> theLanguageOfExtension = new HashMap<>();
500
            List<ScriptEngineFactory> factories = getEngineManager().getEngineFactories();
501
            for (ScriptEngineFactory factory : factories) {
502
                if( "ognl".equals(factory.getLanguageName()) ) {
503
                    continue;
504
                }
505
                List<String> extensions = factory.getExtensions();
506
                if (extensions != null) {
507
                    for (String extension1 : extensions) {
508
                        theLanguageOfExtension.put(
509
                                extension1.toLowerCase(),
510
                                factory.getLanguageName().toLowerCase()
511
                        );
512
                    }
513
                }
514
            }
515
            this.languageOfExtension = theLanguageOfExtension;
516
        }
517
    }
518

    
519
    @Override
520
    public String getExtensionOfLanguage(String langName) {
521
        if (langName == null) {
522
            return null;
523
        }
524
        langName = langName.toLowerCase();
525
        initLanguages();
526
        return this.extensionOfLanguage.get(langName);
527
    }
528

    
529
    @Override
530
    public List<String> getSupportedLanguages() {
531
        List<String> languages = new ArrayList<>();
532

    
533
        initLanguages();
534
        languages.addAll(this.extensionOfLanguage.keySet());
535
        Collections.sort(languages);
536
        return languages;
537
    }
538

    
539
    public String getLanguageOfExtension(String extension) {
540
        if (extension == null) {
541
            return null;
542
        }
543
        extension = extension.toLowerCase();
544
        if (extension.startsWith(".")) {
545
            extension = extension.substring(1);
546
        }
547
        initLanguages();
548
        return this.languageOfExtension.get(extension);
549
    }
550

    
551
    @Override
552
    public Object get(String key) {
553
        return this.bindings.get(key);
554
    }
555

    
556
    @Override
557
    public void put(String key, Object value) {
558
        this.bindings.put(key, value);
559

    
560
    }
561

    
562
    @Override
563
    public ScriptingUnit createUnit(String unitType, ScriptingFolder folder, String id) {
564
        return createUnit(unitType, folder, id, null);
565
    }
566

    
567
    @Override
568
    public ScriptingUnit createUnit(String unitType, ScriptingFolder folder, String id, String language) {
569
        if (unitType.equals(UNIT_SCRIPT)) {
570
            return this.createScript(folder, id, language);
571
        }
572
        if (unitType.equals(UNIT_DIALOG)) {
573
            return this.createDialog(folder, id, language);
574
        }
575
        if (unitType.equals(UNIT_FOLDER)) {
576
            return this.createFolder(folder, id);
577
        }
578
        if (unitType.equals(UNIT_EXTERNALFILE)) {
579
            return this.createExternalFile(folder, id);
580
        }
581
        return null;
582
    }
583

    
584
    @Override
585
    public List<String> getUnitTypes() {
586
        if (this.unitTypes == null) {
587
            this.unitTypes = new ArrayList<>();
588
            this.unitTypes.add(UNIT_SCRIPT);
589
            this.unitTypes.add(UNIT_DIALOG);
590
            this.unitTypes.add(UNIT_FOLDER);
591
            this.unitTypes.add(UNIT_EXTERNALFILE);
592
        }
593
        return this.unitTypes;
594
    }
595

    
596
    @Override
597
    public void addLibFolder(File lib) {
598
        if (lib.exists()) {
599
            LOG.info("Add scripting lib folder '" + lib.getAbsolutePath() + "'");
600
            this.libFolders.add(lib);
601
        } else {
602
            LOG.info("Skip add scripting lib folder '" + lib.getAbsolutePath() + "', folder don't exist");
603
        }
604
    }
605

    
606
    @Override
607
    public List<File> getLibFolders() {
608
        return new ArrayList(this.libFolders);
609
    }
610

    
611
    @Override
612
    public Map<String, String> getLibFoldersVersions() {
613
        Map<String, String>versions = new HashMap<>();
614
        List<File> folders = this.getLibFolders();
615
        for (File folder : folders) {
616
            File parent = folder.getParentFile();
617
            File libVersions = new File(parent,folder.getName()+".versions");
618
            if( libVersions.exists() ) {
619
                this.loadLibVersions(versions, libVersions);
620
            }
621
        }
622
        if( versions.isEmpty() ) {
623
            return null;
624
        }
625
        return versions;
626
    }
627

    
628
    private void loadLibVersions(Map<String,String>versions, File file) {
629
        List<String> lines;
630
        try {
631
            lines = FileUtils.readLines(file);
632
        } catch (IOException ex) {
633
            LOG.warn("Can't load lib versions from '"+file+".",ex);
634
            return;
635
        }
636
        for (String line : lines) {
637
            String[] x = line.split("=");
638
            if( x.length==2 ) {
639
                versions.put(x[0], x[1]);
640
            } 
641
        }
642
    }
643
    
644
    @Override
645
    public ProviderFactory getInstallerFactory() {
646
        return new ScriptingInstallerProviderFactory();
647
    }
648

    
649
    @Override
650
    public File getPackagesFolder() {
651
        return this.packagesFolder;
652
    }
653

    
654
    @Override
655
    public void setPackagesFolder(File folder) {
656
        this.packagesFolder = folder;
657
    }
658

    
659
    @Override
660
    public ScriptingFolder createLink(String name, File link, String targetPathName) {
661
        StringBuilder contents = new StringBuilder();        
662
        contents.append("[Unit]\n")
663
            .append("type = Folder\n")
664
            .append("name = ").append(name).append("\n")
665
            .append("description =\n")
666
            .append("createdBy =\n")
667
            .append("version =\n")
668
            .append("\n")
669
            .append("[Folder]\n")
670
            .append("path =").append(targetPathName).append("\n")
671
            .append("\n\n");
672

    
673
        if( link.isDirectory() ) {
674
            link = new File(link,name+".inf");
675
        } else if( !link.getName().endsWith(".inf") ) {
676
            link = new File( link.getPath() + ".inf");
677
        }
678
        if( !link.exists() ) {
679
            try {
680
                FileUtils.writeStringToFile(link, contents.toString());
681
            } catch (IOException ex) {
682
                LOG.warn("Can't create ScriptingFolder file in '" + link.getAbsolutePath() + "'.", ex);
683
            }
684
        }
685
        ScriptingFolder folder = this.getFolder(link);
686
        return folder;
687
    }
688

    
689
    @Override
690
    public ScriptingFolder createLink(String name, ScriptingFolder link, String targetPathName) {
691
        return this.createLink(name, link.getFile(), targetPathName);
692
    }
693

    
694
    private final Map<File,File> links = new HashMap<>();
695
    
696
    public void addLink(File source, File target) {    
697
        this.links.put(FileUtils.getRealFile(target), source);
698
    }
699
    
700
    public File getLinkSource(File target) {
701
        File source = this.links.get(FileUtils.getRealFile(target));
702
        if( source == null ) {
703
            return target;
704
        }
705
        if( source.exists() ) {
706
            return source;
707
        }
708
        return target;
709
    }
710
    
711
    public boolean isInUserFolder(File f) {
712
        if( FileUtils.isSubfolder(this.getRootUserFolder(), f) ) {
713
            return true;
714
        }
715
        for( File file : this.links.keySet()) {
716
            if( FileUtils.isSubfolder(file, f) ) {
717
                return true;
718
            }
719
        }
720
        return false;
721
    }
722
}