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

History | View | Annotate | Download (18 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

    
16
import org.apache.commons.io.FilenameUtils;
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 infFile;
33
    private File linkTarget;
34
    private String[] iconNames = new String[]{"scripting-icon-folder", "scripting-icon-folder-open"};
35
    
36
    protected DefaultScriptingFolder(ScriptingManager manager) {
37
        super(null, ScriptingManager.UNIT_FOLDER, manager, null);
38
    }
39

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

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

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

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

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

    
118
    }
119

    
120
    @Override
121
    public Unit getUnit(File afile) {
122
        Unit unit = null;
123

    
124
        File file;
125
        if (afile.isAbsolute()) {
126
            file = afile.getAbsoluteFile();
127
        } else {
128
            file = new File(this.getFile(), afile.getPath());
129
        }
130

    
131
        String id = FilenameUtils.getBaseName(afile.getAbsolutePath());
132
        if( StringUtils.isBlank(id) ) {
133
            id = afile.getName();
134
        }
135
        ScriptingFolder parent;
136
        if (FilenameUtils.equalsNormalizedOnSystem(this.getFile().getAbsolutePath(), file.getParentFile().getAbsolutePath())) {
137
            parent = this;
138
        } else {
139
            parent = new DefaultScriptingFolder(null, manager, file.getParentFile());
140
        }
141

    
142
        if (file.isDirectory()) {
143
            unit = (Unit) this.manager.createUnit(ScriptingManager.UNIT_FOLDER, parent, id);
144

    
145
        } else if (file.isFile()) {
146
            if (!file.getName().endsWith(".inf")) {
147
                file = new File(file.getParentFile(),id + ".inf");
148
            }
149
            if (!file.exists()) {
150
                logger.warn("Can't get Unit, file '" + file.getAbsolutePath() + "' not exists.");
151
                return null;
152
            }
153
            unit = (Unit) this.manager.createUnit(getTypenameFromInf(file), parent, id);
154
        }
155
        return unit;
156
    }
157

    
158
    private boolean containsAny(Set<File> files, Collection<File> other) {
159
        for (File file : other) {
160
            if( files.contains(file) ) {
161
                return true;
162
            }
163
        }
164
        return false;
165
    }
166
    
167
    @Override
168
    public List<ScriptingUnit> getUnits() {
169
        List<ScriptingUnit> ol = new ArrayList<>();
170
        //
171
        // Buscamos los directorios y ficheros ".inf".
172
        File[] files = this.getFile().listFiles(new FilenameFilter() {
173
            @Override
174
            public boolean accept(File arg0, String arg1) {
175
                File f = new File(arg0, arg1);
176
                if (!f.canRead() || f.isHidden()) {
177
                    return false;
178
                }
179
                if (f.isDirectory()) {
180
                    return true;
181
                }
182
                if( "#folder.inf".equals(f.getName()) ) {
183
                    return false;
184
                }
185
                String ext = FilenameUtils.getExtension(f.getName());
186
                return "inf".equalsIgnoreCase(ext);
187
            }
188
        });
189
        Set<File> filesAdded = new HashSet<>();
190
        if (files != null) {
191
            for (File f : files) {
192
                try {
193
                    ScriptingUnit unit = this.getUnit(f);
194
                    if( !containsAny(filesAdded, unit.getFiles()) ) {
195
                        filesAdded.addAll(unit.getFiles());
196
                        ol.add(unit);
197
                    }
198
                } catch (Exception ex) {
199
                    logger.warn("Can't create unit from file '" + f.getAbsolutePath() + "'.",ex);
200
                }
201
            }
202
        }
203
        
204
        
205
        // Ahora buscamos los ficheros de tipo ExternalFile, no son 
206
        // directorios, no tienen ".inf".
207
        files = this.getFile().listFiles(new FilenameFilter() {
208
            @Override
209
            public boolean accept(File arg0, String arg1) {
210
                File f = new File(arg0, arg1);
211
                if (!f.canRead() || f.isHidden()) {
212
                    return false;
213
                }
214
                if (f.isDirectory()) {
215
                    return false;
216
                }
217
                if( "#folder.inf".equals(f.getName()) ) {
218
                    return false;
219
                }
220
                return true;
221
            }
222
        });
223
        if (files != null) {
224
            for (File f : files) {
225
                try {
226
                    String extension = FilenameUtils.getExtension(f.getName());
227
                    if( "inf".equalsIgnoreCase(extension) || "class".equalsIgnoreCase(extension) ) {
228
                        continue;
229
                    }
230
                    if( !filesAdded.contains(f) ) {
231
                        ScriptingUnit unit = this.manager.createExternalFile(this, f.getName());
232
                        filesAdded.addAll(unit.getFiles());
233
                        ol.add(unit);
234
                    } 
235
                } catch (Exception ex) {
236
                    logger.warn("Can't create unit from file '" + f.getAbsolutePath() + "'.",ex);
237
                }
238
            }
239
        }
240
        Collections.sort(ol, new Comparator<ScriptingUnit>() {
241

    
242
            @Override
243
            public int compare(ScriptingUnit o1, ScriptingUnit o2) {
244
                if( o1 instanceof ScriptingFolder ) {
245
                    if( ! (o2 instanceof ScriptingFolder) ) {
246
                        return -1;
247
                    }
248
                } else if( o2 instanceof ScriptingFolder ) { 
249
                    return 1;
250
                }
251
                return o1.getId().compareToIgnoreCase(o2.getId());
252
            }
253
        });
254
        return ol;
255
    }
256

    
257
    @Override
258
    public List<ScriptingFolder> getUnitFolders() {
259
        List<ScriptingFolder> ol = new ArrayList<>();
260
        File[] files = this.getFile().listFiles(new FilenameFilter() {
261
            @Override
262
            public boolean accept(File arg0, String arg1) {
263
                File f = new File(arg0, arg1);
264
                if (!f.canRead() || f.isHidden()) {
265
                    return false;
266
                }
267
                if (f.isDirectory()) {
268
                    return true;
269
                }
270
                String ext = FilenameUtils.getExtension(f.getName());
271
                return "inf".equalsIgnoreCase(ext);
272
            }
273
        });
274
        if (files != null) {
275
            Arrays.sort(files, new Comparator<File>() {
276
                @Override
277
                public int compare(File f1, File f2) {
278
                    if (f1.isDirectory() && !f2.isDirectory()) {
279
                        return -1;
280
                    } else if (!f1.isDirectory() && f2.isDirectory()) {
281
                        return 1;
282
                    } else {
283
                        return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());
284
                    }
285
                }
286
            });
287
            for (File f : files) {
288
                try {
289
                    ScriptingUnit unit = this.getUnit(f);
290
                    if( unit instanceof ScriptingFolder ) {
291
                        ol.add((ScriptingFolder) unit);
292
                    }
293
                } catch (Exception ex) {
294
                    logger.warn("Can't create unit from file '" + f.getAbsolutePath() + "'.");
295
                }
296
            }
297
        }
298
        return ol;
299
    }
300

    
301
    @Override
302
    public void add(ScriptingUnit unit) {
303
        unit.move(this);
304
    }
305

    
306
    @Override
307
    public void remove(ScriptingUnit unit) {
308
        unit.remove();
309
    }
310

    
311
    @Override
312
    public File getFileResource(String extension) {
313
        if( this.isLink() ) {
314
            return new File(
315
                    this.infFile.getParentFile(), 
316
                    FilenameUtils.getBaseName(this.infFile.getName()) + extension
317
                ).getAbsoluteFile();
318
        }
319
        return new File(
320
                this.getFile().getParentFile(), 
321
                this.getFile().getName() + extension
322
            ).getAbsoluteFile();
323
    }
324
    
325

    
326
    @Override
327
    public void save() {
328
        File f = this.infFile;
329
        if( f==null ) {
330
            f = new File(folder,"#folder.inf");
331
        }
332
        try {        
333
            Ini prefs = new Ini();
334
            prefs.setFile(f);
335
            if( this.linkTarget!=null ) {
336
                prefs.put(
337
                        ScriptingManager.UNIT_FOLDER, 
338
                        "path", 
339
                        relativizeFile(this.infFile.getParentFile(), this.linkTarget)
340
                );
341
            }
342
            if( this.iconNames!=null ) {
343
                prefs.put(ScriptingManager.UNIT_FOLDER, "iconName", this.iconNames[0]);
344
                prefs.put(ScriptingManager.UNIT_FOLDER, "iconNameOpen", this.iconNames[1]);
345
            }
346
            this.save(prefs);
347
        } catch (Throwable e) {
348
            String msg = "Can't save 'inf' file '" + f.getAbsolutePath() + "'.";
349
            logger.warn(msg, e);
350
            throw new RuntimeException(msg, e);
351
        }
352
    }
353
    
354
    @Override
355
    public void load(ScriptingFolder parent, String id) {
356
        this.infFile = null;
357
        this.linkTarget = null;
358
        this.iconNames = new String[]{"scripting-icon-folder", "scripting-icon-folder-open"};
359
        this.setId(id);
360
        this.setParent(parent);
361

    
362
        File fileInf = getFileResource(".inf");
363
        if (!fileInf.isFile()) {
364
            fileInf = new File(this.folder, "#folder.inf");
365
            if (!fileInf.isFile()) {
366
                return;
367
            }
368
        }
369
        Ini prefs;
370
        try {
371
            prefs = new Ini(fileInf);
372
            loadInf(prefs);
373
            String iconName = getInfString(
374
                    prefs,
375
                    ScriptingManager.UNIT_FOLDER,
376
                    "iconName",
377
                    null
378
            );
379
            String iconNameOpen = getInfString(
380
                    prefs,
381
                    ScriptingManager.UNIT_FOLDER,
382
                    "iconNameOpen",
383
                    null
384
            );
385
            if( iconName!=null ) {
386
                this.iconNames = new String[] {
387
                    iconName,
388
                    iconNameOpen==null? iconName:iconNameOpen
389
                };
390
            }
391
            String targetPath = getInfString(
392
                    prefs,
393
                    ScriptingManager.UNIT_FOLDER,
394
                    "path",
395
                    null
396
            );
397
            if( !StringUtils.isEmpty(targetPath) ) {
398
                File target = new File(targetPath);
399
                if (target.isAbsolute()) {
400
                    this.linkTarget = target;
401
                } else {
402
                    this.linkTarget = new File(FilenameUtils.concat(fileInf.getParent(), targetPath));
403
                }
404
                this.manager.addLink(this.infFile, this.linkTarget);
405
            }
406
            this.infFile = FileUtils.getAbsoluteFile(fileInf);
407
        } catch (Exception e) {
408
            logger.warn("Can't load 'inf' file '" + fileInf.getAbsolutePath() + "'.", e);
409
        }
410

    
411
    }
412

    
413
    @Override
414
    public String[] getIconNames() {
415
        return this.iconNames;
416
    }
417

    
418
    @Override
419
    public boolean remove() {
420
        File f = this.getFile();
421
        try {
422
            File infofile = getFileResource(".inf");
423
            if( infofile.exists() ) {
424
                FileUtils.forceDelete(infofile);
425
            }            
426
            if( !this.isLink() ) {
427
                if( f!=null ) {
428
                    FileUtils.forceDelete(this.getFile());
429
                }
430
            }
431
            return true;
432
        } catch (Throwable e) {
433
            logger.warn("Can't remove folder '" + ((f==null)?"unknown":f.getAbsolutePath()) + "'.", e);
434
            return false;
435
        }
436
    }
437

    
438
    @Override
439
    public boolean move(ScriptingFolder target) {
440
        if (! manager.validateUnitId(target, this.getId()) ) {
441
            logger.info("Can't move folder '"+this.getId()+"' to '"+target.getFile().getAbsolutePath()+"', is not valid.");
442
            return false;
443
        }
444
        try {
445
            File infofile = getFileResource(".inf");
446
            if( infofile.exists() ) {
447
                FileUtils.moveFileToDirectory(infofile, target.getFile(), true);
448
            }
449
            if( !this.isLink() ) {
450
                FileUtils.moveDirectoryToDirectory(this.getFile(), target.getFile(),true);
451
            }
452
            this.parent = target;
453
            this.load(target, id);
454
        } catch (IOException ex) {
455
            logger.info("Can't move folder '"+this.getId()+"' to '"+target.getFile().getAbsolutePath()+"', "+ex.getMessage(),ex);
456
            return false;
457
        }
458
        return true;
459
    }
460

    
461
    @Override
462
    public boolean rename(String newId) {
463
        if (! manager.validateUnitId(this.getParent(), newId) ) {
464
            logger.info("Can't rename folder '"+this.getId()+"', target id '"+newId+"' is not valid.");
465
            return false;
466
        }
467
        try {
468
            File target = this.getParent().getFile();
469
            File infofile = getFileResource(".inf");
470
            if( this.isLink() ) {
471
                FileUtils.moveFile(infofile, new File(target,newId));
472
            } else {
473
                FileUtils.moveDirectory(this.getFile(), new File(target,newId));
474
                if( infofile.exists() ) {
475
                    FileUtils.moveFile(infofile, new File(target,newId));
476
                }
477
            }
478
            this.setId(newId);
479
            this.load(this.getParent(), id);
480
        } catch (IOException ex) {
481
            logger.info("Can't rename folder '"+this.getId()+"' to '"+newId+"', "+ex.getMessage(),ex);
482
            return false;
483
        }        
484
        return true;
485
    }
486

    
487
    @Override
488
    public void accept(Visitor visitor) throws BaseException {
489
        List<ScriptingUnit> units = this.getUnits();
490
        for( ScriptingUnit unit : units ) {
491
            if( unit instanceof ScriptingFolder ) {
492
                ScriptingFolder folder = (ScriptingFolder) unit;
493
                folder.accept(visitor);
494
            } else {
495
                visitor.visit(unit);
496
            }
497
        }
498
    }
499
    
500
    @Override
501
    public boolean isLink() {
502
        return this.linkTarget!=null;
503
    }
504
    
505
    @Override
506
    public void accept(Visitor visitor, Predicate<ScriptingUnit> includeFilter) throws BaseException {
507
        List<ScriptingUnit> units = this.getUnits();
508
        for( ScriptingUnit unit : units ) {
509
            if( includeFilter.test(unit) ) {
510
                if( unit instanceof ScriptingFolder ) {
511
                    ScriptingFolder folder = (ScriptingFolder) unit;
512
                    folder.accept(visitor);
513
                } else {
514
                    visitor.visit(unit);
515
                }
516
            }
517
        }
518
    }
519

    
520
    @Override
521
    public String getRawInf() {
522
        if( this.infFile == null ) {
523
            return null;
524
        }
525
        try {
526
            String rawInf = org.apache.commons.io.FileUtils.readFileToString(infFile);
527
            return rawInf;
528
        } catch (IOException ex) {
529
            // TODO: 
530
        }
531
        return null;
532
    }
533
    
534
    @Override
535
    public void setRawInf(String rawInf) {
536
        if( this.infFile == null ) {
537
            this.infFile = new File(folder,"#folder.inf");
538
        }
539
        try {
540
            org.apache.commons.io.FileUtils.write(infFile, rawInf);
541
            this.reload();
542
        } catch (IOException ex) {
543
            // TODO: 
544
        }
545
    }
546
}