2 * ******************************************************************************
\r
3 * Copyright (C) 2007, International Business Machines Corporation and others.
\r
4 * All Rights Reserved.
\r
5 * ******************************************************************************
\r
7 package com.ibm.icu.dev.tool.tzu;
\r
10 import java.io.IOException;
\r
11 import java.util.ArrayList;
\r
12 import java.util.Iterator;
\r
13 import java.util.List;
\r
16 * Finds all updatable ICU4J jars in a set of specified directories.
\r
18 public class ICUJarFinder {
\r
21 * The delay in milliseconds between showing directories to the command line user.
\r
23 public static final long DELAY = 5000; // 5 seconds
\r
26 * The delay in milliseconds between showing directories to the command line user.
\r
28 public static long lastShowtime = 0; // 5 seconds
\r
31 * Searchs the directories / files represented in <code>paths</code> for valid ICU4J jars. The
\r
32 * logic for determining if a file is an ICU4J jar is taken care of by the constructor of
\r
33 * ICUFile. The resulting ICUFile's are then added to the result model.
\r
35 * @param resultModel
\r
36 * The result model to add any discovered ICU4J jars to.
\r
38 * The current logger.
\r
40 * The list of paths to include to and exclude from the search.
\r
42 * Whether to include subdirectories in the search.
\r
44 * The base directory of the tool.
\r
46 * The backup directory, or null if none. The backup directory is excluded from the
\r
48 * @return The same result model as given.
\r
49 * @throws InterruptedException
\r
51 public static ResultModel search(ResultModel resultModel, Logger logger, IncludePath[] paths,
\r
52 boolean subdirs, File curDir, File backupDir) throws InterruptedException {
\r
53 // sift the included / excluded paths into two seperate arraylists
\r
54 List included = new ArrayList();
\r
55 List excluded = new ArrayList();
\r
56 for (int i = 0; i < paths.length; i++) {
\r
57 IncludePath path = paths[i];
\r
58 File file = path.getPath();
\r
60 file = file.getCanonicalFile();
\r
61 } catch (IOException ex) {
\r
62 // recover in the simplest way, but report the error
\r
63 file = file.getAbsoluteFile();
\r
64 logger.errorln(ex.getMessage());
\r
66 if (path.isIncluded())
\r
72 // if the backup dir is specified, don't search it
\r
73 if (backupDir != null) {
\r
74 File file = backupDir;
\r
76 file = file.getCanonicalFile();
\r
77 } catch (IOException ex) {
\r
78 // recover in the simplest way, but report the error
\r
79 file = file.getAbsoluteFile();
\r
80 logger.errorln(ex.getMessage());
\r
85 // exclude the icu4j.jar that comes with this tool
\r
86 File file = new File(curDir.getPath(), "icu4j.jar");
\r
88 file = file.getCanonicalFile();
\r
89 } catch (IOException ex) {
\r
90 // recover in the simplest way, but report the error
\r
91 file = file.getAbsoluteFile();
\r
92 logger.errorln(ex.getMessage());
\r
96 // search each of the included files/directories
\r
97 for (int i = 0; i < included.size(); i++)
\r
98 search(resultModel, logger, (File) included.get(i), excluded, subdirs, 0);
\r
100 // chain the result model
\r
101 return resultModel;
\r
105 * Checks a specific file. If the file is an ICU4J jar that can be updated, then the ICUFile
\r
106 * representing that file is added to the result model. If the file is a directory, the
\r
107 * directory is then recursed.
\r
109 * @param resultModel
\r
110 * The result model to add any discovered ICU4J jars to.
\r
112 * The current logger.
\r
114 * The status bar for status-bar messages, or null if none is present.
\r
116 * The current file to check or directory to search.
\r
118 * The list of all directories excluded in the search.
\r
120 * Whether to include subdirectories in the search.
\r
122 * The current depth of the search.
\r
123 * @return The same result model as given.
\r
124 * @throws InterruptedException
\r
126 private static ResultModel search(ResultModel resultModel, Logger logger, File file,
\r
127 List excluded, boolean subdirs, int depth) throws InterruptedException {
\r
128 // ensure we are not following a symbolic link
\r
129 if (isSymbolic(file))
\r
130 return resultModel;
\r
132 // ensure that the file is in canonical form
\r
134 file = file.getCanonicalFile();
\r
135 } catch (IOException ex) {
\r
136 logger.errorln(ex.getMessage());
\r
137 return resultModel;
\r
140 // check for interruptions
\r
141 if (Thread.currentThread().isInterrupted())
\r
142 throw new InterruptedException();
\r
144 // make sure the current file/directory isn't excluded
\r
145 Iterator iter = excluded.iterator();
\r
146 while (iter.hasNext())
\r
147 if (file.equals(((File) iter.next())))
\r
148 return resultModel;
\r
150 if ((subdirs || depth == 0) && file.isDirectory()) {
\r
151 // recurse through each file/directory inside this directory
\r
152 File[] dirlist = file.listFiles();
\r
153 if (dirlist != null && dirlist.length > 0) {
\r
154 // notify the user that something is happening
\r
155 long curTime = System.currentTimeMillis();
\r
156 if (depth <= 1 || curTime - lastShowtime > DELAY) {
\r
157 lastShowtime = curTime;
\r
158 logger.printlnToScreen(file.getPath());
\r
160 // give a chance for the UI to display the message
\r
161 if (Thread.currentThread().isInterrupted())
\r
162 throw new InterruptedException();
\r
167 for (int i = 0; i < dirlist.length; i++)
\r
168 search(resultModel, logger, dirlist[i], excluded, subdirs, depth + 1);
\r
171 // attempt to create an ICUFile object on the current file and add
\r
172 // it to the result model if possible
\r
174 // if the file/directory is an ICU jar file that we can
\r
175 // update, add it to the results
\r
176 resultModel.add(new ICUFile(file, logger));
\r
177 logger.printlnToBoth("Added " + file.getPath());
\r
178 } catch (IOException ex) {
\r
179 // if it's not an ICU jar file that we can update, ignore it
\r
183 // chain the result model
\r
184 return resultModel;
\r
188 * Tests whether a file is a symbolic link by comparing the absolute path with the canonical
\r
192 * The file to check.
\r
193 * @return Whether the file is a symbolic link.
\r
195 private static boolean isSymbolic(File file) {
\r
197 File parent = file.getParentFile();
\r
198 if (parent == null)
\r
199 parent = new File(".");
\r
200 File betterFile = new File(parent.getCanonicalPath(), file.getName());
\r
201 return !betterFile.getAbsoluteFile().equals(betterFile.getCanonicalFile());
\r
202 } catch (IOException ex) {
\r
203 // if getCanonicalFile throws an IOException for this file, we won't
\r
204 // want to dig into this path
\r
210 * An empty constructor that restricts construction.
\r
212 private ICUJarFinder() {
\r