1
2
3 package DTDDoc;
4
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileNotFoundException;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.OutputStream;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.Comparator;
17 import java.util.Enumeration;
18 import java.util.LinkedList;
19 import java.util.List;
20 import java.util.StringTokenizer;
21
22
23 /** A class that gather some useful tools.
24 *
25 * @author expertmb (http://www.experts-exchange.com/M_237837.html)
26 * @author stefan schampailler_at_skynet_dot_be */
27
28
29 public class Tools {
30
31 /** Copy the whole content of a stream into another.
32 *
33 * @param source Input stream.
34 * @param destination Output stream.
35 * @throws IOException If anything goes wrong.
36 */
37
38 private static void streamCopy( InputStream source, OutputStream destination)
39 throws IOException {
40
41 if( source == null)
42 throw new IOException( "Trying to input from a null stream");
43 else if( destination == null)
44 throw new IOException( "Trying to output to a null stream");
45
46 byte[] buffer = new byte[16384];
47
48 while (true) {
49 int bytes_read = source.read(buffer);
50 if (bytes_read > 0)
51 destination.write(buffer, 0, bytes_read);
52 else
53 break;
54 }
55 }
56
57 /** Copy the content of stream into another and close both of them when
58 * done.
59 *
60 * @param source Source stream.
61 * @param destination Destination stream.
62 * @throws IOException If anything goes wrong.
63 */
64
65 private static void streamCopyAndClose( InputStream source,
66 OutputStream destination) throws IOException {
67
68 IOException exception = null;
69
70 try {
71 streamCopy( source, destination);
72 } catch( IOException ex) {
73 exception = ex;
74 }
75
76 if (source != null)
77 try {
78 source.close();
79 } catch (IOException e) {
80 if( exception != null)
81 exception = new IOException( exception.getMessage()+" (and I was not able to close this stream)");
82 }
83
84 if (destination != null)
85 try {
86 destination.close();
87 } catch (IOException e) {
88 if( exception != null)
89 exception = new IOException( exception.getMessage()+" (and I was not able to close this stream)");
90 }
91
92 if( exception != null)
93 throw exception;
94 }
95
96 /** Open a file so that it's ready to be written in. This takes as
97 * much care as possible to ensure the operation is possible.
98 *
99 * @param destinationFile File to open.
100 * @return A stream to write (overwrite) into the file.
101 * @throws FileCopyException
102 */
103 private static OutputStream openToWrite( File destinationFile) throws FileCopyException {
104
105
106
107
108 if (destinationFile.exists()) {
109 if (destinationFile.isFile()) {
110 if (!destinationFile.canWrite())
111 throw new FileCopyException("Can't write into "
112 + destinationFile);
113
114
115
116
117
118
119
120
121
122 } else
123 throw new FileCopyException(destinationFile + " is not a file.");
124 } else {
125 File parentdir = parent(destinationFile);
126 if (!parentdir.exists())
127 throw new FileCopyException( "Destination directory " +
128 "doesn't exist for " + destinationFile);
129 if (!parentdir.canWrite())
130 throw new FileCopyException( "Destination directory " +
131 "for " + destinationFile + " is unwritable.");
132 }
133
134
135
136
137 try {
138 return new FileOutputStream(destinationFile);
139 } catch( FileNotFoundException ex) {
140 throw new FileCopyException("Can't write to "+destinationFile+
141 " because "+ex.getLocalizedMessage());
142 }
143 }
144
145 /** Copies a resource file (in-jar) to a given destination.
146 *
147 * @param name Full path to the resource (relative to the jar though).
148 * @param destinationFile Where to copy the file.
149 * @throws FileCopyException
150 */
151
152 public static void copyFromResource( String name, File destinationFile)
153 throws FileCopyException {
154
155
156
157 InputStream source = Tools.class.getResourceAsStream( name);
158
159 if( source == null) {
160 String error = "Unable to find "+name+".";
161 if( !name.startsWith("/"))
162 error += " Please note that name doesn't start with a slash '/'.";
163
164 throw new FileCopyException( error);
165 }
166
167 OutputStream destination = openToWrite( destinationFile);
168
169 try {
170 streamCopyAndClose( source, destination);
171 } catch( IOException ex) {
172 throw new FileCopyException("Unable to copy "+name+" into "+destinationFile);
173 }
174 }
175
176 /** Copy one file into antoher. If the destination file already exists, it
177 * is overwritten.
178 *
179 * @param sourceFile Source path.
180 * @param destinationFile Destination path.
181 * @throws IOException
182 */
183
184 public static void copy( File sourceFile, File destinationFile)
185 throws IOException {
186
187
188
189 if (!sourceFile.exists() || !sourceFile.isFile())
190 throw new FileCopyException(
191 "Can't find "+sourceFile);
192
193 if (!sourceFile.canRead())
194 throw new FileCopyException("File " + sourceFile +
195 " is unreadable");
196
197 InputStream source = new FileInputStream( sourceFile);
198 OutputStream destination = openToWrite( destinationFile);
199
200 try {
201 streamCopyAndClose( source, destination);
202 } catch( IOException ex) {
203 throw new FileCopyException("Unable to copy "+sourceFile+" into "+destinationFile);
204 }
205 }
206
207
208 /** Get the parent of a given path.
209 *
210 * @param f The path.
211 * @return The path's parent. Null if there's no such parent.
212 */
213
214 public static File parent(File f) {
215 String dirname = f.getParent();
216 if (dirname == null) {
217 if (f.isAbsolute())
218 return new File(File.separator);
219 else
220 return new File(System.getProperty("user.dir"));
221 }
222 return new File(dirname);
223 }
224
225 /** Returns a sorted copy of a given collection.
226 *
227 * @param collection Colelction to sort.
228 * @param comparator Comparator to use while sorting.
229 * @return A sorted copy of the collection.
230 */
231
232 static public Collection sort( Collection collection, Comparator comparator) {
233 List l = new ArrayList( collection);
234 Collections.sort( l, comparator);
235 return l;
236 }
237
238 /** Transform a list into an array. The list is a string of texts
239 * separated by a character called "separator".
240 * @param s The list
241 * @param separator the separator.
242 * @return An array containing all the elements of the list. Null
243 * if the list is empty. */
244
245 public static String[] listToArray( String s, String separator) {
246 if( s == null) return null;
247
248 List l = new ArrayList();
249 StringTokenizer st = new StringTokenizer( s, separator, false);
250
251 while( st.hasMoreTokens()) {
252 l.add( st.nextToken());
253 }
254
255 if( l.size() <= 0) return null;
256
257 return (String[])l.toArray(new String[l.size()]);
258
259 }
260
261
262 public static String join( String[] array, String separator) {
263 int len = array.length;
264 StringBuffer buff = new StringBuffer();
265 for (int i = 0; i < len; i++) {
266 if (i > 0) {
267 buff.append(separator);
268 }
269 buff.append(array[i]);
270 }
271 return buff.toString();
272 }
273
274 /** Escape all non-ASCII character in a UNICODE string.
275 * The "escaping convention" is the one of HTML : &#xxxx;.
276 *
277 * <p>Additionally, this function can escape the single quote character for
278 * Javascript strings.</p>
279 *
280 *
281 * @param s String to escape. If null, nothing is done.
282 * @param javascript If true, escapes the single quote character into
283 * \' so that it can appear in a single quote delimited Javascript
284 * string.
285 * @return The escaped version of the string. If the parameter is null,
286 * returns null.
287 */
288
289 public static String escapeHTMLUnicode( String s, boolean javascript) {
290
291
292
293
294
295
296 if( s != null) {
297
298 StringBuffer out = new StringBuffer(s.length()*2);
299
300 for (int j = 0; j < s.length(); j++) {
301 char c = s.charAt(j);
302
303 if (javascript && c == '\'')
304 out.append( "\\'");
305 else if( (int) c < 128)
306
307 out.append( c);
308 else
309
310 out.append("&#").append((int) c).append(';');
311 }
312
313 return out.toString();
314
315 } else
316 return null;
317 }
318
319 public static List enumerationToList( Enumeration enumeration) {
320
321 if( enumeration == null)
322 return null;
323
324 List c = new LinkedList();
325
326 while( enumeration.hasMoreElements())
327 c.add( enumeration.nextElement());
328
329 return c;
330 }
331
332 /** Extract the file name out of a full path. For example,
333 * for "/alpha/bravo/zulu", this function will return "zulu".
334 *
335 * @param path The full path.
336 * @return The file name part of the path. */
337
338 public static String getFilename(String path) {
339
340
341 int li = path.lastIndexOf(File.separator) + 1;
342
343 return path.substring(li);
344 }
345
346 /** Will create the directories present in the path of a file.
347 * @param f The file to get the path from. */
348
349 public static void makeFileDir(File f) throws IOException {
350
351 String c = f.getCanonicalPath();
352 File dir = new File(c.substring(0, c.lastIndexOf(File.separator)));
353 dir.mkdirs();
354 }
355
356
357
358
359
360
361
362
363
364
365
366 public final static List HTML_TAGS;
367 static {
368 List html = Arrays.asList(new String[] {
369 "script", "noscript", "iframe", "div", "p",
370 "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol",
371 "menu", "dir", "li", "dl", "dt", "dd", "address", "hr",
372 "pre", "blockquote", "center", "ins", "del", "a", "span",
373 "bdo", "br", "em", "strong", "dfn", "code", "samp", "kbd", "var", "cite",
374 "abbr", "acronym", "q", "sub", "sup", "tt", "i", "b", "big", "small",
375 "u", "s", "strike", "basefont", "font", "object", "param", "applet",
376 "img", "map", "area", "form", "label", "input", "select", "optgroup",
377 "option", "textarea", "fieldset", "legend", "button", "isindex",
378 "table", "caption", "thead", "tfoot", "tbody", "colgroup", "col",
379 "tr", "th", "td"
380 });
381 Collections.sort(html);
382 HTML_TAGS = Collections.unmodifiableList(html);
383 }
384
385 public static boolean startsWithHtmlTag(String txt) {
386
387 if (txt.startsWith("</")) {
388 txt = txt.substring(2);
389 } else if (txt.startsWith("<")) {
390 txt = txt.substring(1);
391 } else {
392 return false;
393 }
394
395
396 int idx = txt.indexOf(' ');
397 if (idx > 0) {
398 txt = txt.substring(0, idx);
399 }
400 idx = txt.indexOf('>');
401 if (idx > 0) {
402 txt = txt.substring(0, idx);
403 }
404
405 String tag = txt.toLowerCase();
406 return (Collections.binarySearch(HTML_TAGS, tag) >= 0);
407 }
408
409 public static String replace(String src, String token, String with) {
410 int index = src.indexOf(token);
411 if (index < 0) {
412 return src;
413 }
414 StringBuffer buffer = new StringBuffer();
415 int prev = 0;
416 while (index >= 0) {
417 buffer.append(src.substring(prev, index));
418 buffer.append(with);
419 prev = index + token.length();
420 index = src.indexOf(token, prev);
421 }
422 buffer.append(src.substring(prev));
423 return buffer.toString();
424 }
425 }