1 package com.atlassian.plugin.loaders;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.apache.commons.lang.Validate;
6
7 import java.io.File;
8 import java.util.*;
9
10 import com.atlassian.plugin.loaders.classloading.*;
11 import com.atlassian.plugin.PluginException;
12
13
14
15
16
17
18 class DirectoryScanner implements com.atlassian.plugin.loaders.classloading.Scanner
19 {
20 private static Log log = LogFactory.getLog(DirectoryScanner.class);
21
22
23
24
25 private final File pluginsDirectory;
26
27
28
29
30 private final Map<String,DeploymentUnit> scannedDeploymentUnits = new TreeMap<String,DeploymentUnit>();
31
32
33
34
35
36
37
38 public DirectoryScanner(File pluginsDirectory)
39 {
40 Validate.notNull(pluginsDirectory, "Plugin scanner directory must not be null");
41 this.pluginsDirectory = pluginsDirectory;
42 }
43
44 private DeploymentUnit createAndStoreDeploymentUnit(File file)
45 {
46 if (isScanned(file))
47 return null;
48
49 DeploymentUnit unit = new DeploymentUnit(file);
50 scannedDeploymentUnits.put(file.getAbsolutePath(), unit);
51
52 return unit;
53 }
54
55
56
57
58
59
60 public DeploymentUnit locateDeploymentUnit(File file)
61 {
62 return scannedDeploymentUnits.get(file.getAbsolutePath());
63 }
64
65
66
67
68 private boolean isScanned(File file)
69 {
70 return locateDeploymentUnit(file) != null;
71 }
72
73
74
75
76
77
78
79 public void clear(File file)
80 {
81 scannedDeploymentUnits.remove(file.getAbsolutePath());
82 }
83
84
85
86
87
88
89 public Collection<DeploymentUnit> scan()
90 {
91
92 List<File> removedFiles = new ArrayList<File>();
93 for (DeploymentUnit unit : scannedDeploymentUnits.values())
94 {
95 if (!unit.getPath().exists() || !unit.getPath().canRead())
96 {
97 removedFiles.add(unit.getPath());
98 }
99 }
100 clear(removedFiles);
101
102
103 Collection<DeploymentUnit> result = new ArrayList<DeploymentUnit>();
104 File files[] = pluginsDirectory.listFiles();
105 if (files == null)
106 {
107 log.error("listFiles returned null for directory " + pluginsDirectory.getAbsolutePath());
108 return result;
109 }
110
111 Arrays.sort(files);
112 for (File file : files)
113 {
114 if (isScanned(file) && isModified(file))
115 {
116 clear(file);
117 DeploymentUnit unit = createAndStoreDeploymentUnit(file);
118 if (unit != null)
119 result.add(unit);
120 }
121 else if (!isScanned(file))
122 {
123 DeploymentUnit unit = createAndStoreDeploymentUnit(file);
124 if (unit != null)
125 result.add(unit);
126 }
127 }
128 return result;
129 }
130
131 private boolean isModified(File file)
132 {
133 DeploymentUnit unit = locateDeploymentUnit(file);
134 return file.lastModified() > unit.lastModified();
135 }
136
137 private void clear(List<File> toUndeploy)
138 {
139 for (File aToUndeploy : toUndeploy)
140 {
141 clear( aToUndeploy);
142 }
143 }
144
145
146
147
148
149
150 public Collection<DeploymentUnit> getDeploymentUnits()
151 {
152 return Collections.unmodifiableCollection(scannedDeploymentUnits.values());
153 }
154
155
156
157
158 public void reset()
159 {
160 scannedDeploymentUnits.clear();
161 }
162
163 public void remove(DeploymentUnit unit) throws PluginException
164 {
165 if (!unit.getPath().delete())
166 throw new PluginException("Unable to delete file: " + unit.getPath());
167
168 clear(unit.getPath());
169 }
170 }