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 / DefaultScriptingFolder.java @ 1084

History | View | Annotate | Download (20.5 KB)

1
package org.gvsig.scripting.impl;
2

    
3
import java.io.File;
4
import java.io.FilenameFilter;
5
import java.io.IOException;
6
import java.util.ArrayList;
7
import java.util.List;
8
import java.util.Arrays;
9
import java.util.Collection;
10
import java.util.Collections;
11
import java.util.Comparator;
12
import java.util.HashSet;
13
import java.util.Set;
14
import java.util.function.Predicate;
15
import org.apache.commons.io.FilenameUtils;
16

    
17
import org.apache.commons.lang3.StringUtils;
18
import org.gvsig.scripting.ScriptingFolder;
19
import org.gvsig.scripting.ScriptingManager;
20
import org.gvsig.scripting.ScriptingUnit;
21
import org.gvsig.tools.exception.BaseException;
22
import static org.gvsig.tools.util.FileTools.relativizeFile;
23
import org.gvsig.tools.visitor.Visitor;
24
import org.ini4j.Ini;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27

    
28
public class DefaultScriptingFolder extends AbstractUnit implements ScriptingFolder {
29

    
30
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultScriptingFolder.class);
31
    protected File folder;
32
    private File configFile;
33
    private File linkTarget;
34
    private Ini config;
35
    private String[] iconNames = null;
36
    
37
    protected DefaultScriptingFolder(ScriptingManager manager) {
38
        super(null, ScriptingManager.UNIT_FOLDER, manager, null);
39
    }
40

    
41
    @SuppressWarnings("OverridableMethodCallInConstructor")
42
    public DefaultScriptingFolder(ScriptingFolder parent, ScriptingManager manager, File folder) {
43
        super(parent, ScriptingManager.UNIT_FOLDER, manager, null);
44
        this.folder = new File(FilenameUtils.normalizeNoEndSeparator(folder.getAbsolutePath(),true));
45
        if( this.folder.isFile() && !FilenameUtils.isExtension(this.folder.getName(), "inf") ) {
46
            throw new IllegalArgumentException("folder argument can be a folder.");
47
        }
48
        this.load(parent, folder.getName());
49
   }
50
    
51
    @Override
52
    public void create(ScriptingFolder folder, String id) {
53
        File f = new File(folder.getFile(), id);
54
        this.load(folder, id);
55
        if( !this.isLink() ) {
56
            f.mkdir();
57
        }
58
    }
59

    
60
    @Override
61
    public void create(ScriptingFolder folder, String id, String language) {
62
        this.create(folder, id);
63
    }
64
    
65
    @Override
66
    public File getFile() {
67
        if( this.linkTarget==null ) {
68
            return this.folder;
69
        }
70
        return this.linkTarget;
71
    }
72

    
73
    @Override
74
    public List<File> getFiles() {
75
        List<File> l = new ArrayList<>();
76
        l.add(this.folder);
77
        if( this.configFile!=null ) {
78
            l.add(this.configFile);
79
        }
80
        return l;
81
    }
82

    
83
    @Override
84
    public ScriptingFolder getParent() {
85
        ScriptingFolder theParent = super.getParent();
86
        if( theParent != null ) {
87
            return theParent;
88
        }
89
        File f = this.folder;
90
        if( this.isLink() ) {
91
            f = this.configFile.getParentFile();
92
        }
93
        if( FileUtils.isSameFile(this.manager.getRootUserFolder(), f) ) {
94
            return null;
95
        }
96
        if( FileUtils.isRootFile(f) ) {
97
            return null;
98
        }
99
        return manager.getFolder(f.getParentFile());
100
    }
101

    
102
    @SuppressWarnings("UseSpecificCatch")
103
    private String getTypenameFromInf(File file) {
104
        if (file == null) {
105
            LOGGER.warn("Can't load 'inf' file, file is null.");
106
            return null;
107
        }
108
        try {
109
            Ini inf = new Ini(file);
110
            String theTypename = inf.get("Unit", "type");
111
            if (theTypename == null) {
112
                return ScriptingManager.UNIT_SCRIPT;
113
            }
114
            return theTypename;
115
        } catch (Exception e) {
116
            LOGGER.warn("Can't load 'inf' file '" + file.getAbsolutePath() + "'.", e);
117
            return null;
118
        }
119

    
120
    }
121
    
122
    public Unit getUnit(String path) {
123
        path = FilenameUtils.normalizeNoEndSeparator(path, true);
124
        if( path == null ) {
125
            return null;
126
        }
127
        File f;
128
        ScriptingUnit unit;
129
        String[] path_a = StringUtils.split(path, '/');
130
        switch( path_a.length ) {
131
            case 0:
132
                return null;
133
            default:
134
                f = new File(this.getFile(), path_a[0]);
135
                unit = this.getUnit(f);
136
                if( unit instanceof ScriptingFolder ) {
137
                    unit = ((ScriptingFolder) unit).getUnit(
138
                            StringUtils.join(path_a, '/', 1, path_a.length)
139
                    );
140
                    return (Unit) unit;
141
                }
142
                return null;
143
            case 1:
144
                f = new File(this.getFile(), path_a[0]);
145
                unit = this.getUnit(f);
146
                return (Unit) unit;
147
        }
148
        
149
    }
150
    
151

    
152
    @Override
153
    public Unit getUnit(File afile) {
154
        Unit unit = null;
155

    
156
        File file;
157
        if (afile.isAbsolute()) {
158
            file = afile.getAbsoluteFile();
159
        } else {
160
            file = new File(this.getFile(), afile.getPath());
161
        }
162

    
163
        String TheId = FilenameUtils.getBaseName(afile.getAbsolutePath());
164
        if( StringUtils.isBlank(TheId) ) {
165
            TheId = afile.getName();
166
        }
167
        ScriptingFolder theParent;
168
        if (FilenameUtils.equalsNormalizedOnSystem(this.getFile().getAbsolutePath(), file.getParentFile().getAbsolutePath())) {
169
            theParent = this;
170
        } else {
171
            theParent = new DefaultScriptingFolder(null, manager, file.getParentFile());
172
        }
173

    
174
        if (file.isDirectory()) {
175
            unit = (Unit) this.manager.createUnit(ScriptingManager.UNIT_FOLDER, theParent, TheId);
176

    
177
        } else if (file.isFile()) {
178
            if (!file.getName().endsWith(".inf")) {
179
                file = new File(file.getParentFile(),TheId + ".inf");
180
            }
181
            if (!file.exists()) {
182
                LOGGER.warn("Can't get Unit, file '" + file.getAbsolutePath() + "' not exists.");
183
                return null;
184
            }
185
            unit = (Unit) this.manager.createUnit(getTypenameFromInf(file), theParent, TheId);
186
        }
187
        return unit;
188
    }
189

    
190
    private boolean containsAny(Set<File> files, Collection<File> other) {
191
        for (File file : other) {
192
            if( files.contains(file) ) {
193
                return true;
194
            }
195
        }
196
        return false;
197
    }
198
    
199
    @Override
200
    public List<ScriptingUnit> getUnits() {
201
        List<ScriptingUnit> ol = new ArrayList<>();
202
        //
203
        // Buscamos los directorios y ficheros ".inf".
204
        File[] files = this.getFile().listFiles(new FilenameFilter() {
205
            @Override
206
            public boolean accept(File arg0, String arg1) {
207
                File f = new File(arg0, arg1);
208
                if (!f.canRead() || f.isHidden()) {
209
                    return false;
210
                }
211
                if (f.isDirectory()) {
212
                    return true;
213
                }
214
                if( "#folder.inf".equals(f.getName()) ) {
215
                    return false;
216
                }
217
                String ext = FilenameUtils.getExtension(f.getName());
218
                return "inf".equalsIgnoreCase(ext);
219
            }
220
        });
221
        Set<File> filesAdded = new HashSet<>();
222
        if (files != null) {
223
            for (File f : files) {
224
                try {
225
                    ScriptingUnit unit = this.getUnit(f);
226
                    if( !containsAny(filesAdded, unit.getFiles()) ) {
227
                        filesAdded.addAll(unit.getFiles());
228
                        ol.add(unit);
229
                    }
230
                } catch (Exception ex) {
231
                    LOGGER.warn("Can't create unit from file '" + f.getAbsolutePath() + "'.",ex);
232
                }
233
            }
234
        }
235
        
236
        
237
        // Ahora buscamos los ficheros de tipo ExternalFile, no son 
238
        // directorios, no tienen ".inf".
239
        files = this.getFile().listFiles(new FilenameFilter() {
240
            @Override
241
            public boolean accept(File arg0, String arg1) {
242
                File f = new File(arg0, arg1);
243
                if (!f.canRead() || f.isHidden()) {
244
                    return false;
245
                }
246
                if (f.isDirectory()) {
247
                    return false;
248
                }
249
                if( "#folder.inf".equals(f.getName()) ) {
250
                    return false;
251
                }
252
                return true;
253
            }
254
        });
255
        if (files != null) {
256
            for (File f : files) {
257
                try {
258
                    String extension = FilenameUtils.getExtension(f.getName());
259
                    if( "inf".equalsIgnoreCase(extension) || "class".equalsIgnoreCase(extension) ) {
260
                        continue;
261
                    }
262
                    if( !filesAdded.contains(f) ) {
263
                        ScriptingUnit unit = this.manager.createExternalFile(this, f.getName());
264
                        filesAdded.addAll(unit.getFiles());
265
                        ol.add(unit);
266
                    } 
267
                } catch (Exception ex) {
268
                    LOGGER.warn("Can't create unit from file '" + f.getAbsolutePath() + "'.",ex);
269
                }
270
            }
271
        }
272
        Collections.sort(ol, new Comparator<ScriptingUnit>() {
273

    
274
            @Override
275
            public int compare(ScriptingUnit o1, ScriptingUnit o2) {
276
                if( o1 instanceof ScriptingFolder ) {
277
                    if( ! (o2 instanceof ScriptingFolder) ) {
278
                        return -1;
279
                    }
280
                } else if( o2 instanceof ScriptingFolder ) { 
281
                    return 1;
282
                }
283
                return o1.getId().compareToIgnoreCase(o2.getId());
284
            }
285
        });
286
        return ol;
287
    }
288

    
289
    @Override
290
    public List<ScriptingFolder> getUnitFolders() {
291
        List<ScriptingFolder> ol = new ArrayList<>();
292
        File[] files = this.getFile().listFiles(new FilenameFilter() {
293
            @Override
294
            public boolean accept(File arg0, String arg1) {
295
                File f = new File(arg0, arg1);
296
                if (!f.canRead() || f.isHidden()) {
297
                    return false;
298
                }
299
                if (f.isDirectory()) {
300
                    return true;
301
                }
302
                String ext = FilenameUtils.getExtension(f.getName());
303
                return "inf".equalsIgnoreCase(ext);
304
            }
305
        });
306
        if (files != null) {
307
            Arrays.sort(files, new Comparator<File>() {
308
                @Override
309
                public int compare(File f1, File f2) {
310
                    if (f1.isDirectory() && !f2.isDirectory()) {
311
                        return -1;
312
                    } else if (!f1.isDirectory() && f2.isDirectory()) {
313
                        return 1;
314
                    } else {
315
                        return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());
316
                    }
317
                }
318
            });
319
            for (File f : files) {
320
                try {
321
                    ScriptingUnit unit = this.getUnit(f);
322
                    if( unit instanceof ScriptingFolder ) {
323
                        ol.add((ScriptingFolder) unit);
324
                    }
325
                } catch (Exception ex) {
326
                    LOGGER.warn("Can't create unit from file '" + f.getAbsolutePath() + "'.");
327
                }
328
            }
329
        }
330
        return ol;
331
    }
332

    
333
    @Override
334
    public void add(ScriptingUnit unit) {
335
        unit.move(this);
336
    }
337

    
338
    @Override
339
    public void remove(ScriptingUnit unit) {
340
        unit.remove();
341
    }
342

    
343
    @Override
344
    public File getFileResource(String extension) {
345
        if( this.isLink() ) {
346
            return new File(
347
                    this.configFile.getParentFile(), 
348
                    FilenameUtils.getBaseName(this.configFile.getName()) + extension
349
                ).getAbsoluteFile();
350
        }
351
        return new File(
352
                this.getFile().getParentFile(), 
353
                this.getFile().getName() + extension
354
            ).getAbsoluteFile();
355
    }
356

    
357
    public File getConfigFile() {
358
        if( this.configFile == null ) {
359
            this.configFile = getFileResource(".inf");
360
            if (!this.configFile.isFile()) {
361
                this.configFile = new File(this.folder, "#folder.inf");
362
            }
363
        }
364
        return this.configFile;
365
    }
366
    
367
    public Ini getConfig() {
368
        File f = this.getConfigFile();
369
        return this.getConfig(f);
370
    }
371
    
372
    public Ini getConfig(File f) {
373
        if (this.config == null) {
374
            Ini theConfig = new Ini();
375
            theConfig.setFile(f);
376
            if (f.exists()) {
377
                try {
378
                    theConfig.load();
379
                } catch (IOException ex) {
380
                    throw new RuntimeException(ex);
381
                }
382
            }
383
            this.config = theConfig;
384
        }
385
        return this.config;
386
    }
387
    
388
    @Override
389
    public String getProperty(String group, String name) {
390
        Ini theConfig = this.getConfig();
391
        String value = theConfig.get(group, name);
392
        return value;
393
    }
394
    
395
    @Override
396
    public void setProperty(String group, String name, String value) {
397
        Ini theConfig = this.getConfig();
398
        theConfig.put(group, name, value);
399
    }
400
    
401
    @Override
402
    public void save() {
403
        File theConfigFile = this.getConfigFile();
404
        try {        
405
            Ini theConfig = this.getConfig(theConfigFile);
406
            if( this.linkTarget!=null ) {
407
                theConfig.put(
408
                        ScriptingManager.UNIT_FOLDER, 
409
                        "path", 
410
                        relativizeFile(this.configFile.getParentFile(), this.linkTarget)
411
                );
412
            }
413
            if( this.iconNames!=null ) {
414
                theConfig.put(ScriptingManager.UNIT_FOLDER, "iconName", this.iconNames[0]);
415
                theConfig.put(ScriptingManager.UNIT_FOLDER, "iconNameOpen", this.iconNames[1]);
416
            }
417
            this.save(theConfig);
418
        } catch (Throwable e) {
419
            String msg = "Can't save 'inf' file '" + theConfigFile.getAbsolutePath() + "'.";
420
            LOGGER.warn(msg, e);
421
            throw new RuntimeException(msg, e);
422
        }
423
    }
424
    
425
    @Override
426
    public void load(ScriptingFolder parent, String id) {
427
        this.configFile = null;
428
        this.config = null;
429
        this.linkTarget = null;
430
        this.iconNames = new String[]{"scripting-icon-folder", "scripting-icon-folder-open"};
431
        this.setId(id);
432
        this.setParent(parent);
433

    
434
        File theConfigFile = getConfigFile();
435
        try {
436
            Ini theConfig = this.getConfig(theConfigFile);
437
            loadInf(theConfig);
438
            String iconName = getInfString(
439
                    theConfig,
440
                    ScriptingManager.UNIT_FOLDER,
441
                    "iconName",
442
                    null
443
            );
444
            String iconNameOpen = getInfString(
445
                    theConfig,
446
                    ScriptingManager.UNIT_FOLDER,
447
                    "iconNameOpen",
448
                    null
449
            );
450
            if( iconName!=null ) {
451
                this.iconNames = new String[] {
452
                    iconName,
453
                    iconNameOpen==null? iconName:iconNameOpen
454
                };
455
            }
456
            String targetPath = getInfString(
457
                    theConfig,
458
                    ScriptingManager.UNIT_FOLDER,
459
                    "path",
460
                    null
461
            );
462
            if( !StringUtils.isEmpty(targetPath) ) {
463
                File target = new File(targetPath);
464
                if (target.isAbsolute()) {
465
                    this.linkTarget = target;
466
                } else {
467
                    this.linkTarget = new File(FilenameUtils.concat(theConfigFile.getParent(), targetPath));
468
                }
469
                this.manager.addLink(this.configFile, this.linkTarget);
470
            }
471
            this.configFile = FileUtils.getAbsoluteFile(theConfigFile);
472
        } catch (Exception e) {
473
            LOGGER.warn("Can't load 'inf' file '" + theConfigFile.getAbsolutePath() + "'.", e);
474
        }
475

    
476
    }
477

    
478
    @Override
479
    public String[] getIconNames() {
480
        return this.iconNames;
481
    }
482

    
483
    @Override
484
    public void setIconNames(String iconName, String iconNameOpen) {
485
        this.iconNames = new String[] {
486
            iconName,
487
            StringUtils.isEmpty(iconNameOpen)? iconName : iconNameOpen
488
                
489
        };
490
    }
491
    
492
    @Override
493
    @SuppressWarnings("UseSpecificCatch")
494
    public boolean remove() {
495
        File f = this.getFile();
496
        try {
497
            File infofile = getFileResource(".inf");
498
            if( infofile.exists() ) {
499
                FileUtils.forceDelete(infofile);
500
            }            
501
            if( !this.isLink() ) {
502
                if( f!=null ) {
503
                    FileUtils.forceDelete(this.getFile());
504
                }
505
            }
506
            return true;
507
        } catch (Throwable e) {
508
            LOGGER.warn("Can't remove folder '" + ((f==null)?"unknown":f.getAbsolutePath()) + "'.", e);
509
            return false;
510
        }
511
    }
512

    
513
    @Override
514
    public boolean move(ScriptingFolder target) {
515
        if (! manager.validateUnitId(target, this.getId()) ) {
516
            LOGGER.info("Can't move folder '"+this.getId()+"' to '"+target.getFile().getAbsolutePath()+"', is not valid.");
517
            return false;
518
        }
519
        try {
520
            File infofile = getFileResource(".inf");
521
            if( infofile.exists() ) {
522
                FileUtils.moveFileToDirectory(infofile, target.getFile(), true);
523
            }
524
            if( !this.isLink() ) {
525
                FileUtils.moveDirectoryToDirectory(this.getFile(), target.getFile(),true);
526
            }
527
            this.parent = target;
528
            this.load(target, id);
529
        } catch (IOException ex) {
530
            LOGGER.info("Can't move folder '"+this.getId()+"' to '"+target.getFile().getAbsolutePath()+"', "+ex.getMessage(),ex);
531
            return false;
532
        }
533
        return true;
534
    }
535

    
536
    @Override
537
    public boolean rename(String newId) {
538
        if (! manager.validateUnitId(this.getParent(), newId) ) {
539
            LOGGER.info("Can't rename folder '"+this.getId()+"', target id '"+newId+"' is not valid.");
540
            return false;
541
        }
542
        try {
543
            File target = this.getParent().getFile();
544
            File infofile = getFileResource(".inf");
545
            if( this.isLink() ) {
546
                FileUtils.moveFile(infofile, new File(target,newId));
547
            } else {
548
                FileUtils.moveDirectory(this.getFile(), new File(target,newId));
549
                if( infofile.exists() ) {
550
                    FileUtils.moveFile(infofile, new File(target,newId));
551
                }
552
            }
553
            this.setId(newId);
554
            this.load(this.getParent(), id);
555
        } catch (IOException ex) {
556
            LOGGER.info("Can't rename folder '"+this.getId()+"' to '"+newId+"', "+ex.getMessage(),ex);
557
            return false;
558
        }        
559
        return true;
560
    }
561

    
562
    @Override
563
    public void accept(Visitor visitor) throws BaseException {
564
        List<ScriptingUnit> units = this.getUnits();
565
        for( ScriptingUnit unit : units ) {
566
            if( unit instanceof ScriptingFolder ) {
567
                ScriptingFolder theFolder = (ScriptingFolder) unit;
568
                theFolder.accept(visitor);
569
            } else {
570
                visitor.visit(unit);
571
            }
572
        }
573
    }
574
    
575
    @Override
576
    public boolean isLink() {
577
        return this.linkTarget!=null;
578
    }
579
    
580
    @Override
581
    public void accept(Visitor visitor, Predicate<ScriptingUnit> includeFilter) throws BaseException {
582
        List<ScriptingUnit> units = this.getUnits();
583
        for( ScriptingUnit unit : units ) {
584
            if( includeFilter.test(unit) ) {
585
                if( unit instanceof ScriptingFolder ) {
586
                    ScriptingFolder theFolder = (ScriptingFolder) unit;
587
                    theFolder.accept(visitor);
588
                } else {
589
                    visitor.visit(unit);
590
                }
591
            }
592
        }
593
    }
594

    
595
    @Override
596
    @SuppressWarnings("UseSpecificCatch")
597
    public String getRawInf() {
598
        try {
599
            String rawInf = org.apache.commons.io.FileUtils.readFileToString(
600
                    this.getConfigFile()
601
            );
602
            return rawInf;
603
        } catch (Exception ex) {
604
        }
605
        return null;
606
    }
607
    
608
    @Override
609
    public void setRawInf(String rawInf) {
610
        if( this.configFile == null ) {
611
            this.configFile = new File(folder,"#folder.inf");
612
        }
613
        try {
614
            org.apache.commons.io.FileUtils.write(
615
                    this.getConfigFile(), rawInf
616
            );
617
            this.reload();
618
        } catch (IOException ex) {
619
            // TODO: 
620
        }
621
    }
622
}