1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
|
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.sourceforge.jnlp.config;
import static net.sourceforge.jnlp.runtime.Translator.R;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.jnlp.runtime.JNLPRuntime;
import net.sourceforge.jnlp.util.FileUtils;
import net.sourceforge.jnlp.util.logging.OutputController;
/**
*
* @author jvanek
*/
public class DirectoryValidator {
/**
* This class is holding results of directory validation.
* Various errors like can not read, write create dir can apeear
* For sumaries of results are here getPasses, getFailures methods
*
* Individual results can be read from results field, or converted to string
*/
public static class DirectoryCheckResults {
public final List<DirectoryCheckResult> results;
/**
* Wraps results so we can make some statistics or convert to message
* @param results
*/
public DirectoryCheckResults(List<DirectoryCheckResult> results) {
this.results = results;
}
/**
*
* @return sum of passed checks, 0-3 per result
*/
public int getPasses() {
int passes = 0;
for (DirectoryCheckResult directoryCheckResult : results) {
passes += directoryCheckResult.getPasses();
}
return passes;
}
/**
*
* @return sum of failed checks, 0-3 per results
*/
public int getFailures() {
int failures = 0;
for (DirectoryCheckResult directoryCheckResult : results) {
failures += directoryCheckResult.getFailures();
}
return failures;
}
/**
* The result have one reuslt per line, separated by \n
* as is inherited from result.getMessage() method.
*
* @return all results connected.
*/
public String getMessage(){
return resultsToString(results);
}
/**
* using getMessage
* @return
*/
@Override
public String toString() {
return getMessage();
}
public static String resultsToString(List<DirectoryCheckResult> results) {
StringBuilder sb = new StringBuilder();
for (DirectoryCheckResult r : results) {
if (r.getFailures() >0 ){
sb.append(r.getMessage());
}
}
return sb.toString();
}
}
/**
* Is storing result of directory validation.
*
* validated are existence of directory
* whether it is directory
* if it have read/write permissions
*/
public static class DirectoryCheckResult {
//do exist?
public boolean exists = true;
//is dir?
public boolean isDir = true;
//can be read, written to?
public boolean correctPermissions = true;
//have correct subdir? - this implies soe rules, when subdirecotry of some
//particular directory have weeker permissions
public DirectoryCheckResult subDir = null;
//actual tested directory
private final File testedDir;
public DirectoryCheckResult(File testedDir) {
this.testedDir = testedDir;
}
public static String notExistsMessage(File f) {
return R("DCmaindircheckNotexists", f.getAbsolutePath());
}
public static String notDirMessage(File f) {
return R("DCmaindircheckNotdir", f.getAbsolutePath());
}
public static String wrongPermissionsMessage(File f) {
return R("DCmaindircheckRwproblem", f.getAbsolutePath());
}
private static int booleanToInt(boolean b) {
if (b) {
return 1;
} else {
return 0;
}
}
/**
* count passes of this result (0-3, both inclusive).
*/
public int getPasses() {
int subdirs = 0;
if (subDir != null) {
subdirs = subDir.getPasses();
}
return booleanToInt(exists)
+ booleanToInt(isDir)
+ booleanToInt(correctPermissions)
+ subdirs;
}
/*
* count failures of this result (0-3, both inclusive).
*/
public int getFailures() {
int max = 3;
if (subDir != null) {
max = 2 * max;
}
return max - getPasses();
}
/**
* Convert results to string.
* Each failure by line. PAsses are not mentioned
* The subdirectory (and it subdirectories are included to )
*
* @return string with \n, or/and ended by \n
*/
public String getMessage() {
StringBuilder sb = new StringBuilder();
if (!exists) {
sb.append(notExistsMessage(testedDir)).append("\n");
}
if (!isDir) {
sb.append(notDirMessage(testedDir)).append("\n");
}
if (!correctPermissions) {
sb.append(wrongPermissionsMessage(testedDir)).append("\n");
}
if (subDir != null) {
String s = subDir.getMessage();
if (!s.isEmpty()) {
sb.append(s);
}
}
return sb.toString();
}
@Override
public String toString() {
return getMessage();
}
}
private final List<File> dirsToCheck;
/**
* Creates DirectoryValidator to ensure given directories
*
* @param dirsToCheck
*/
public DirectoryValidator(List<File> dirsToCheck) {
this.dirsToCheck = dirsToCheck;
}
/**
* Creates DirectoryValidator to ensure directories read from
* user (if any - default otherwise ) settings via keys:
* <ul>
* <li>KEY_USER_CACHE_DIR</li>
* <li>KEY_USER_PERSISTENCE_CACHE_DIR</li>
* <li>KEY_SYSTEM_CACHE_DIR</li>
* <li>KEY_USER_LOG_DIR</li>
* <li>KEY_USER_TMP_DIR</li>
* <li>KEY_USER_LOCKS_DIR</li>
* </ul>
*/
public DirectoryValidator() {
dirsToCheck = new ArrayList<File>(6);
DeploymentConfiguration dc = JNLPRuntime.getConfiguration();
String[] keys = new String[]{
DeploymentConfiguration.KEY_USER_CACHE_DIR,
DeploymentConfiguration.KEY_USER_PERSISTENCE_CACHE_DIR,
DeploymentConfiguration.KEY_SYSTEM_CACHE_DIR,
DeploymentConfiguration.KEY_USER_LOG_DIR,
DeploymentConfiguration.KEY_USER_TMP_DIR,
DeploymentConfiguration.KEY_USER_LOCKS_DIR};
for (String key : keys) {
String value = dc.getProperty(key);
if (value == null) {
OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG, "WARNING: key " + key + " has no value, setting to default value");
value = Defaults.getDefaults().get(key).getValue();
}
if (value == null) {
if (JNLPRuntime.isDebug()) {
OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG, "WARNING: key " + key + " has no value, skipping");
}
continue;
}
File f = new File(value);
dirsToCheck.add(f);
}
}
/**
* This method is ensuring, that specified directories will exists after
* call and will have enough permissions.
*
* This methods is trying to create the directories if they are not present
* and is testing if can be written inside. All checks are done in bulk. If
* one or more defect is found, user is warned via dialogue in gui mode
* (again in bulk). In headless mode stdout/stderr is enough, as application
* (both gui and headless) should not stop to work, but continue to run with
* hope that corrupted dirs will not be necessary
*/
public DirectoryCheckResults ensureDirs() {
return ensureDirs(dirsToCheck);
}
static DirectoryCheckResults ensureDirs(List<File> dirs) {
List<DirectoryCheckResult> result = new ArrayList<DirectoryCheckResult>(dirs.size());
for (File f : dirs) {
if (f.exists()) {
DirectoryCheckResult r = testDir(f, true, true);
result.add(r);
continue;
}
if (!f.mkdirs()) {
OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "ERROR: Directory " + f.getAbsolutePath() + " does not exist and has not been created");
} else {
OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG,"OK: Directory " + f.getAbsolutePath() + " did not exist but has been created");
}
DirectoryCheckResult r = testDir(f, true, true);
result.add(r);
}
return new DirectoryCheckResults(result);
}
/**
* This method is package private for testing purposes only.
*
* This method verify that directory exists, is directory, file and
* directory can be created, file can be written into, and subdirectory can
* be written into.
*
* Some steps may looks like redundant, but some permission settings really
* alow to create file but not directory and vice versa. Also some settings
* can allow to create file or directory which can not be written into. (eg
* ACL or network disks)
*/
static DirectoryCheckResult testDir(File f, boolean verbose, boolean testSubdir) {
DirectoryCheckResult result = new DirectoryCheckResult(f);
if (!f.exists()) {
if (verbose) {
OutputController.getLogger().log(OutputController.Level.ERROR_ALL, DirectoryCheckResult.notExistsMessage(f));
}
result.exists = false;
}
if (!f.isDirectory()) {
if (verbose) {
OutputController.getLogger().log(OutputController.Level.ERROR_ALL, DirectoryCheckResult.notDirMessage(f));
}
result.isDir = false;
}
File testFile = null;
boolean correctPermissions = true;
try {
testFile = File.createTempFile("maindir", "check", f);
if (!testFile.exists()) {
correctPermissions = false;
}
try {
FileUtils.saveFile("ww", testFile);
String s = FileUtils.loadFileAsString(testFile);
if (!s.trim().equals("ww")) {
correctPermissions = false;
}
} catch (Exception ex) {
if (JNLPRuntime.isDebug()) {
ex.printStackTrace();
}
correctPermissions = false;
}
File[] canList = f.listFiles();
if (canList == null || canList.length == 0) {
correctPermissions = false;
}
testFile.delete();
if (testFile.exists()) {
correctPermissions = false;
} else {
boolean created = testFile.mkdir();
if (!created) {
correctPermissions = false;
}
if (testFile.exists()) {
if (testSubdir) {
DirectoryCheckResult subdirResult = testDir(testFile, verbose, false);
if (subdirResult.getFailures() != 0) {
result.subDir = subdirResult;
correctPermissions = false;
}
testFile.delete();
if (testFile.exists()) {
correctPermissions = false;
}
}
} else {
correctPermissions = false;
}
}
} catch (Exception ex) {
if (JNLPRuntime.isDebug()) {
ex.printStackTrace();
}
correctPermissions = false;
} finally {
if (testFile != null && testFile.exists()) {
testFile.delete();
}
}
if (!correctPermissions) {
if (verbose) {
OutputController.getLogger().log(OutputController.Level.ERROR_ALL, DirectoryCheckResult.wrongPermissionsMessage(f));
}
result.correctPermissions = false;
}
return result;
}
}
|