| Files.java |
1 /*
2 * Files.java
3 *
4 * Copyright (c) 1998-2004, The University of Sheffield.
5 *
6 * This file is part of GATE (see http://gate.ac.uk/), and is free
7 * software, licenced under the GNU Library General Public License,
8 * Version 2, June 1991 (in the distribution as file licence.html,
9 * and also available at http://gate.ac.uk/gate/licence.html).
10 *
11 * $Id: Files.java,v 1.33 2004/07/21 17:10:09 akshay Exp $
12 */
13
14 package gate.util;
15 import java.io.*;
16 import java.util.*;
17
18 import gnu.regexp.*;
19
20 /** Some utilities for use with Files and with resources.
21 * <P>
22 * <B>Note</B> that there is a terminology conflict between the use
23 * of "resources" here and <TT>gate.Resource</TT> and its inheritors.
24 * <P>
25 * Java "resources" are files that live on the CLASSPATH or in a Jar
26 * file that are <I>not</I> <TT>.class</TT> files. For example: a
27 * <TT>.gif</TT> file that is used by a GUI, or one of the XML files
28 * used for testing GATE's document format facilities. This class
29 * allows you to access these files in various ways (as streams, as
30 * byte arrays, etc.).
31 * <P>
32 * GATE resources are components (Java Beans) that provide all of the
33 * natural language processing capabilities of a GATE-based system, and
34 * the language data that such systems analsyse and produce. For
35 * example: parsers, lexicons, generators, corpora.
36 * <P>
37 * Where we say "resource" in this class we mean Java resource; elsewhere
38 * in the system we almost always mean GATE resource.
39 */
40 public class Files {
41
42 /** Debug flag */
43 private static final boolean DEBUG = false;
44
45 /** Used to generate temporary resources names*/
46 static long resourceIndex = 0;
47
48 /**Where on the classpath the gate resources are to be found*/
49 protected static String resourcePath = "/gate/resources";
50
51 /**Gets the path for the gate resources within the classpath*/
52 public static String getResourcePath(){
53 return resourcePath;
54 }
55
56 /** It returns the last component in a file path.
57 * It takes E.g: d:/tmp/file.txt and returns file.txt
58 */
59 public static String getLastPathComponent(String path){
60 if(path == null || path.length() == 0) return "";
61 //we should look both for "/" and "\" as on windows the file separator is"\"
62 //but a path coming from an URL will be separated by "/"
63 int index = path.lastIndexOf('/');
64 if(index == -1) index = path.lastIndexOf('\\');
65 if(index == -1) return path;
66 else return path.substring(index + 1);
67 }// getLastPathComponent()
68
69 /** Get a string representing the contents of a text file. */
70 public static String getString(String fileName) throws IOException {
71 return getString(new File(fileName));
72 } // getString(fileName)
73
74 /** Get a string representing the contents of a text file. */
75 public static String getString(File textFile) throws IOException {
76 FileInputStream fis = new FileInputStream(textFile);
77 int len = (int) textFile.length();
78 byte[] textBytes = new byte[len];
79 fis.read(textBytes, 0, len);
80 fis.close();
81 return new String(textBytes);
82 } // getString(File)
83
84 /** Get a byte array representing the contents of a binary file. */
85 public static byte[] getByteArray(File binaryFile) throws IOException {
86 FileInputStream fis = new FileInputStream(binaryFile);
87 int len = (int) binaryFile.length();
88 byte[] bytes = new byte[len];
89 fis.read(bytes, 0, len);
90 fis.close();
91 return bytes;
92 } // getByteArray(File)
93
94 /** Get a resource from the classpath as a String.
95 */
96 public static String getResourceAsString(String resourceName)
97 throws IOException {
98 InputStream resourceStream = getResourceAsStream(resourceName);
99 BufferedReader resourceReader =
100 new BufferedReader(new InputStreamReader(resourceStream));
101 StringBuffer resourceBuffer = new StringBuffer();
102
103 int i;
104
105 int charsRead = 0;
106 final int size = 1024;
107 char[] charArray = new char[size];
108
109 while( (charsRead = resourceReader.read(charArray,0,size)) != -1 )
110 resourceBuffer.append (charArray,0,charsRead);
111
112 while( (i = resourceReader.read()) != -1 )
113 resourceBuffer.append((char) i);
114
115 resourceReader.close();
116 return resourceBuffer.toString();
117 } // getResourceAsString(String)
118
119 /** Get a resource from the GATE resources directory as a String.
120 * The resource name should be relative to <code>resourcePath</code> which
121 * is equal with <TT>gate/resources</TT>; e.g.
122 * for a resource stored as <TT>gate/resources/jape/Test11.jape</TT>,
123 * this method should be passed the name <TT>jape/Test11.jape</TT>.
124 */
125 public static String getGateResourceAsString(String resourceName)
126 throws IOException {
127
128 InputStream resourceStream = getGateResourceAsStream(resourceName);
129 BufferedReader resourceReader =
130 new BufferedReader(new InputStreamReader(resourceStream));
131 StringBuffer resourceBuffer = new StringBuffer();
132
133 int i;
134
135 int charsRead = 0;
136 final int size = 1024;
137 char[] charArray = new char[size];
138
139 while( (charsRead = resourceReader.read(charArray,0,size)) != -1 )
140 resourceBuffer.append (charArray,0,charsRead);
141
142 while( (i = resourceReader.read()) != -1 )
143 resourceBuffer.append((char) i);
144
145 resourceReader.close();
146 return resourceBuffer.toString();
147 } // getGateResourceAsString(String)
148
149 /**
150 * Writes a temporary file into the default temporary directory,
151 * form an InputStream a unique ID is generated and associated automaticaly
152 * with the file name...
153 */
154 public static File writeTempFile(InputStream contentStream)
155 throws IOException {
156
157 File resourceFile = null;
158 FileOutputStream resourceFileOutputStream = null;
159
160 // create a temporary file name
161 resourceFile = File.createTempFile ("gateResource", ".tmp");
162 resourceFileOutputStream = new FileOutputStream(resourceFile);
163 resourceFile.deleteOnExit ();
164
165 if (contentStream == null)
166 return resourceFile;
167
168 int bytesRead = 0;
169 final int readSize = 1024;
170 byte[] bytes = new byte[readSize];
171 while( (bytesRead = contentStream.read(bytes,0,readSize) ) != -1 )
172 resourceFileOutputStream.write(bytes,0, bytesRead);
173
174 resourceFileOutputStream.close();
175 contentStream.close ();
176 return resourceFile;
177 }// writeTempFile()
178
179 /**
180 * Writes aString into a temporary file located inside
181 * the default temporary directory defined by JVM, using the specific
182 * anEncoding.
183 * An unique ID is generated and associated automaticaly with the file name.
184 * @param aString the String to be written. If is null then the file will be
185 * empty.
186 * @param anEncoding the encoding to be used. If is null then the default
187 * encoding will be used.
188 * @return the tmp file containing the string.
189 */
190 public static File writeTempFile(String aString, String anEncoding) throws
191 UnsupportedEncodingException, IOException{
192 File resourceFile = null;
193 OutputStreamWriter writer = null;
194
195 // Create a temporary file name
196 resourceFile = File.createTempFile ("gateResource", ".tmp");
197 resourceFile.deleteOnExit ();
198
199 if (aString == null) return resourceFile;
200 // Prepare the writer
201 if (anEncoding == null){
202 // Use default encoding
203 writer = new OutputStreamWriter(new FileOutputStream(resourceFile));
204
205 }else {
206 // Use the specified encoding
207 writer = new OutputStreamWriter(
208 new FileOutputStream(resourceFile),anEncoding);
209 }// End if
210
211 // This Action is added only when a gate.Document is created.
212 // So, is for sure that the resource is a gate.Document
213 writer.write(aString);
214 writer.flush();
215 writer.close();
216 return resourceFile;
217 }// writeTempFile()
218
219 /**
220 * Writes aString into a temporary file located inside
221 * the default temporary directory defined by JVM, using the default
222 * encoding.
223 * An unique ID is generated and associated automaticaly with the file name.
224 * @param aString the String to be written. If is null then the file will be
225 * empty.
226 * @return the tmp file containing the string.
227 */
228 public static File writeTempFile(String aString) throws IOException{
229 return writeTempFile(aString,null);
230 }// writeTempFile()
231
232
233 /** Get a resource from the classpath as a byte array.
234 */
235 public static byte[] getResourceAsByteArray(String resourceName)
236 throws IOException, IndexOutOfBoundsException, ArrayStoreException {
237
238 InputStream resourceInputStream = getResourceAsStream(resourceName);
239 BufferedInputStream resourceStream =
240 new BufferedInputStream(resourceInputStream);
241 byte b;
242 final int bufSize = 1024;
243 byte[] buf = new byte[bufSize];
244 int i = 0;
245
246 // get the whole resource into buf (expanding the array as needed)
247 while( (b = (byte) resourceStream.read()) != -1 ) {
248 if(i == buf.length) {
249 byte[] newBuf = new byte[buf.length * 2];
250 System.arraycopy (buf,0,newBuf,0,i);
251 buf = newBuf;
252 }
253 buf[i++] = b;
254 }
255
256 // close the resource stream
257 resourceStream.close();
258
259 // copy the contents of buf to an array of the correct size
260 byte[] bytes = new byte[i];
261 // copy from buf to bytes
262 System.arraycopy (buf,0,bytes,0,i);
263 return bytes;
264 } // getResourceAsByteArray(String)
265
266 /** Get a resource from the GATE resources directory as a byte array.
267 * The resource name should be relative to <code>resourcePath<code> which
268 * is equal with <TT>gate/resources</TT>; e.g.
269 * for a resource stored as <TT>gate/resources/jape/Test11.jape</TT>,
270 * this method should be passed the name <TT>jape/Test11.jape</TT>.
271 */
272 public static byte[] getGateResourceAsByteArray(String resourceName)
273 throws IOException, IndexOutOfBoundsException, ArrayStoreException {
274
275 InputStream resourceInputStream = getGateResourceAsStream(resourceName);
276 BufferedInputStream resourceStream =
277 new BufferedInputStream(resourceInputStream);
278 byte b;
279 final int bufSize = 1024;
280 byte[] buf = new byte[bufSize];
281 int i = 0;
282
283 // get the whole resource into buf (expanding the array as needed)
284 while( (b = (byte) resourceStream.read()) != -1 ) {
285 if(i == buf.length) {
286 byte[] newBuf = new byte[buf.length * 2];
287 System.arraycopy (buf,0,newBuf,0,i);
288 buf = newBuf;
289 }
290 buf[i++] = b;
291 }
292
293 // close the resource stream
294 resourceStream.close();
295
296 // copy the contents of buf to an array of the correct size
297 byte[] bytes = new byte[i];
298
299 // copy from buf to bytes
300 System.arraycopy (buf,0,bytes,0,i);
301 return bytes;
302 } // getResourceGateAsByteArray(String)
303
304
305 /** Get a resource from the classpath as an InputStream.
306 */
307 public static InputStream getResourceAsStream(String resourceName)
308 throws IOException {
309
310 return Files.class.getResourceAsStream(resourceName);
311 //return ClassLoader.getSystemResourceAsStream(resourceName);
312 } // getResourceAsStream(String)
313
314 /** Get a resource from the GATE resources directory as an InputStream.
315 * The resource name should be relative to <code>resourcePath<code> which
316 * is equal with <TT>gate/resources</TT>; e.g.
317 * for a resource stored as <TT>gate/resources/jape/Test11.jape</TT>,
318 * this method should be passed the name <TT>jape/Test11.jape</TT>.
319 */
320 public static InputStream getGateResourceAsStream(String resourceName)
321 throws IOException {
322
323 if(resourceName.startsWith("/") || resourceName.startsWith("\\") )
324 return getResourceAsStream(resourcePath + resourceName);
325 else return getResourceAsStream(resourcePath + "/" + resourceName);
326 } // getResourceAsStream(String)
327
328
329 /** This method takes a regular expression and a directory name and returns
330 * the set of Files that match the pattern under that directory.
331 */
332 public static Set Find(String regex, String pathFile) {
333 Set regexfinal = new HashSet();
334 String[] tab;
335 File file = null;
336 PrintStream printstr = null;
337 Object obj = new Object();
338 //open a file
339 try {
340 file = new File(pathFile);
341 } catch(NullPointerException npe) {
342 npe.printStackTrace(Err.getPrintWriter());
343 //System.exit(1);
344 }
345 //generate a regular expression
346 try {
347 RE regexp = new RE("^"+regex);
348 if (file.isDirectory()){
349 tab = file.list();
350 for (int i=0;i<=tab.length-1;i++){
351 String finalPath = pathFile+"/"+tab[i];
352 REMatch m1 = regexp.getMatch(finalPath);
353 if (regexp.getMatch(finalPath) != null){
354 regexfinal.add(finalPath);
355 }
356 }
357 }
358 else {
359 if (file.isFile()){
360 if (regexp.getMatch(pathFile) != null) {
361 regexfinal.add(file.getAbsolutePath());
362 }
363 }
364 }
365 } catch(REException ree) {
366 ree.printStackTrace(Err.getPrintWriter());
367 //System.exit(1);
368 }
369 return regexfinal;
370 } //find
371
372 /** Recursively remove a directory <B>even if it contains other files
373 * or directories</B>. Returns true when the directory and all its
374 * contents are successfully removed, else false.
375 */
376 public static boolean rmdir(File dir) {
377 if(dir == null || ! dir.isDirectory()) // only delete directories
378 return false;
379
380 // list all the members of the dir
381 String[] members = dir.list();
382
383 // return value indicating success or failure
384 boolean succeeded = true;
385
386 // for each member, if is dir then recursively delete; if file then delete
387 for(int i = 0; i<members.length; i++) {
388 File member = new File(dir, members[i]);
389
390 if(member.isFile()) {
391 if(! member.delete())
392 succeeded = false;
393 } else {
394 if(! Files.rmdir(member))
395 succeeded = false;
396 }
397 }
398
399 // delete the directory itself
400 dir.delete();
401
402 // return status value
403 return succeeded;
404 } // rmdir(File)
405
406 /**
407 * This method updates an XML element with a new set of attributes.
408 * If the element is not found the XML is unchanged. The attributes
409 * keys and values must all be Strings.
410 *
411 * @param xml A stream of the XML data.
412 * @param elementName The name of the element to update.
413 * @param newAttrs The new attributes to place on the element.
414 * @return A string of the whole XML source, with the element updated.
415 */
416 public static String updateXmlElement(
417 BufferedReader xml, String elementName, Map newAttrs
418 ) throws IOException {
419 String line = null;
420 String nl = Strings.getNl();
421 StringBuffer newXml = new StringBuffer();
422
423 // read the whole source
424 while( ( line = xml.readLine() ) != null ) {
425 newXml.append(line);
426 newXml.append(nl);
427 }
428
429 // find the location of the element
430 int start = newXml.toString().indexOf("<" + elementName);
431 if(start == -1) return newXml.toString();
432 int end = newXml.toString().indexOf(">", start);
433 if(end == -1) return newXml.toString();
434
435 // check if the old element is empty (ends in "/>") or not
436 boolean isEmpty = false;
437 if(newXml.toString().charAt(end - 1) == '/') isEmpty = true;
438
439 // create the new element string with the new attributes
440 StringBuffer newElement = new StringBuffer();
441 newElement.append("<");
442 newElement.append(elementName);
443
444 // add in the new attributes
445 Iterator iter = newAttrs.entrySet().iterator();
446 while(iter.hasNext()) {
447 Map.Entry entry = (Map.Entry) iter.next();
448 String key = (String) entry.getKey();
449 String value = (String) entry.getValue();
450
451 newElement.append(" ");newElement.append(key);
452 newElement.append("=\"");
453 newElement.append(value);
454 newElement.append("\"" + nl);
455 }
456
457 // terminate the element
458 if(isEmpty) newElement.append("/");
459 newElement.append(">");
460
461 // replace the old string
462 newXml.replace(start, end + 1, newElement.toString());
463
464 return newXml.toString();
465 } // updateXmlElement(Reader...)
466
467 /**
468 * This method updates an XML element in an XML file
469 * with a new set of attributes. If the element is not found the XML
470 * file is unchanged. The attributes keys and values must all be Strings.
471 *
472 * @param xmlFile An XML file.
473 * @param elementName The name of the element to update.
474 * @param newAttrs The new attributes to place on the element.
475 * @return A string of the whole XML file, with the element updated (the
476 * file is also overwritten).
477 */
478 public static String updateXmlElement(
479 File xmlFile, String elementName, Map newAttrs
480 ) throws IOException {
481 BufferedReader fileReader = new BufferedReader(new FileReader(xmlFile));
482 String newXml = updateXmlElement(fileReader, elementName, newAttrs);
483 fileReader.close();
484
485 FileWriter fileWriter = new FileWriter(xmlFile);
486 fileWriter.write(newXml);
487 fileWriter.close();
488
489 return newXml;
490 } // updateXmlElement(File...)
491
492 } // class Files
493