blob: 785093c2d4569a06f8e7e1c17fdb9b733a8266e6 [file] [log] [blame]
/*
* ******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and others.
* All Rights Reserved.
* ******************************************************************************
*/
package com.ibm.icu.dev.tool.tzu;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.swing.AbstractListModel;
/**
* Represents a list of IncludePaths that is usable by any class that uses AbstractListModels (such
* as a JList in swing). Also contains methods to begin a search on those paths using ICUJarFinder
* and placing the results in a ResultModel, and methods to load a path list from a file.
*/
class PathModel extends AbstractListModel {
/**
* The serializable UID.
*/
public static final long serialVersionUID = 1337;
/**
* The list of paths as IncludePaths.
*/
private List list = new ArrayList();
/**
* The current logger.
*/
private Logger logger;
/**
* The paths file where the paths are stored.
*/
private File pathListFile;
/**
* The filename of the paths file where the paths are stored.
*/
private String pathListFilename;
/**
* Constructs an empty path model.
*
* @param pathFile
* The file to load the path list from.
* @param logger
* The current logger.
*/
public PathModel(Logger logger, File pathFile) {
this.logger = logger;
this.pathListFile = pathFile;
this.pathListFilename = pathFile.getName();
}
/**
* Adds an IncludePath to the path list if it exists and is unique.
*
* @param path
* An existing path.
* @return Whether or not the given IncludePath exists.
*/
public boolean add(IncludePath path) {
remove(path);
if (path.getPath().exists()) {
list.add(path);
int index = list.size() - 1;
fireIntervalAdded(this, index, index);
return true;
}
return false;
}
/**
* Adds a filename to the path list if it is valid and unique. The filename must either be of
* the form (<b>+</b>|<b>-</b>)<i>pathstring</i> and exist, or of the form <b>all</b>. In
* the case of the latter, all drives are added to the path list.
*
* @param includeFilename
* A filename in the form above.
* @return Whether or not <code>includeFilename</code> is both of the form detailed above and
* exists.
*/
public boolean add(String includeFilename) {
if ("all".equalsIgnoreCase(includeFilename)) {
logger
.printlnToScreen("The tool will search all drives for ICU4J jars except any excluded directories specified");
addAllDrives();
return true;
}
return add(new IncludePath(new File(includeFilename.substring(1).trim()), includeFilename
.charAt(0) == '+'));
}
/**
* Adds all drives to the path list.
*/
public void addAllDrives() {
File[] roots = File.listRoots();
for (int i = 0; i < roots.length; i++)
add(new IncludePath(roots[i], true));
}
/**
* Returns the path at the element at a particular index of the path list.
*
* @param index
* The index of the element of the path list to return.
* @return The path at the specified index of the path list. Guaranteed to always be an
* IncludePath.
*/
public Object getElementAt(int index) {
return list.get(index);
}
/**
* Returns the size of the path list.
*
* @return The size of the path list.
*/
public int getSize() {
return (list == null) ? 0 : list.size();
}
/**
* Returns an iterator of the path list.
*
* @return An iterator of the path list.
*/
public Iterator iterator() {
return list.iterator();
}
/**
* Loads a list of paths from the given path list file. Each path must be of the form
*
* @throws IOException
* @throws IllegalArgumentException
*/
public void loadPaths() throws IOException, IllegalArgumentException {
logger.printlnToBoth("Scanning " + pathListFilename + " file...");
logger.loglnToBoth(pathListFilename + " file contains");
BufferedReader reader = null;
int lineNumber = 0;
String line;
char sign;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(pathListFile),
"UTF-8"), 4 * 1024);
while ((line = reader.readLine()) != null) {
if (line.length() >= 1 && line.charAt(0) == '\ufeff')
line = line.substring(1);
line = line.trim();
lineNumber++;
if (line.length() >= 1 && (sign = line.charAt(0)) != '#') {
if (sign != '+' && sign != '-' && !"all".equalsIgnoreCase(line)) {
String error = "Each path entry must start with a + or - to denote inclusion/exclusion";
pathListError(error, lineNumber);
continue;
}
if (!add(line)) {
String error = line.substring(1).trim()
+ " is not a valid file or directory (perhaps it does not exist?)";
pathListError(error, lineNumber);
continue;
}
logger.printlnToBoth(line);
}
}
logger.printlnToBoth("Scanning " + pathListFilename + " complete.");
} catch (FileNotFoundException ex) {
pathListError("The " + pathListFilename + " file doesn't exist.");
} catch (IOException ex) {
pathListError("Could not read the " + pathListFilename + " file.");
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException ex) {
}
}
}
/**
* Removes a path from the path list. Since there are no duplicates in the path list, this
* method either removes a single path or removes none.
*
* @param path
* The path to remove from the path list.
*/
public void remove(IncludePath path) {
int index = list.indexOf(path);
if (index != -1) {
list.remove(index);
fireIntervalRemoved(this, index, index);
}
}
/**
* Removes a selection of paths from the path list by index.
*
* @param indices
* The indices of the path list to remove.
*/
public void remove(int[] indices) {
if (list.size() > 0 && indices.length > 0) {
Arrays.sort(indices);
int max = indices[indices.length - 1];
int min = indices[0];
for (int i = indices.length - 1; i >= 0; i--)
list.remove(indices[i]);
fireIntervalRemoved(this, min, max);
}
}
/**
* Clears the path list.
*/
public void removeAll() {
if (list.size() > 0) {
int index = list.size() - 1;
list.clear();
fireIntervalRemoved(this, 0, index);
}
}
/**
* Searches a selection of paths in the path list for updatable ICU4J jars. Results are added to
* the result model. The indices provided are the indices of the path list to search.
*
* @param resultModel
* The result model to store the results of the search.
* @param indices
* The indices of the path list to use in the search.
* @param subdirs
* Whether to search subdiretories.
* @param curDir
* The base directory of the tool.
* @param backupDir
* Where to store backup files.
* @throws InterruptedException
*/
public void search(ResultModel resultModel, int[] indices, boolean subdirs, File curDir,
File backupDir) throws InterruptedException {
if (list.size() > 0 && indices.length > 0) {
Arrays.sort(indices);
int n = indices.length;
IncludePath[] paths = new IncludePath[n];
int k = 0;
Iterator iter = iterator();
for (int i = 0; k < n && iter.hasNext(); i++)
if (i == indices[k])
paths[k++] = (IncludePath) iter.next();
else
iter.next();
ICUJarFinder.search(resultModel, logger, paths, subdirs, curDir, backupDir);
}
}
/**
* Searches each path in the path list for updatable ICU4J jars. Results are added to the result
* model.
*
* @param resultModel
* The result model to store the results of the search.
* @param subdirs
* Whether to search subdiretories.
* @param curDir
* The base directory of the tool.
* @param backupDir
* Where to store backup files.
* @throws InterruptedException
*/
public void searchAll(ResultModel resultModel, boolean subdirs, File curDir, File backupDir)
throws InterruptedException {
if (list.size() > 0) {
int n = list.size();
IncludePath[] paths = new IncludePath[n];
Iterator iter = iterator();
for (int i = 0; i < n; i++)
paths[i] = (IncludePath) iter.next();
ICUJarFinder.search(resultModel, logger, paths, subdirs, curDir, backupDir);
}
}
/**
* Throws an IOException with the specified message.
*
* @param message
* The message to put in the exception.
* @throws IOException
*/
private void pathListError(String message) throws IOException {
throw new IOException("Error in " + pathListFilename + ": " + message);
}
/**
* Logs as an error a specified message and line number.
*
* @param message
* The message to put in the exception.
* @param lineNumber
* The line number to put in the exception.
*/
private void pathListError(String message, int lineNumber) {
logger.printlnToBoth("Error in " + pathListFilename + " (line " + lineNumber + "): "
+ message);
}
}