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