Java tutorial
/* * Copyright 2004 - 2009 University of Cardiff. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.trianacode.taskgraph.util; import org.apache.commons.logging.Log; import org.trianacode.enactment.logging.Loggers; import org.trianacode.taskgraph.tool.ClassLoaders; import javax.swing.*; import java.applet.Applet; import java.applet.AudioClip; import java.awt.*; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import java.util.Vector; import java.util.zip.ZipFile; /** * Class Description Here... * * @author Andrew Harrison * @version $Revision:$ */ public class FileUtils { static Log logger = Loggers.TOOL_LOGGER; public static final int ASCII = 0; public static final int BINARY = 0; /** * deletes files recursively. can optionally delete the parent file as well. So, if the parent file is not a * directory, and incParent is false, then nothing will be deleted. * * @param parent file to delete. If this is a directory then any children are deleted. * @param incParent boolean that determines if the parent file is also deleted. * @throws java.io.FileNotFoundException */ public static void deleteFiles(File parent, boolean incParent) throws FileNotFoundException { if (!parent.exists()) { throw new FileNotFoundException("File does not exist."); } if (parent.isDirectory() && !(parent.listFiles() == null)) { File[] files = parent.listFiles(); for (int i = 0; i < files.length; i++) { deleteFiles(files[i], true); } } if (incParent) { parent.delete(); } } public static String formatThrowable(Throwable t) { StringBuilder sb = new StringBuilder(t.getClass().getName()); t.fillInStackTrace(); StackTraceElement[] trace = t.getStackTrace(); for (StackTraceElement stackTraceElement : trace) { sb.append("\t\n").append(stackTraceElement); } Throwable cause = t.getCause(); if (cause != null) { sb.append(formatThrowable(cause)); } return sb.toString(); } public static boolean rename(File src, File dest) { if (src.getAbsolutePath().equals(dest.getAbsolutePath())) { return true; } boolean rename = src.renameTo(dest); if (!rename) { try { copyFilesRecursive(src, dest); } catch (IOException e) { logger.warn("Exception thrown while renaming:" + FileUtils.formatThrowable(e)); return false; } } return true; } /** * Copies files and directories recursively. The destination does not have to exist yet. * * @param src the source file to copy. Can be a file or a directory. * @param dest the destination to copy to. Can be a file or directory. * @return a List of the newly created Files * @throws java.io.FileNotFoundException if src does not exist * @throws java.io.IOException if src is a directory and dest exists and is not a directory, or an IO * error occurs. */ public static List<File> copyFilesRecursive(File src, File dest) throws IOException { ArrayList<File> list = new ArrayList<File>(); if (!src.exists()) { throw new FileNotFoundException("Input file does not exist."); } if (src.isDirectory()) { if (!dest.exists()) { dest.mkdirs(); } else if (!dest.isDirectory()) { throw new IOException("cannot write a directory to a file."); } list.add(dest); File[] srcFiles = src.listFiles(); for (int i = 0; i < srcFiles.length; i++) { list.addAll(copyFilesRecursive(srcFiles[i], new File(dest, srcFiles[i].getName()))); } } else { if (dest.exists() && dest.isDirectory()) { dest = new File(dest, src.getName()); } BufferedInputStream in = new BufferedInputStream(new FileInputStream(src)); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest)); byte[] bytes = new byte[8192]; int c; while ((c = in.read(bytes)) != -1) { out.write(bytes, 0, c); } out.flush(); out.close(); in.close(); list.add(dest); } return list; } /** * Deletes the file at the given file location. If the file is a directory then the directory must be empty for the * operation to be successful. */ public static void deleteFile(String loc) { File f1 = new File(loc); f1.delete(); } /** * Determines whether the given path or file is an internet address or not */ public static boolean isOnInternet(String fileOrPath) { if (fileOrPath.indexOf("://") != -1) { return true; } else { return false; } } /** * Determines whether the file specified is a directory. Files specified as string could be internet paths or local * paths. This function will determine which one it is. */ public static boolean isDirectory(String loc) { if (loc.indexOf("://") == -1) { return new File(loc).isDirectory(); } else { try { return isDirectory(new URL(correctURL(loc))); } catch (MalformedURLException url) { } } return false; } /** * Checks whether the <code>child</child> is contained by the <code>parent</code> directory. * * @param parent String representing the parent directory * @param child String representing the child file or directory * @return <b>False</b> if <code>parent</code> is not a directory, or <code>parent</code> equals <code>child</code>, * <b>True</b> if and only if <code>child</code> is contained in <code>parent</code>. */ public static boolean isParent(String parent, String child) { File parentFile = new File(parent); if (parentFile.isDirectory()) { File childFile = new File(child); if (!parentFile.equals(childFile)) { String s = childFile.getParent(); while (s != null) { childFile = new File(s); if (parentFile.equals(childFile)) { return true; } s = childFile.getParent(); } } } return false; } /** * Converts a URL address which may have machine dependant path separators contained within it to an appropraite URL * address e.g. can have http://www.comp.com/\file\on\d\ for example which should be http://www.comp.com/file/on/d/ */ public static String correctURL(String file) { if (file.indexOf("http://") == -1) { return file; } String fn = file.replace('\\', '/'); // System.out.println("Changed to " + fn); return fn; } /** * Determines whether the internet location and file specified is in fact a directory. This is determined by * checking whether * there exists a <pre> <title>Index Of ..... </title></pre> exists * on the first line of the html file which is the typical thing included on the first line if a directory is given * to a server */ public static boolean isDirectory(URL loc) { // if the file has a . in it i.e. tmp.java then dismiss it String s = correctURL(loc.toString()); if (s.indexOf(".", s.lastIndexOf("/")) != -1) { return false; } if (!s.endsWith("/")) { s = s + "/"; } try { Vector<String> str = FileUtils.readAndSplitFile(FileUtils.createReader(s)); if (str.size() == 0) { return false; } if (str.get(0).toLowerCase().indexOf("<title>index of") != -1) { return true; } // before returning false we need to check that the server // hasn't added a /index.html file to the end and passed this // file back instead which it will do. All we need to do // is test that the string s + index.html exists or not. // if it does exist then s is still a directory but it contains // the index.html file :- try { new URL(s + "index.html"); } catch (MalformedURLException murl) { return false; } return true; } catch (IOException except) { return false; } } /** * Lists the filenames and directories within a URL if that URL is a directory */ public static Vector<String> listInternetDirectory(URL loc) { Vector<String> str = FileUtils.readAndSplitFile(FileUtils.createReader(loc)); String cfile; Vector<String> files = new Vector<String>(); String st; for (int i = 0; i < str.size(); ++i) { st = str.get(i).toLowerCase(); if (st.indexOf("href=") != -1) { int pos = st.indexOf("href=") + 6; int pos2 = st.indexOf("\"", pos); int pos3 = st.indexOf("/", pos); if (pos3 > 0) // i.e. a / was found { pos2 = Math.min(pos2, pos3); } String fn; if (pos2 > 0) { fn = str.get(i).substring(pos, pos2); } else { fn = (str.get(i).substring(pos).trim()); } fn = fn.replace("\\", "/"); fn = fn.trim(); cfile = loc.toString(); if (!cfile.endsWith("/")) { cfile += "/"; } cfile += fn; System.out.println("File extracted = " + cfile); if ((!fn.startsWith("/")) && (fn.indexOf("%") == -1) && (fn.indexOf("?") == -1) && (fn.trim().length() > 0) && (!fn.equals("..")) && (!fn.equals("")) && (isDirectory(cfile))) { // miss out root directory and backup files // and empty ones and ../ directories files.addElement(fn); System.out.println("Added " + fn + " to listing.."); } else { System.out.println("Rejected " + fn); } } } return files; } /** * As copyFile except that it doesn't confirm on replacing a file. * * @see #copyFile */ public static boolean copyFile(String loc1, String loc2, int mode) { return copyFile(loc1, loc2, mode, false); } /** * Copies the file from the first location to the second. If the second location exists then the user is prompted * to ask if he/she wants to overwrite the exisiting file. They are given dates of the files also. The full Bill * Gates effect!!!!!! The mode can be either ASCII or BINARY. * * @return false if the file could not be copied, true if successful */ public static boolean copyFile(String loc1, String loc2, int mode, boolean confirmOnReplace) { BufferedReader br; DataInputStream ds; PrintWriter bw; DataOutputStream dout; long fmod1, fmod2; String text; byte[] bytes; File f1; File f2; if ((loc1 == null) || (loc2 == null)) { return false; } f1 = new File(loc1); f2 = new File(loc2); // if (!f1.exists()) { // return false; // } if (f2.isDirectory()) // add source file name if none chosen { loc2 = loc2 + File.separator + loc1.substring(loc1.lastIndexOf(File.separator) + 1); } f2 = new File(loc2); if (confirmOnReplace) { if ((f1.exists()) && (f2.exists())) { // does the time check with user fmod1 = f1.lastModified(); fmod2 = f2.lastModified(); /* TODO QuestionWindow con = new QuestionWindow(null, "Do you want to replace :\n" + loc2 + " modified : " + Str.niceDateAndTime(new Date(fmod2)) + "\nwith\n" + loc1 + " modified : " + Str.niceDateAndTime(new Date(fmod1)) + " ?\n"); if (con.reply != con.YES) return false;*/ } } try { if (mode == ASCII) { br = createReader(loc1); text = readFile(br); bw = FileUtils.createWriter(loc2); bw.print(text); closeWriter(bw); closeReader(br); } else { ds = new DataInputStream(new FileInputStream(f1)); bytes = new byte[(int) f1.length()]; ds.readFully(bytes); dout = createOutputStream(loc2); dout.write(bytes); dout.close(); ds.close(); } } catch (Exception ee) { logger.warn("\"Error Copying from \\n\" +\n" + " loc1 + \" to \\n\" + loc2" + ":" + formatThrowable(ee)); return false; } return true; } /** * creates a buffered writer for a specified local or networked text file. Just give the protocol and path if its a * networked file e.g. :- http:///www.astro.cf.ac.uk/pub/Ian.Taylor/Triana/Help/Wave.html or the absolute file name * if its a local file. </p><p> * * @param name the name of the file you wish to make a writer for. */ public static PrintWriter createWriter(String name) { PrintWriter prn = null; try { if (name.indexOf("://") != -1) { // a network path URL url = new URL(correctURL(name)); return createWriter(url); } else { new File(name).getParentFile().mkdirs(); FileWriter fwrite = new FileWriter((name)); prn = new PrintWriter(new BufferedWriter(fwrite)); } } catch (IOException io) { logger.warn("Couldn't open a writer " + name + ":" + formatThrowable(io)); } return prn; } /** * Creates a buffered writer to a specific URL. </p><p> * * @param url the name of the file you wish to make a writer for */ public static PrintWriter createWriter(URL url) { PrintWriter prn = null; try { prn = new PrintWriter( new BufferedWriter(new OutputStreamWriter(url.openConnection().getOutputStream()))); } catch (IOException io) { // new ErrorDialog(null,"Couldn't open a network writer " + url.getFile()); } return prn; } /** * creates a buffered writer for a specified local file, with an option to append. Just give the absolute file * name.</p><p> * * @param name the name of the file you wish to make a writer for. */ public static PrintWriter createWriter(String name, boolean append) { PrintWriter prn = null; try { new File(name).getParentFile().mkdirs(); FileWriter fwrite = new FileWriter(name, append); prn = new PrintWriter(new BufferedWriter(fwrite)); } catch (IOException io) { logger.warn("Couldn't open a writer " + name + ":" + formatThrowable(io)); } return prn; } /** * creates a buffered reader for a specified local or networked text file. Just give the protocol and path if its a * networked file e.g. :- http:///www.astro.cf.ac.uk/pub/Ian.Taylor/Triana/Help/Wave.html or the absolute file name * if its a local file. </p><p> * * @param name the name of the file you wish to make a reader for. */ public static BufferedReader createReader(String name) throws IOException { BufferedReader br = null; if (name.indexOf("://") != -1) { // a network path URL url = new URL(correctURL(name)); return createReader(url); } else { br = new BufferedReader(new FileReader(name)); } return br; } /** * creates a buffered reader for a URL * * @param url the name of the file you wish to make a reader for. */ public static BufferedReader createReader(URL url) { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(url.openStream())); } catch (IOException io) { // new ErrorDialog(null,"Couldn't open a network reader for " + url.getFile()); } return br; } /** * return true if the specified file (or Directory) exists either on a network or a local server. The function * automatically detects where the file is. * * @param name the name of the file. */ public static boolean fileExists(String name) { try { if (name.indexOf("://") != -1) { // a network path return true; /* URL ur = new URL(correctURL(name)); URLConnection url = ur.openConnection(); String typ = url.getContentType(); StringVector sv = FileUtils.readAndSplitFile( FileUtils.createReader(ur)); System.out.println(sv.at(0)); System.out.println(typ); if (typ.equals("text/plain")) return true; if (typ.equals("text/html")) if (GUIEnv.isAnApplet()) return true; else if (isDirectory(sv.at(0))) return true; return false;*/ } else { File f = new File(name); return f.exists(); } } catch (Exception io) { System.out.println("Exception for " + name); return false; } } /** * closes the given reader * * @param br the reader to close. */ public static void closeReader(BufferedReader br) { try { if (br != null) { br.close(); } } catch (IOException io) { System.out.println("Couldn't close Writer " + br); } } /** * closes the given writer * * @param pw the writer to close. */ public static void closeWriter(PrintWriter pw) { if (pw != null) { pw.close(); } } /** * Write the specified String to the file */ public static void writeToFile(String name, String contents) { PrintWriter pw = createWriter(name); pw.println(contents); closeWriter(pw); } /** * Write the specified String to the file with option to append */ public static void writeToFile(String name, String contents, boolean append) { PrintWriter pw = createWriter(name, append); pw.println(contents); closeWriter(pw); } /** * Write the specified StringVector to the file, writing each element on a separate line */ public static void writeToFile(String name, Vector<String> contents) { PrintWriter pw = createWriter(name); for (int i = 0; i < contents.size(); ++i) { pw.println(contents.get(i)); } closeWriter(pw); } /** * Creates a reader for a specified local or networked binary file. Just give the protocol and path if its a * networked file e.g. :- http:///www.astro.cf.ac.uk/pub/Ian.Taylor/Triana/Help/Wave.html or the absolute file name * if its a local file. </p><p> * * @param name the name of the file you wish to make a reader for. */ public static DataInputStream createInputStream(String name) throws IOException { DataInputStream ds = null; if (name.indexOf("://") != -1) { // a network path URL url = new URL(correctURL(name)); ds = new DataInputStream(new BufferedInputStream(url.openStream())); } else { ds = new DataInputStream(new BufferedInputStream(new FileInputStream(name))); } return ds; } /** * Creates an output stream for a specified local or networked binary file. Just give the protocol and path if its a * networked file e.g. :- http:///www.astro.cf.ac.uk/Triana/data.bin or the absolute file name if its a local file. * </p><p> * * @param name the name of the file you wish to make an output stream for. */ public static DataOutputStream createOutputStream(String name) { DataOutputStream ds = null; try { if (name.indexOf("://") != -1) { // a network path URL url = new URL(correctURL(name)); ds = new DataOutputStream(new BufferedOutputStream(url.openConnection().getOutputStream())); } else { ds = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(name))); } } catch (IOException io) { logger.warn("Couldn't open an Output Stream for " + name + ":" + formatThrowable(io)); } return ds; } /** * Closes the given output stream. */ public static void closeOutputStream(DataOutputStream dos) { try { if (dos != null) { dos.close(); } } catch (IOException io) { System.out.println("Couldn't close Output Stream " + dos); } } /** * Closes the given input stream. */ public static void closeInputStream(DataInputStream di) { try { if (di != null) { di.close(); } } catch (IOException io) { System.out.println("Couldn't close Input Stream " + di); } } /** * Loads in a sound file from the specified internet location. */ public static AudioClip getAudioClip(URL audioLoc) { System.out.println("Loading .... " + audioLoc); try { return Applet.newAudioClip(audioLoc); } catch (Exception e) { System.out.println("Couldn't load sound file " + audioLoc); } return null; } /** * Loads in a sound file from the internet or local disk. It auto-detects what protocol it should use. */ public static AudioClip getAudioClip(String audioFile) { AudioClip audio = null; try { if (FileUtils.isOnInternet(audioFile)) { audio = getAudioClip(new URL(audioFile)); } else { URL url = FileUtils.class.getResource(audioFile); if (url != null) { audio = getAudioClip(url); } } } catch (Exception e) { audio = null; e.printStackTrace(); } return audio; } /** * Loads in a Triana system sound file via the internet (if it is an applet) or local disk. It auto-detects what * protocol it should use. It looks in the triana/system/sounds directory for the sound file called "audioFile" */ public static AudioClip getSystemAudioClip(String audioFile) { return getAudioClip("system" + "/" + "sounds" + "/" + audioFile); } /** * Plays a Triana system sound file by loading it across the internet (if Triana is an applet)or local disk. It * auto-detects what protocol it should use. It looks in the %TRIANA%/system/sounds directory for the sound file * called "audioFile" */ public static void playSystemAudio(String audioFile) { final AudioClip audio = getSystemAudioClip(audioFile); audio.play(); /* Thread t = new Thread( new Runnable() { // set off in a different thread public void run() { audio.play(); } }); t.start(); */ } /** * Loads in an image from the internet or local disk. It auto-detects what protocol it should use. * <p/> * This is legacy and only used by some Units - core Triana classes should use {@link #getSystemImage} */ public static Image getImage(String imageName) { Image image; try { if (FileUtils.isOnInternet(imageName)) { image = Toolkit.getDefaultToolkit().getImage(new URL(imageName)); } else { System.out.println("FileUtils.getImage getting image for path:" + imageName); image = Toolkit.getDefaultToolkit().getImage(imageName); } } catch (Exception e) { System.out.println("Couldn't load image " + imageName); image = null; } return image; } /** * Loads in a triana system image icon from the internet or local disk. It auto-detects what protocol it should use * and looks in the triana/system/icons directory for the image called "imageName" */ public static ImageIcon getSystemImageIcon(String imageName) { Image image = getSystemImage(imageName); if (image == null) { return null; } else { return new ImageIcon(image); } } /** * Loads in a triana system image from the internet or local disk. It auto-detects what protocol it should use and * looks in the triana/system/icons directory for the image called "imageName" */ public static Image getSystemImage(String imageName) { imageName = imageName.replace(File.separatorChar, '/'); String dir = "system/icons/"; if (imageName.startsWith("/")) { dir = "system/icons"; } String imageURL = dir + imageName; logger.trace("loading icon: " + imageURL); URL imageResource = ClassLoaders.getResource(imageURL); if (imageResource == null) { logger.warn("error loading icon: " + imageURL); return null; } else { return Toolkit.getDefaultToolkit().getImage(imageResource); } } /** * @return the file name without suffix or path details. */ public static String getFileNameNoSuffix(String fullName) { String name = (new File(fullName)).getName(); if (name.lastIndexOf('.') > -1) { return name.substring(0, name.lastIndexOf('.')); } else { return name; } } /** * This function splits up the CLASSPATH and the TOOLBOXES environment variables into the various specified paths. A * Vector is returned containing the paths found. We also take into account that paths can be internet address also * by including an internet address in the following form in your environment variables :- </p> * <p/> * <center> protocol://server/directory<br> for example<br> http://www.astro.cf.ac.uk/pub/Ian.Taylor/Triana/Release/classes<br> * </center> */ public static Vector splitPath(String path) { if (path == null) { return null; } Vector paths = new Vector(10); // 10's quite a lot, should be OK String separator = System.getProperty("path.separator"); String newpath; URL urlPath; // get rid of colons as they are confusing as they act // as path separators as well. Put the http and ftp etc in just // in case some accidentally put // in as a local directory after // a deliminator e.g. path://usr/local/path path.replace("http://", "http+//"); path.replace("ftp://", "ftp+//"); path.replace("file://", "file+//"); StringTokenizer st = new StringTokenizer(correctURL(path), separator); while (st.hasMoreTokens()) { newpath = st.nextToken(); int aNetwork = newpath.indexOf("+"); if (aNetwork != -1) { // an internet directory if ((!newpath.endsWith("/")) && (!newpath.endsWith(".tbx")) && (!newpath.endsWith(".html"))) { newpath = newpath + "/"; } path.replace("+", ":"); // swap +'s with :'s try { urlPath = new URL(newpath); paths.addElement(urlPath); } catch (MalformedURLException me) { System.err.println("Network Path " + newpath + " NOT FOUND!"); } } else { // local directory or zipfile ZipFile z = null; if (newpath.indexOf(".zip") != -1) { // a zip file try { if (newpath != null) { z = new ZipFile(newpath); } if (z != null) { if (!paths.contains(z)) { paths.addElement(z); } } } catch (IOException io) { // System.out.println(newpath + " not a zipfile!"); } } else { if ((!newpath.endsWith(File.separator)) && (!newpath.endsWith(".tbx")) && (!newpath.endsWith(".html"))) { newpath = newpath + File.separator; } paths.addElement(newpath); } } } return paths; } /** * This function splits the next line createTool from the specified BufferReader into a vector of Strings contained * within the line. Each string is split up if they are separated by a single white space. The function returns a * StringVector which is basically, a Vector which only stores strings, so we don't have type-cast all the time. */ public static Vector<String> readAndSplitLine(BufferedReader br) { if (br == null) { return null; } String line; try { line = br.readLine(); } catch (IOException ee) { System.out.println("Couldn't input from " + br.toString()); return null; } if (line == null) { return null; } return splitLine(line); } /** * Skips the empty lines in a file and returns the next non-empty line or null if the end of the file is reached. * The line returned is a vector of string with one string representing each word or whatever in the file, like * readAndSplitLine * * @see #readAndSplitLine */ public static Vector<String> nextNonEmptySplitLine(BufferedReader br) { Vector<String> line; do { line = FileUtils.readAndSplitLine(br); if (line == null) { return null; } } while ((line.size() < 1) || ((line.size() == 1) && (line.get(0).equals("")))); return line; } /** * Skips the empty lines in a file and returns the next non-empty line or null if the end of the file is reached. * * @see #readAndSplitLine */ public static String nextNonEmptyLine(BufferedReader br) throws IOException { String line; do { line = br.readLine(); if (line == null) { return null; } line = line.trim(); } while (line.length() < 1); return line; } /** * This function splits the line into a vector of Strings separated by spaces. Each string is split up if they are * separated by a single white space. The function returns a StringVector which is basically, a Vector which only * stores strings, so we don't have type-cast all the time. */ public static Vector<String> splitLine(String line) { Vector<String> items = new Vector<String>(10); // 10 should be OK StringTokenizer st = new StringTokenizer(line); while (st.hasMoreTokens()) { items.addElement(st.nextToken()); } return items; } /** * Reads all the file pointed to by the given reader into the returned string. This function also closes the file * (since we have createTool it all!). </p> <p> For example, to open, createTool all, and close a file you type :- * </p> * <pre> * String template = FileUtils.readFile(FileUtils.createReader(fileName)); * </pre> */ public static String readFile(BufferedReader br) { String line; String str = ""; if (br == null) { return str; } try { while ((line = br.readLine()) != null) { str = str + line + "\n"; } } catch (IOException ee) { System.out.println("Couldn't input from " + br.toString()); return null; } closeReader(br); return str; } /** * Reads the file specified by the given Filename and puts it into a string. This uses DataInputStream to createTool * the file fully and then create a string which is a lot faster than reading a line at a time. Use this function * for speed. */ public static String readFile(String filename) { String st = null; try { if (filename.indexOf("://") != -1) { // a network path BufferedReader br = createReader(correctURL(filename)); String contents = readFile(br); closeReader(br); return contents; } File fi = new File(filename); long llen = fi.length(); int len = (int) (llen & 0x7FFFFFFF); if (len != llen) { System.out.println("File too big to createTool into a single object"); return null; } byte[] b = new byte[len]; DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(fi))); dis.readFully(b); st = new String(b); dis.close(); } catch (FileNotFoundException ee) { logger.warn("Couldn't find file " + filename + ":" + formatThrowable(ee)); return null; } catch (IOException eee) { logger.warn("IO exception on file " + filename + ":" + formatThrowable(eee)); return null; } return st; } /** * This function splits the file into a vector of Strings, each item in the vector representing one line. Used for * loading in the TrianaType file and useful for splitting up file into a vector of easily accessable lines. This * function also closes the file (since we have createTool it all!) */ public static Vector<String> readAndSplitFile(BufferedReader br) { Vector<String> lines = new Vector<String>(10); // 10 should be OK if (br == null) { return null; } String line; try { while ((line = br.readLine()) != null) { lines.addElement(line); } } catch (IOException ee) { System.out.println("Couldn't input from " + br.toString()); return null; } closeReader(br); return lines; } /** * This function splits the file into a vector of Strings, each item in the vector representing one line. Used for * loading in the TrianaType file and useful for splitting up file into a vector of easily accessable lines. This * function also closes the file (since we have createTool it all!) */ public static Vector<String> readAndSplitFile(String fileName) { try { return readAndSplitFile(createReader(fileName)); } catch (IOException except) { return new Vector<String>(); } } /** * Convert the given fileName into a machine independant form by making use of the environment variables to set up * relative paths etc. for example, instead of using /getApplicationDataDir/specta/ian/grodcl/dir/file.name we would use * $TRIANA/dir/file.name so that we could convert the file to the relevant directory on any machine. */ public static String convertToVirtualName(String fileName) { // start with the largest path and then all sub paths // to try an extract as much information as possible. String newFile = new String(correctURL(fileName)); if (fileName.trim().equals("")) { return fileName; } /* System.out.println("File = " + newFile); if (Env.getApplicationDataDir().length() <= newFile.length()) System.out.println("File = " + newFile.substring(0, Env.getApplicationDataDir().length())); System.out.println("File = " + Env.getApplicationDataDir()); */ String userHome = System.getProperty("user.getApplicationDataDir"); if (userHome.length() <= newFile.length()) { if (newFile.substring(0, userHome.length()).equalsIgnoreCase(userHome)) { newFile = "$USER_HOME" + newFile.substring(userHome.length()); } } return newFile; } /** * Convert machine independant form to actual fileName */ public static String convertFromVirtualName(String fileName) { // start with the largest path and then all sub paths // to try an extract as much information as possible. String newFile = new String(fileName); if (fileName.trim().equals("")) { return fileName; } if (newFile.indexOf("$USER_HOME") != -1) { newFile = System.getProperty("user.getApplicationDataDir") + newFile.substring("$USER_HOME".length()); } if (newFile.indexOf("://") == -1) { if (newFile.indexOf("/") != -1) { // created on Unix if (!File.separator.equals("/")) { newFile = newFile.replace('/', File.separator.charAt(0)); } } else { // created on a DOS machine if (File.separator.equals("/")) { newFile = newFile.replace('\\', '/'); } } } else { if ((newFile.indexOf('\\')) != -1) { newFile = newFile.replace('\\', '+'); newFile = newFile.replace("+", ""); } } return newFile; } /** * Gets a Listing Object for the given directory, the given searchstring (i.e. a wildcard based matcher) and a flag * indicating whether the FileList should recurse into other directories or not. </p> <p> The searchFilter can be * any unix style (or DOS style) search expression when using <i>ls</i> or <i>dir</i>. This can also be a file, * directory or null. If its a file then this class can be used to determine whether the file exists or not (i.e. * if fileFound() == 0 or exists() == false then the file does not exist. If searchFilter is a directory then the * directory is listed (if it exists) and if it is set to null then the search is based on the first argument (i.e. * the searchdir). This is useful for just lsiting the contents of the directory.</p <p> The searchdir can contain * "./" or "../" (unix) or ".\" "..\" in dos. */ public static Listing listFileNames(String searchdir, String searchFilter, boolean recurseDirs) { String absDir = absolutePath(searchdir); Listing allNames; allNames = listDir(absDir, recurseDirs); // contains high structure return (allNames == null) ? null : allNames.justFileList(searchFilter).pickOutMatching(searchFilter); } /** * Gets a Listing Object for the given directory, the given searchstring (i.e. a wildcard based matcher) and a flag * indicating whether the FileList should recurse into other directories or not. </p> <p> The searchFilter can be * any unix style (or DOS style) search expression when using <i>ls</i> or <i>dir</i>. This can also be a file, * directory or null. If its a file then this class can be used to determine whether the file exists or not (i.e. * if fileFound() == 0 or exists() == false then the file does not exist. If searchFilter is a directory then the * directory is listed (if it exists) and if it is set to null then the search is based on the first argument (i.e. * the searchdir). This is useful for just lsiting the contents of the directory.</p <p> The searchdir can contain * "./" or "../" (unix) or ".\" "..\" in dos. */ public static Listing listDirNames(String searchdir, String searchFilter, boolean recurseDirs) { if (searchdir.indexOf("://") != -1) { if (!searchdir.endsWith("/")) { searchdir = searchdir + "/"; } } else { if (!searchdir.endsWith(File.separator)) { searchdir = searchdir + File.separator; } } String absDir = absolutePath(searchdir); Listing allNames; allNames = listDir(absDir, recurseDirs); // contains high structure return (allNames == null) ? null : allNames.justDirStructure(searchFilter).pickOutMatching(searchFilter); } /** * Gets a Listing Object for the given directory, the given searchstring (i.e. a wildcard based matcher) and a flag * indicating whether the FileList should recurse into other directories or not. </p> <p> The searchFilter can be * any unix style (or DOS style) search expression when using <i>ls</i> or <i>dir</i>. This can also be a file, * directory or null. If its a file then this class can be used to determine whether the file exists or not (i.e. * if fileFound() == 0 or exists() == false then the file does not exist. If searchFilter is a directory then the * directory is listed (if it exists) and if it is set to null then the search is based on the first argument (i.e. * the searchdir). This is useful for just lsiting the contents of the directory.</p <p> The searchdir can contain * "./" or "../" (unix) or ".\" "..\" in dos. */ public static Listing listAllFiles(String searchdir, String searchFilter, boolean recurseDirs) { String absDir = absolutePath(searchdir); logger.debug("Listing directory: " + absDir); Listing allNames = listDir(absDir, recurseDirs); // contains high structure return (allNames == null) ? null : allNames.pickOutMatching(searchFilter); } /** * @return the absolute path of the given directory i.e. the path may contain many ../'s or ./'s in its path. This * works out the correct path */ public static String absolutePath(String path) { if (path.indexOf("://") != -1) { return path; } File f = new File(path); String s = null; try { s = f.getCanonicalPath(); } catch (IOException ee) { logger.error("Couldn't get absolue Path for " + path, ee); } return s; } /** * Finds all file names in the specified directory and in all directories lower down in the tree. This list includes * directories also and is highly structured. It contains a Vector of File Object (representing file and directory) * names and Vectors containing listings of other directories. These other such directories also have the same * format. */ public static Listing listDir(String dir, boolean recurse) { if (dir == null) { return null; } try { if (dir.indexOf("://") != -1) { return listDir(new URL(dir), recurse); } } catch (MalformedURLException murl) { logger.warn("Internet Address " + dir + " does not exist!"); return null; } Listing filelist = new Listing(10); File file; String[] dirlist = listDir(dir); if (dirlist == null) { return null; } for (int i = 0; i < dirlist.length; ++i) { file = new File(dir + File.separator + dirlist[i]); filelist.addElement(file); // add it whether its a // directory or a normal file if ((file.isDirectory()) && (recurse)) { Listing f = listDir(file.getPath(), recurse); if (f != null) // don't add it if its empty { filelist.addElement(f); } } } if (filelist.size() > 0) { return filelist; } else { return null; } } /** * returns a list of file names in the given directory or returns null if the directory is empty or if it does not * exist. */ public static String[] listDir(String dir) { if (dir == null) { return null; } try { if (dir.indexOf("://") != -1) { Vector<String> sv = listInternetDirectory(new URL(dir)); String[] s = new String[sv.size()]; for (int i = 0; i < sv.size(); ++i) { s[i] = sv.get(i); } return s; } } catch (MalformedURLException murl) { logger.warn("Internet Address " + dir + " does not exist!"); return null; } File file = new File(dir); if ((!file.exists()) || (!file.isDirectory())) { return null; } String[] files = file.list(); if ((files == null) || (files.length == 0)) { return null; } else { return files; } } /** * Finds all file names in the specified directory and in all directories lower down in the tree. This list includes * directories also and is highly structured. It contains a Vector of File Object (representing file and directory) * names and Vectors containing listings of other directories. These other such directories also have the same * format. */ public static Listing listDir(URL dir, boolean recurse) { try { dir.openConnection(); } catch (Exception ee) { logger.warn("Internet Address " + dir + " does not exist!"); return null; } if (!dir.toString().endsWith("/")) { try { dir = new URL(dir.toString() + "/"); } catch (MalformedURLException murl) { // not possible, same directory! } } Listing filelist = new Listing(10); String file; URL furl; String sdir = dir.toString(); Vector<String> dirlist = listInternetDirectory(dir); if (dirlist == null) { return null; } for (int i = 0; i < dirlist.size(); ++i) { if (!sdir.endsWith("/")) { file = dir + "/" + dirlist.get(i); } else { file = dir + dirlist.get(i); } filelist.addElement(file); // add it whether its a // directory or a normal file try { furl = new URL(file); } catch (MalformedURLException murl) { // not possible but :- logger.error(file + "is not valid", murl); return null; } if (FileUtils.isDirectory(furl) && (recurse)) { Listing f = listDir(furl, recurse); if (f != null) // don't add it if its empty { filelist.addElement(f); } } } if (filelist.size() > 0) { return filelist; } else { return null; } } public static File[] listEndsWith(String baseDir, String endsWith) { return listEndsWith(baseDir, endsWith, new String[0]); } public static File[] listEndsWith(String baseDir, String endsWith, String[] excludedir) { ArrayList list = new ArrayList(); list(baseDir, excludedir, endsWith, list); return (File[]) list.toArray(new File[list.size()]); } public static File[] listEndsWith(String baseDir, String[] endsWith, String[] excludedir) { ArrayList list = new ArrayList(); list(baseDir, excludedir, endsWith, list); return (File[]) list.toArray(new File[list.size()]); } private static void list(String baseDir, String[] excludedir, String endsWith, ArrayList list) { File base = new File(baseDir); ExcludeFilter exfilter = new ExcludeFilter(excludedir); if (base.exists()) { File[] baseList = base.listFiles(exfilter); if (baseList != null) { list(baseList, exfilter, new EndsWithFilter(endsWith), list); } } } private static void list(String baseDir, String[] excludedir, String[] endsWith, ArrayList list) { File base = new File(baseDir); ExcludeFilter exfilter = new ExcludeFilter(excludedir); if (base.exists()) { File[] baseList = base.listFiles(exfilter); if (baseList != null) { list(baseList, exfilter, new EndsWithFilters(endsWith), list); } } } private static void list(File[] files, ExcludeFilter exfilter, Filter filter, ArrayList list) { File[] dirfiles; for (int count = 0; count < files.length; count++) { if (filter.matches(files[count])) { list.add(files[count]); } dirfiles = files[count].listFiles(exfilter); if (dirfiles != null) { list(dirfiles, exfilter, filter, list); } } } private static class ExcludeFilter implements FileFilter { private String[] exclude; public ExcludeFilter(String[] excludedir) { this.exclude = excludedir; } public boolean accept(File pathname) { boolean accept = true; for (int count = 0; (count < exclude.length) && (accept); count++) { accept = (!pathname.getName().equalsIgnoreCase(exclude[count])) && accept; } return accept; } } private static interface Filter { /** * @return true if the specified file matches the filter */ public boolean matches(File file); } private static class EndsWithFilter implements Filter { private String endsWith; public EndsWithFilter(String endsWith) { this.endsWith = endsWith; } /** * @return true if the specified file matches the filter */ public boolean matches(File file) { return file.getAbsolutePath().endsWith(endsWith); } } private static class EndsWithFilters implements Filter { private String[] endsWith; public EndsWithFilters(String[] endsWith) { this.endsWith = endsWith; } /** * @return true if the specified file matches the filter */ public boolean matches(File file) { if (file.isDirectory()) { return true; } for (String s : endsWith) { if (file.getAbsolutePath().endsWith(s)) { return true; } } return false; } } }