View Javadoc

1   /*******************************************************************************
2    * Copyright (c) 2005-2006 Polarion Software.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *    Alexander Gurov - Initial API and implementation
10   *    Gabor Liptak - Speedup Pattern's usage
11   *******************************************************************************/
12  package com.atlassian.theplugin.eclipse.util;
13  
14  import java.io.BufferedReader;
15  import java.io.File;
16  import java.io.FileFilter;
17  import java.io.FileInputStream;
18  import java.io.FileOutputStream;
19  import java.io.IOException;
20  import java.io.InputStreamReader;
21  import java.lang.reflect.Method;
22  import java.text.MessageFormat;
23  import java.util.Arrays;
24  import java.util.Collections;
25  import java.util.Comparator;
26  import java.util.HashMap;
27  import java.util.HashSet;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.MissingResourceException;
31  import java.util.ResourceBundle;
32  import java.util.Set;
33  
34  import org.eclipse.core.internal.preferences.Base64;
35  import org.eclipse.core.resources.IContainer;
36  import org.eclipse.core.resources.IProject;
37  import org.eclipse.core.resources.IResource;
38  import org.eclipse.core.resources.IResourceVisitor;
39  import org.eclipse.core.resources.IWorkspaceRoot;
40  import org.eclipse.core.resources.ResourcesPlugin;
41  import org.eclipse.core.runtime.CoreException;
42  import org.eclipse.core.runtime.IPath;
43  import org.eclipse.core.runtime.IProgressMonitor;
44  import org.eclipse.core.runtime.Platform;
45  
46  import com.atlassian.theplugin.eclipse.preferences.Activator;
47  
48  /**
49   * Common file processing functions
50   * 
51   * @author Alexander Gurov
52   */
53  public final class FileUtil {
54  	public static final IResource[] NO_CHILDREN = new IResource[0];
55  
56  	public static IResource selectOneOf(IResource[] scope, IResource[] set) {
57  		for (int i = 0; i < set.length; i++) {
58  			if (FileUtil.relatesTo(scope, set[i])) {
59  				return set[i];
60  			}
61  		}
62  		return null;
63  	}
64  
65  	public static boolean relatesTo(IResource[] set, IResource resource) {
66  		for (int i = 0; i < set.length; i++) {
67  			if (FileUtil.relatesTo(set[i], resource)) {
68  				return true;
69  			}
70  		}
71  		return false;
72  	}
73  
74  	public static boolean relatesTo(IResource set, IResource resource) {
75  		return set.equals(resource) ? true : (resource == null ? false
76  				: FileUtil.relatesTo(set, resource.getParent()));
77  	}
78  
79  	public static String getResource(ResourceBundle bundle, String key) {
80  		if (key == null) {
81  			return null;
82  		}
83  		if (bundle == null) {
84  			return key;
85  		}
86  		String retVal = FileUtil.getResourceImpl(bundle, key);
87  		if (retVal != null) {
88  			if (key.indexOf("Error") != -1) {
89  				String id = FileUtil.getResourceImpl(bundle, key + ".Id");
90  				if (id != null) {
91  					retVal = id + ": " + retVal;
92  				}
93  			}
94  			return retVal;
95  		}
96  		return key;
97  	}
98  
99  	public static String getWorkingCopyPath(IResource resource) {
100 		return FileUtil.getResourcePath(resource).toString();
101 	}
102 
103 	public static IPath getResourcePath(IResource resource) {
104 		IPath location = resource.getLocation();
105 		if (location == null) {
106 			String errMessage = Activator.getDefault().getResource(
107 					"Error.InaccessibleResource");
108 			throw new RuntimeException(MessageFormat.format(errMessage,
109 					new Object[] { resource.getFullPath().toString() }));
110 		}
111 		return location;
112 	}
113 
114 	@SuppressWarnings("unchecked")
115 	public static Map<String, String> getEnvironmentVariables() {
116 		try {
117 			Method getenv = System.class.getMethod("getenv", (Class[]) null);
118 			return (Map<String, String>) getenv.invoke((Object[]) null,
119 					(Object[]) null);
120 		} catch (Exception ex) {
121 			try {
122 				boolean isWindows = FileUtil.isWindows();
123 				Process p = isWindows ? Runtime.getRuntime().exec(
124 						"cmd.exe /c set") : Runtime.getRuntime().exec("env");
125 
126 				BufferedReader br = new BufferedReader(new InputStreamReader(p
127 						.getInputStream()));
128 				String varLine;
129 				Map<String, String> retVal = new HashMap<String, String>();
130 				while ((varLine = br.readLine()) != null) {
131 					int idx = varLine.indexOf('=');
132 					if (idx != -1) {
133 						String name = varLine.substring(0, idx);
134 						retVal.put(isWindows ? name.toUpperCase() : name,
135 								varLine.substring(idx + 1));
136 					} else if (varLine.length() > 0) {
137 						retVal.put(varLine, "");
138 					}
139 				}
140 				return retVal;
141 			} catch (IOException ex1) {
142 				return Collections.EMPTY_MAP;
143 			}
144 		}
145 	}
146 
147 	public static String normalizePath(String path) {
148 		return FileUtil.isWindows() ? path.replace('/', '\\') : path.replace(
149 				'\\', '/');
150 	}
151 
152 	public static boolean isWindows() {
153 		return FileUtil.getOSName().indexOf("windows") != -1;
154 	}
155 
156 	public static String getOSName() {
157 		return System.getProperty("os.name").toLowerCase();
158 	}
159 
160 	public static boolean isCaseInsensitiveOS() {
161 		return !(Platform.OS_MACOSX.equals(Platform.getOS()) ? false
162 				: new java.io.File("a").compareTo(new java.io.File("A")) != 0);
163 	}
164 
165 	public static boolean isLinked(IResource resource) {
166 		// Eclipse 3.2 and higher
167 		return resource.isLinked(IResource.CHECK_ANCESTORS);
168 	}
169 
170 	public static String[] asPathArray(IResource[] resources) {
171 		String[] retVal = new String[resources.length];
172 		for (int i = 0; i < resources.length; i++) {
173 			retVal[i] = FileUtil.normalizePath(FileUtil
174 					.getWorkingCopyPath(resources[i]));
175 		}
176 		return retVal;
177 	}
178 
179 	public static String[] asPathArray(File[] files) {
180 		String[] retVal = new String[files.length];
181 		for (int i = 0; i < files.length; i++) {
182 			retVal[i] = FileUtil.normalizePath(files[i].getAbsolutePath());
183 		}
184 		return retVal;
185 	}
186 
187 	/*
188 	 * public static String getResourceParent(IRepositoryResource resource) {
189 	 * String parent = ""; String url = resource.getUrl(); String rootUrl =
190 	 * resource.getRoot().getUrl(); if (url.equals(rootUrl)) { return ""; }
191 	 * parent = url.substring(rootUrl.length(), url.length() -
192 	 * resource.getName().length() - 1); return parent; }
193 	 */
194 
195 	public static String formatResourceName(String projectName) {
196 		// remove invalid characters when repository root was specified
197 		return PatternProvider.replaceAll(projectName, "([\\/:])+", ".");
198 	}
199 
200 	public static String formatPath(String path) {
201 		return PatternProvider.replaceAll(path, "\\\\", "/");
202 	}
203 
204 	public static String getUsernameParam(String username) {
205 		return username == null || username.trim().length() == 0 ? ""
206 				: " --username \"" + username + "\"";
207 	}
208 
209 	public static String flattenText(String text) {
210 		StringBuffer flat = new StringBuffer(text.length() + 20);
211 		boolean skipAdjacentLineSeparator = true;
212 		for (int i = 0; i < text.length(); i++) {
213 			char currentChar = text.charAt(i);
214 			if (currentChar == '\r' || currentChar == '\n') {
215 				if (!skipAdjacentLineSeparator) {
216 					flat.append("/");
217 				}
218 				skipAdjacentLineSeparator = true;
219 			} else {
220 				flat.append(currentChar);
221 				skipAdjacentLineSeparator = false;
222 			}
223 		}
224 		return flat.toString().replace('\t', ' ');
225 	}
226 
227 	public static int getMaxStringLength(String[] strings) {
228 		int result = 0;
229 		for (int i = 0; i < strings.length; i++) {
230 			result = Math.max(result, strings[i].length());
231 		}
232 		return result;
233 	}
234 
235 	public static String formatMultilineText(String text) {
236 		if (text.length() > 0 && text.substring(0, 1).matches("(\\s)+")) {
237 			text = text.replaceFirst("(\\s)+", "");
238 		}
239 		if (text.length() == 0) {
240 			return "";
241 		}
242 		text = text.replace('\t', ' ');
243 		int idx = text.indexOf('\n');
244 		int idx1 = text.indexOf('\r');
245 		if (idx == -1) {
246 			idx = idx1;
247 		}
248 		idx = idx < idx1 || idx1 == -1 ? idx : idx1;
249 		if (idx != -1) {
250 			if (text.substring(idx).trim().length() != 0) {
251 				return text.substring(0, idx) + "...";
252 			} else {
253 				return text.substring(0, idx);
254 			}
255 		}
256 		return text;
257 	}
258 
259 	@SuppressWarnings("restriction")
260 	public static String[] decodeStringToArray(String encodedString) {
261 		String[] valuesArray = new String[] {};
262 		if (encodedString != null && encodedString.length() > 0) {
263 			valuesArray = encodedString.split(";");
264 			for (int i = 0; i < valuesArray.length; i++) {
265 				valuesArray[i] = new String(Base64.decode(valuesArray[i]
266 						.getBytes()));
267 			}
268 		}
269 		return valuesArray;
270 	}
271 
272 	@SuppressWarnings("restriction")
273 	public static String encodeArrayToString(String[] valuesArray) {
274 		String result = "";
275 		for (int i = 0; i < valuesArray.length; i++) {
276 			String str = new String(Base64.encode(valuesArray[i].getBytes()));
277 			result += result.length() == 0 ? str : (";" + str);
278 		}
279 		return result;
280 	}
281 
282 	public static void visitNodes(IResource resource, IResourceVisitor visitor,
283 			int depth) throws CoreException {
284 		boolean stepInside = visitor.visit(resource);
285 		if (stepInside && resource instanceof IContainer
286 				&& depth != IResource.DEPTH_ZERO && resource.isAccessible()) {
287 
288 			IContainer container = (IContainer) resource;
289 			IResource[] children = FileUtil.resourceMembers(container, true);
290 			int nextDepth = depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO
291 					: depth;
292 			for (int i = 0; i < children.length; i++) {
293 				FileUtil.visitNodes(children[i], visitor, nextDepth);
294 			}
295 		}
296 	}
297 
298 	/*
299 	 * public static boolean checkForResourcesPresenceRecursive(IResource
300 	 * []roots, IStateFilter filter) { return
301 	 * FileUtil.checkForResourcesPresence(roots, filter,
302 	 * IResource.DEPTH_INFINITE); }
303 	 */
304 
305 	/*
306 	 * public static boolean checkForResourcesPresence(IResource []roots,
307 	 * IStateFilter filter, int depth) { IRemoteStorage storage =
308 	 * SVNRemoteStorage.instance();
309 	 * 
310 	 * ArrayList recursiveCheck = null; int nextDepth = IResource.DEPTH_ZERO; if
311 	 * (depth != IResource.DEPTH_ZERO) { recursiveCheck = new ArrayList();
312 	 * nextDepth = depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO :
313 	 * IResource.DEPTH_INFINITE; }
314 	 * 
315 	 * // first check all resources that are already accessible (performance
316 	 * optimizations) for (int i = 0; i < roots.length; i++) { if
317 	 * (roots[i].isTeamPrivateMember()) {//FileUtil.isSVNInternals(roots[i])
318 	 * continue; }
319 	 * 
320 	 * ILocalResource local = storage.asLocalResource(roots[i]); if (local !=
321 	 * null) { if (filter.accept(roots[i], local.getStatus(),
322 	 * local.getChangeMask())) { return true; } else if (roots[i] instanceof
323 	 * IContainer && depth != IResource.DEPTH_ZERO &&
324 	 * filter.allowsRecursion(roots[i], local.getStatus(),
325 	 * local.getChangeMask())) { recursiveCheck.add(roots[i]); } } }
326 	 * 
327 	 * // no resources accepted, check recursively (performance optimizations)
328 	 * if (depth != IResource.DEPTH_ZERO) { for (Iterator it =
329 	 * recursiveCheck.iterator(); it.hasNext(); ) { IContainer local =
330 	 * (IContainer)it.next(); if
331 	 * (FileUtil.checkForResourcesPresence(FileUtil.getAllMembers(local),
332 	 * filter, nextDepth)) { return true; } } } return false; }
333 	 */
334 
335 	/*
336 	 * public static IResource []getResourcesRecursive(IResource []roots,
337 	 * IStateFilter filter) { return FileUtil.getResourcesRecursive(roots,
338 	 * filter, IResource.DEPTH_INFINITE); }
339 	 */
340 
341 	/*
342 	 * public static IResource []getResourcesRecursive(IResource []roots,
343 	 * IStateFilter filter, int depth) { return
344 	 * FileUtil.getResourcesRecursive(roots, filter, depth, null, null); }
345 	 */
346 
347 	/*
348 	 * public static IResource []getResourcesRecursive(IResource []roots,
349 	 * IStateFilter filter, int depth, IActionOperation calledFrom,
350 	 * IProgressMonitor monitor) { Set resources = new HashSet();
351 	 * FileUtil.addChildren(resources, roots, filter, depth, calledFrom,
352 	 * monitor); return (IResource [])resources.toArray(new
353 	 * IResource[resources.size()]); }
354 	 * 
355 	 * public static IResource []addOperableParents(IResource []resources,
356 	 * IStateFilter stateFilter) { return FileUtil.addOperableParents(resources,
357 	 * stateFilter, false); }
358 	 * 
359 	 * public static IResource []addOperableParents(IResource []resources,
360 	 * IStateFilter stateFilter, boolean through) { HashSet tmp = new
361 	 * HashSet(Arrays.asList(resources));
362 	 * tmp.addAll(Arrays.asList(FileUtil.getOperableParents(resources,
363 	 * stateFilter, through))); return (IResource [])tmp.toArray(new
364 	 * IResource[tmp.size()]); }
365 	 * 
366 	 * public static IResource []getOperableParents(IResource []resources,
367 	 * IStateFilter stateFilter) { return FileUtil.getOperableParents(resources,
368 	 * stateFilter, false); }
369 	 * 
370 	 * public static IResource []getOperableParents(IResource []resources,
371 	 * IStateFilter stateFilter, boolean through) { HashSet tmp = new HashSet();
372 	 * IResource []parents = FileUtil.getParents(resources, true); if (!through)
373 	 * { FileUtil.reorder(parents, false); } for (int i = 0; i < parents.length;
374 	 * i++) { ILocalResource parent =
375 	 * SVNRemoteStorage.instance().asLocalResource(parents[i]); if (parent !=
376 	 * null && stateFilter.accept(parents[i], parent.getStatus(),
377 	 * parent.getChangeMask())) { tmp.add(parents[i]); } else if (!through) {
378 	 * IPath current = parents[i].getFullPath(); while (i < parents.length) { if
379 	 * (parents[i].getFullPath().isPrefixOf(current)) { i++; } else { i--;
380 	 * break; } } } } return (IResource [])tmp.toArray(new
381 	 * IResource[tmp.size()]); }
382 	 * 
383 	 * public static IResource []getParents(IResource []resources, boolean
384 	 * excludeIncoming) { HashSet parents = new HashSet(); for (int i = 0; i <
385 	 * resources.length; i++) { IResource parent = resources[i]; while ((parent
386 	 * = parent.getParent()) != null && !(parent instanceof IWorkspaceRoot)) {
387 	 * parents.add(parent); } if (parents == resources[i]) {
388 	 * parents.add(parent); } } if (excludeIncoming) {
389 	 * parents.removeAll(Arrays.asList(resources)); } return (IResource
390 	 * [])parents.toArray(new IResource[parents.size()]); }
391 	 * 
392 	 * public static boolean isSVNInternals(IResource resource) { if
393 	 * (SVNUtility.getSVNFolderName().equals(resource.getName())) { return true;
394 	 * } IResource parent = resource.getParent(); return parent == null ? false
395 	 * : FileUtil.isSVNInternals(parent); }
396 	 * 
397 	 * public static void findAndMarkSVNInternals(IResource node, boolean
398 	 * isTeamPrivate) throws CoreException { if (node instanceof IContainer &&
399 	 * !FileUtil.isLinked(node)) { if
400 	 * (SVNUtility.getSVNFolderName().equals(node.getName()) &&
401 	 * node.isTeamPrivateMember() != isTeamPrivate) {
402 	 * FileUtil.markSVNInternalsTree(node, isTeamPrivate); } else { IResource
403 	 * []children = FileUtil.resourceMembers((IContainer)node, false); for (int
404 	 * i = 0; i < children.length; i++) {
405 	 * FileUtil.findAndMarkSVNInternals(children[i], isTeamPrivate); } } } }
406 	 */
407 
408 	public static boolean deleteRecursive(File node) {
409 		return FileUtil.deleteRecursive(node, null);
410 	}
411 
412 	public static boolean deleteRecursive(File node, IProgressMonitor monitor) {
413 		if (node.isDirectory()) {
414 			File[] files = node.listFiles();
415 			if (files != null) {
416 				for (int i = 0; i < files.length
417 						&& (monitor == null || !monitor.isCanceled()); i++) {
418 					FileUtil.deleteRecursive(files[i], monitor);
419 				}
420 			}
421 		}
422 		return node.delete();
423 	}
424 
425 	public static void copyAll(File to, File what, IProgressMonitor monitor)
426 			throws Exception {
427 		FileUtil.copyAll(to, what, false, monitor);
428 	}
429 
430 	public static final int COPY_NO_OPTIONS = 0x00;
431 	public static final int COPY_IGNORE_EXISTING_FOLDERS = 0x01;
432 	public static final int COPY_OVERRIDE_EXISTING_FILES = 0x02;
433 
434 	public static void copyAll(File to, File what,
435 			boolean ignoreExistingFolders, IProgressMonitor monitor)
436 			throws Exception {
437 		FileUtil.copyAll(to, what,
438 				ignoreExistingFolders ? FileUtil.COPY_IGNORE_EXISTING_FOLDERS
439 						: FileUtil.COPY_NO_OPTIONS, null, monitor);
440 	}
441 
442 	public static void copyAll(File to, File what, int options,
443 			FileFilter filter, IProgressMonitor monitor) throws Exception {
444 		if (what.isDirectory()) {
445 			to = new File(to.getAbsolutePath() + "/" + what.getName());
446 			if (monitor.isCanceled()) {
447 				return;
448 			}
449 			if (!to.mkdirs()
450 					&& ((options & FileUtil.COPY_IGNORE_EXISTING_FOLDERS) == 0)) {
451 				String errMessage = Activator.getDefault().getResource(
452 						"Error.CreateDirectory");
453 				throw new Exception(MessageFormat.format(errMessage,
454 						new Object[] { to.getAbsolutePath() }));
455 			}
456 			File[] files = what.listFiles(filter);
457 			if (files != null) {
458 				for (int i = 0; i < files.length && !monitor.isCanceled(); i++) {
459 					FileUtil.copyAll(to, files[i], options, filter, monitor);
460 				}
461 			}
462 		} else {
463 			FileUtil.copyFile(to, what, options, monitor);
464 		}
465 	}
466 
467 	public static void copyFile(File to, File what, IProgressMonitor monitor)
468 			throws Exception {
469 		FileUtil.copyFile(to, what, FileUtil.COPY_OVERRIDE_EXISTING_FILES,
470 				monitor);
471 	}
472 
473 	public static void copyFile(File to, File what, int options,
474 			IProgressMonitor monitor) throws Exception {
475 		if (to.exists() && to.isDirectory()) {
476 			to = new File(to.getAbsolutePath() + "/" + what.getName());
477 		}
478 		if ((!to.exists() || (options & FileUtil.COPY_OVERRIDE_EXISTING_FILES) != 0)
479 				&& !monitor.isCanceled()) {
480 			FileOutputStream output = null;
481 			FileInputStream input = null;
482 			try {
483 				output = new FileOutputStream(to);
484 				input = new FileInputStream(what);
485 				byte[] buf = new byte[2048];
486 				int loaded = 0;
487 				while ((loaded = input.read(buf)) > 0 && !monitor.isCanceled()) {
488 					output.write(buf, 0, loaded);
489 				}
490 			} finally {
491 				if (output != null) {
492 					try {
493 						output.close();
494 					} catch (Exception ex) {
495 						//
496 					}
497 				}
498 				if (input != null) {
499 					try {
500 						input.close();
501 					} catch (Exception ex) {
502 						//
503 					}
504 				}
505 			}
506 		}
507 	}
508 
509 	/*
510 	 * public static void removeSVNMetaInformation(IResource root,
511 	 * IProgressMonitor monitor) throws CoreException { final List toRemove =
512 	 * new ArrayList();
513 	 * 
514 	 * root.accept(new IResourceVisitor() { public boolean visit(IResource
515 	 * resource) throws CoreException { if
516 	 * (SVNUtility.getSVNFolderName().equals(resource.getName()) &&
517 	 * !FileUtil.isLinked(resource)) { toRemove.add(resource); return false; }
518 	 * return true; } }, IResource.DEPTH_INFINITE, IContainer.INCLUDE_PHANTOMS |
519 	 * IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS);
520 	 * 
521 	 * for (Iterator it = toRemove.iterator(); it.hasNext(); ) { IResource
522 	 * resource = (IResource)it.next(); FileUtil.deleteRecursive(new
523 	 * File(resource.getLocation().toString())); } }
524 	 */
525 
526 	/*
527 	 * public static boolean alreadyOnSVN(IResource root) { return
528 	 * SVNUtility.getSVNInfoForNotConnected(root) != null; }
529 	 * 
530 	 * public static boolean isConnected(IResource resource) {
531 	 * RepositoryProvider provider =
532 	 * RepositoryProvider.getProvider(resource.getProject()); return provider !=
533 	 * null && provider instanceof IConnectedProjectInformation; }
534 	 */
535 
536 	public static IResource[] getPathNodes(IResource resource) {
537 		return FileUtil.getPathNodes(new IResource[] { resource });
538 	}
539 
540 	public static IResource[] getPathNodes(IResource[] resources) {
541 		List<IResource> tmp = Arrays.asList(resources);
542 		Set<IResource> modifiedRoots = new HashSet<IResource>();
543 		IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
544 
545 		for (int i = 0; i < resources.length; i++) {
546 			IResource root = resources[i];
547 			while ((root = root.getParent()) != wRoot) {
548 				if (!tmp.contains(root)) {
549 					modifiedRoots.add(root);
550 				} else {
551 					break;
552 				}
553 			}
554 		}
555 
556 		return (IResource[]) modifiedRoots.toArray(new IResource[modifiedRoots
557 				.size()]);
558 	}
559 
560 	public static void reorder(IResource[] resources, final boolean parent2Child) {
561 		Arrays.sort(resources, new Comparator<IResource>() {
562 			public int compare(IResource rf, IResource rs) {
563 				String first = rf.getFullPath().toString();
564 				String second = rs.getFullPath().toString();
565 				return parent2Child ? first.compareTo(second) : second
566 						.compareTo(first);
567 			}
568 		});
569 	}
570 
571 	public static void reorder(File[] files, final boolean parent2Child) {
572 		Arrays.sort(files, new Comparator<File>() {
573 			public int compare(File o1, File o2) {
574 				String first = ((File) o1).getAbsolutePath();
575 				String second = ((File) o2).getAbsolutePath();
576 				return parent2Child ? first.compareTo(second) : second
577 						.compareTo(first);
578 			}
579 		});
580 	}
581 
582 	public static IResource[] shrinkChildNodes(IResource[] resources) {
583 		Set<IResource> tRoots = new HashSet<IResource>(Arrays.asList(resources));
584 		for (int i = 0; i < resources.length; i++) {
585 			if (FileUtil.hasRoots(tRoots, resources[i])) {
586 				tRoots.remove(resources[i]);
587 			}
588 		}
589 		return (IResource[]) tRoots.toArray(new IResource[tRoots.size()]);
590 	}
591 
592 	public static File[] shrinkChildNodes(File[] files, boolean skipFiles) {
593 		Set<File> tRoots = new HashSet<File>(Arrays.asList(files));
594 		for (int i = 0; i < files.length; i++) {
595 			if (skipFiles && files[i].isFile()) {
596 				continue;
597 			}
598 			if (FileUtil.hasRoots(tRoots, files[i])) {
599 				tRoots.remove(files[i]);
600 			}
601 		}
602 		return (File[]) tRoots.toArray(new File[tRoots.size()]);
603 	}
604 
605 	public static IResource[] resourceMembers(IContainer node,
606 			boolean includePhantoms) throws CoreException {
607 		try {
608 			return node.members(includePhantoms);
609 		} catch (CoreException ex) {
610 			// if project asynchronously closed then skip node
611 			// checked only in case of exception and not before members() due to
612 			// non-transactional nature of isAccessible()/members() methods pair
613 			if (node.isAccessible()) {
614 				throw ex;
615 			}
616 		}
617 		return new IResource[0];
618 	}
619 
620 	/*
621 	 * public static String getNamesListAsString(Object []resources) { String
622 	 * resourcesNames = ""; String name = ""; for (int i = 0; i <
623 	 * resources.length; i++) { if (i == 4) { resourcesNames += "..."; break; }
624 	 * if (resources[i] instanceof IRepositoryResource) { name =
625 	 * ((IRepositoryResource)resources[i]).getName(); } else if (resources[i]
626 	 * instanceof IResource) { name = ((IResource)resources[i]).getName(); }
627 	 * else { name = resources[i].toString(); } resourcesNames += (i == 0 ? "'"
628 	 * : ", '") + name + "'"; }
629 	 * 
630 	 * return resourcesNames; }
631 	 */
632 
633 	public static boolean hasNature(IResource resource, String natureId)
634 			throws CoreException {
635 		IProject project = resource.getProject();
636 		if (project == null) {
637 			return false;
638 		}
639 		String[] natureIds = project.getDescription().getNatureIds();
640 		for (int i = 0; i < natureIds.length; i++) {
641 			if (natureId.equals(natureIds[i])) {
642 				return true;
643 			}
644 		}
645 		return false;
646 	}
647 
648 	private static boolean hasRoots(Set<IResource> roots, IResource node) {
649 		while ((node = node.getParent()) != null) {
650 			if (roots.contains(node)) {
651 				return true;
652 			}
653 		}
654 		return false;
655 	}
656 
657 	private static boolean hasRoots(Set<File> roots, File node) {
658 		while ((node = node.getParentFile()) != null) {
659 			if (roots.contains(node)) {
660 				return true;
661 			}
662 		}
663 		return false;
664 	}
665 
666 	/*
667 	 * private static void markSVNInternalsTree(IResource node, boolean
668 	 * isTeamPrivate) throws CoreException { if (node instanceof IContainer) {
669 	 * IResource []children = FileUtil.resourceMembers((IContainer)node, false);
670 	 * for (int i = 0; i < children.length; i++) {
671 	 * FileUtil.markSVNInternalsTree(children[i], isTeamPrivate); } }
672 	 * node.setTeamPrivateMember(isTeamPrivate); }
673 	 */
674 
675 	/*
676 	 * private static void addChildren(Set resources, IResource []roots,
677 	 * IStateFilter filter, int depth, IActionOperation calledFrom,
678 	 * IProgressMonitor monitor) { int nextDepth = depth == IResource.DEPTH_ONE
679 	 * ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE; IRemoteStorage storage
680 	 * = SVNRemoteStorage.instance(); for (int i = 0; i < roots.length &&
681 	 * (monitor == null || !monitor.isCanceled()); i++) { if
682 	 * (roots[i].isTeamPrivateMember()) {//FileUtil.isSVNInternals(roots[i])
683 	 * continue; }
684 	 * 
685 	 * if (monitor != null) { String path = roots[i].getFullPath().toString();
686 	 * if (calledFrom != null) { ProgressMonitorUtility.setTaskInfo(monitor,
687 	 * calledFrom, path); } else { monitor.subTask(path); }
688 	 * ProgressMonitorUtility.progress(monitor, 1, IProgressMonitor.UNKNOWN); }
689 	 * 
690 	 * ILocalResource local = storage.asLocalResource(roots[i]); if (local ==
691 	 * null) { continue; }
692 	 * 
693 	 * if (filter.accept(roots[i], local.getStatus(), local.getChangeMask())) {
694 	 * resources.add(roots[i]); }
695 	 * 
696 	 * if (roots[i] instanceof IContainer && depth != IResource.DEPTH_ZERO &&
697 	 * filter.allowsRecursion(roots[i], local.getStatus(),
698 	 * local.getChangeMask())) { FileUtil.addChildren(resources,
699 	 * FileUtil.getAllMembers((IContainer)roots[i]), filter, nextDepth,
700 	 * calledFrom, monitor); } } }
701 	 * 
702 	 * private static IResource []getAllMembers(IContainer root) {
703 	 * GetAllResourcesOperation op = new GetAllResourcesOperation(root);
704 	 * ProgressMonitorUtility.doTaskExternalDefault(op, new
705 	 * NullProgressMonitor()); return op.getChildren(); }
706 	 */
707 
708 	private static String getResourceImpl(ResourceBundle bundle, String key) {
709 		try {
710 			return bundle.getString(key);
711 		} catch (MissingResourceException ex) {
712 			return null;
713 		}
714 	}
715 
716 	private FileUtil() {
717 	}
718 
719 }