/[svn]/jlscp/trunk/src/org/linuxsampler/lscp/Parser.java
ViewVC logotype

Contents of /jlscp/trunk/src/org/linuxsampler/lscp/Parser.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1346 - (show annotations) (download)
Thu Sep 13 22:02:03 2007 UTC (16 years, 7 months ago) by iliev
File size: 23927 byte(s)
* added support for escape sequences to all
  instruments db related methods

1 /*
2 * jlscp - a java LinuxSampler control protocol API
3 *
4 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 *
6 * This file is part of jlscp.
7 *
8 * jlscp is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * jlscp is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with jlscp; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23 package org.linuxsampler.lscp;
24
25 import java.io.IOException;
26
27 import java.util.Vector;
28
29
30 /**
31 * This class contains only helper functions that are used from the other classes in this library.
32 * @author Grigor Iliev
33 */
34 public final class Parser {
35 /** Forbits the instantiatrion of this class */
36 private Parser() { }
37
38 /**
39 * Parses an integer value.
40 * @param s The integer value to be parsed.
41 * @throws LscpException If the string does not contain valid integer value.
42 */
43 protected static int
44 parseInt(String s) throws LscpException {
45 try { return Integer.parseInt(s); }
46 catch(NumberFormatException x) {
47 throw new LscpException(LscpI18n.getLogMsg("Parser.notInt!", s), x);
48 }
49 }
50
51 /**
52 * Parses a float value.
53 * @param s The float value to be parsed.
54 * @throws LscpException If the string does not contain valid float value.
55 */
56 protected static float
57 parseFloat(String s) throws LscpException {
58 try { return Float.parseFloat(s); }
59 catch(NumberFormatException x) {
60 throw new LscpException(LscpI18n.getLogMsg("Parser.notFloat!", s));
61 }
62 }
63
64 /**
65 * Parses a comma separated list.
66 *
67 * @param list The comma separated list.
68 * @return A <code>String</code> array containing all items in the list.
69 */
70 protected static String[]
71 parseList(String list) { return parseList(list, ','); }
72
73 /**
74 * Parses a list.
75 * @param list The list to parse.
76 * @param separator Provides the character used as separator.
77 * @return A <code>String</code> array containing all items in the list.
78 */
79 protected static String[]
80 parseList(String list, char separator) {
81 if(list == null || list.length() == 0) return new String[0];
82 int pos = 0;
83 int idx;
84 Vector<String> v = new Vector<String>();
85 while((idx = list.indexOf(separator, pos)) > 0) {
86 v.add(list.substring(pos, idx));
87 pos = idx + 1;
88 }
89
90 if(pos < list.length()) v.add(list.substring(pos));
91 return v.toArray(new String[v.size()]);
92 }
93
94 /**
95 * Parses a comma separated list with boolean values.
96 *
97 * @param list The comma separated list with boolean values.
98 * @return A <code>Boolean</code> array containing all items in the list.
99 */
100 protected static Boolean[]
101 parseBoolList(String list) {
102 String[] ar = parseList(list);
103
104 Boolean[] bar = new Boolean[ar.length];
105 for(int i = 0; i < ar.length; i++) {
106 bar[i] = Boolean.parseBoolean(ar[i]);
107 }
108
109 return bar;
110 }
111
112 /**
113 * Parses a comma separated list with integer values.
114 *
115 * @param list The comma separated list with integer values.
116 * @return A <code>Integer</code> array containing all items in the list.
117 *
118 * @throws LscpException if the list contains value(s) from different type.
119 */
120 protected static Integer[]
121 parseIntList(String list) throws LscpException { return parseIntList(list, ','); }
122
123 /**
124 * Parses a list of integer values.
125 *
126 * @param list The list of integer values.
127 * @param separator Provides the character used as separator.
128 * @return A <code>Integer</code> array containing all items in the list.
129 *
130 * @throws LscpException if the list contains value(s) from different type.
131 */
132 protected static Integer[]
133 parseIntList(String list, char separator) throws LscpException {
134 String[] ar = parseList(list, separator);
135
136 Integer[] iar = new Integer[ar.length];
137 for(int i = 0; i < ar.length; i++) iar[i] = parseInt(ar[i]);
138
139 return iar;
140 }
141
142 /**
143 * Parses a comma separated list with float values.
144 *
145 * @param list The comma separated list with float values.
146 * @return A <code>Float</code> array containing all items in the list.
147 *
148 * @throws LscpException if the list contains value(s) from different type.
149 */
150 protected static Float[]
151 parseFloatList(String list) throws LscpException {
152 String[] ar = parseList(list);
153
154 Float[] far = new Float[ar.length];
155 for(int i = 0; i < ar.length; i++) far[i] = parseFloat(ar[i]);
156
157 return far;
158 }
159
160 /**
161 * Parses a comma separated list whose items are not encapsulated into apostrophes.
162 * @param list The comma separated list.
163 * @return A <code>String</code> array containing all items in the list.
164 * @throws LscpException if the list is broken.
165 */
166 protected static String[]
167 parseStringList(String list) throws LscpException {
168 list = removeQuotation(list);
169 return parseList(list);
170 }
171
172 /**
173 * Parses a comma separated string list, which elements contains escaped sequences.
174 * @param list The list to parse.
175 * @return A <code>String</code> array containing all items in the list.
176 */
177 protected static String[]
178 parseEscapedStringList(String list) throws LscpException {
179 return parseEscapedStringList(list, ',');
180 }
181
182 /**
183 * Parses a string list, which elements contains escaped sequences.
184 * @param list The list to parse.
185 * @param separator Provides the character used as separator.
186 * @return A <code>String</code> array containing all items in the list.
187 */
188 protected static String[]
189 parseEscapedStringList(String list, char separator) throws LscpException {
190 if(list == null || list.length() == 0) return new String[0];
191 int q1 = 0, q2 = 0;
192 Vector<String> v = new Vector<String>();
193
194 for(;;) {
195 if(list.charAt(q1) != '\'')
196 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
197 q2 = findApostrophe(list, q1 + 1);
198 if(q2 == -1) throw new LscpException(LscpI18n.getLogMsg("Parser.EOL!"));
199 v.add(list.substring(q1 + 1, q2));
200
201 if(q2 + 1 >= list.length()) break;
202
203 if(list.charAt(q2 + 1) != separator)
204 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
205 q1 = q2 + 2;
206 if(q1 >= list.length())
207 throw new LscpException(LscpI18n.getLogMsg("Parser.EOL!"));
208 }
209
210 return v.toArray(new String[v.size()]);
211 }
212
213 /**
214 * Returns the index of the first occurrence of a non-escaped apostrophe
215 * in the specified string, starting at <b>index</b>, or -1 if nothing is found.
216 */
217 private static int
218 findApostrophe(String s, int index) {
219 return findNonEscapedChar(s, index, '\'');
220 }
221
222 /**
223 * Parses a comma separated list whose items are encapsulated into apostrophes.
224 * @param list The comma separated list.
225 * @return A <code>String</code> array containing all items in the list.
226 * @throws LscpException if the list is broken.
227 */
228 protected static String[]
229 parseQuotedStringList(String list) throws LscpException {
230 return parseQuotedStringList(list, ',');
231 }
232
233 /**
234 * Parses a list whose items are encapsulated into apostrophes.
235 * @param list The list of strings.
236 * @param separator Provides the character used as separator.
237 * @return A <code>String</code> array containing all items in the list.
238 * @throws LscpException if the list is broken.
239 */
240 protected static String[]
241 parseQuotedStringList(String list, char separator) throws LscpException {
242 if(list == null || list.length() == 0) return new String[0];
243 int q1 = 0, q2 = 0;
244 Vector<String> v = new Vector<String>();
245
246 for(;;) {
247 if(list.charAt(q1) != '\'')
248 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
249 q2 = list.indexOf('\'', q1 + 1);
250 if(q2 == -1) throw new LscpException(LscpI18n.getLogMsg("Parser.EOL!"));
251 v.add(list.substring(q1 + 1, q2));
252
253 if(q2 + 1 >= list.length()) break;
254
255 if(list.charAt(q2 + 1) != separator)
256 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
257 q1 = q2 + 2;
258 if(q1 >= list.length())
259 throw new LscpException(LscpI18n.getLogMsg("Parser.EOL!"));
260 }
261
262 return v.toArray(new String[v.size()]);
263 }
264
265 protected static String[][]
266 parseListOfStringLists(String list) throws LscpException {
267 if(list.length() == 0) return new String[0][0];
268
269 String[][] s2S;
270 if(!list.startsWith("''") && !list.startsWith("\"\"")) {
271 s2S = new String[1][];
272 s2S[0] = parseQuotedStringList(list);
273 return s2S;
274 }
275
276 int i = 0, i2 = 0;
277 Vector<String> v = new Vector<String>();
278
279 for(;;) {
280 i2 = getEndListIndex(i, list);
281 v.add(list.substring(i + 1, i2));
282 if(i2 == list.length() - 1) break;
283 if(list.charAt(i2 + 1) != ',')
284 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
285 i = i2 + 2;
286 }
287
288 s2S = new String[v.size()][];
289 for(i = 0; i < v.size(); i++) s2S[i] = parseQuotedStringList(v.get(i));
290
291 return s2S;
292 }
293
294 /**
295 * Parses a comma separated list whose items are encapsulated into curly braces.
296 *
297 * @param list The comma separated list.
298 * @return A <code>String</code> array containing all items in the list.
299 *
300 * @throws LscpException if the list is broken.
301 */
302 protected static String[]
303 parseArray(String list) throws LscpException {
304 if(list == null || list.length() == 0) return new String[0];
305 int q1 = 0, q2 = 0;
306 Vector<String> v = new Vector<String>();
307
308 for(;;) {
309 if(list.charAt(q1) != '{')
310 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
311 q2 = list.indexOf('}', q1 + 1);
312 if(q2 == -1) throw new LscpException(LscpI18n.getLogMsg("Parser.EOL!"));
313 v.add(list.substring(q1 + 1, q2));
314
315 if(q2 + 1 >= list.length()) break;
316
317 if(list.charAt(q2 + 1) != ',')
318 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
319 q1 = q2 + 2;
320 if(q1 >= list.length())
321 throw new LscpException(LscpI18n.getLogMsg("Parser.EOL!"));
322 }
323
324 return v.toArray(new String[v.size()]);
325 }
326
327 /** Helper function used by <code>parseListOfStringLists</code>. */
328 private static int
329 getEndListIndex(int start, String list) throws LscpException {
330 int i = start + 1;
331 char q = list.charAt(0); // quote symbol
332 if(list.charAt(start) != q)
333 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
334
335 if(list.charAt(i) == '\'') { // Check for empty list
336 if(i == list.length() - 1 || list.charAt(i + 1) == ',') return i;
337 }
338
339 for(;;) {
340 if(list.charAt(i) != q)
341 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
342 i = list.indexOf(q, i + 1);
343 if(i == -1 || i == list.length() - 1)
344 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
345
346 if(list.charAt(i + 1) == q) return i + 1;
347
348 if(list.charAt(i + 1) != ',')
349 throw new LscpException(LscpI18n.getLogMsg("Parser.brokenList!"));
350 i += 2;
351 }
352 }
353
354
355 /**
356 * Gets the type of the parameter represented by the specified result set.
357 * @param resultSet A <code>String</code> array containing the information categories
358 * of a multi-line result set.
359 * @return The type of the parameter represented by the specified result set or
360 * <code>null</code> if the specified result set does not contain
361 * <code>TYPE</code> category.
362 */
363 protected static ParameterType
364 parseType(String[] resultSet) {
365 if(resultSet == null || resultSet.length == 0) return null;
366 for(String s : resultSet) {
367 if(s.startsWith("TYPE: ")) {
368 String type = s.substring("TYPE: ".length(), s.length());
369 if(type.equals("BOOL")) return ParameterType.BOOL;
370 if(type.equals("INT")) return ParameterType.INT;
371 if(type.equals("FOAT")) return ParameterType.FLOAT;
372 if(type.equals("STRING")) return ParameterType.STRING;
373 }
374 }
375 return null;
376 }
377
378 /**
379 * Determines whether the parameter represented by the specified result set allows
380 * only one value or a list of values.
381 * @param resultSet A <code>String</code> array containing the information categories
382 * of a multi-line result set.
383 * @return <code>false</code> if the parameter represented by the specified result set
384 * allows only one value and <code>true</code> if allows a list of values.
385 */
386 protected static Boolean
387 parseMultiplicity(String[] resultSet) {
388 if(resultSet == null || resultSet.length == 0) return null;
389
390 for(String s : resultSet) {
391 if(s.startsWith("MULTIPLICITY: ")) return Boolean.parseBoolean (
392 s.substring("MULTIPLICITY: ".length(), s.length())
393 );
394 }
395
396 return null;
397 }
398
399 /**
400 * Parses an empty result set and returns an appropriate <code>ResultSet</code> object.
401 * Notice that the result set may be of type warning or error.
402 * @param ln A <code>String</code> representing the single line result set to be parsed.
403 * @return A <code>ResultSet</code> object.
404 * @throws LscpException If LSCP protocol error occurs.
405 * @throws LSException If the LinuxSampler instance returns error message.
406 */
407 protected static ResultSet
408 parseEmptyResultSet(String ln) throws LscpException, LSException {
409 ResultSet rs = new ResultSet();
410
411 if(ln.equals("OK")) {
412 return rs;
413 } else if(ln.startsWith("OK[") && ln.endsWith("]")) {
414 ln = ln.substring("OK[".length(), ln.length() - 1);
415 try {
416 rs.setIndex(Integer.parseInt(ln));
417 return rs;
418 } catch(NumberFormatException x) {
419 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"), x);
420 }
421 } else if(ln.startsWith("WRN")) {
422 parseWarning(ln, rs);
423 Client.getLogger().warning(rs.getMessage());
424 return rs;
425 } else if(ln.startsWith("ERR:")) {
426 parseError(ln, rs);
427 throw new LSException(rs.getCode(), rs.getMessage());
428 }
429
430 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!") );
431 }
432
433 /**
434 * Parses warning message.
435 * @param ln The warning message to be parsed.
436 * @param rs A <code>ResultSet</code> instance where the warning must be stored.
437 * @throws LscpException If LSCP protocol corruption occurs.
438 */
439 protected static void
440 parseWarning(String ln, ResultSet rs) throws LscpException {
441 if(!ln.startsWith("WRN"))
442 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
443
444 int i, j;
445 rs.setWarning(true);
446
447 if(ln.charAt(3) == '[') {
448 i = ln.indexOf(']');
449 if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
450
451 try {
452 j = Integer.parseInt(ln.substring("WRN[".length(), i));
453 rs.setIndex(j);
454 } catch(NumberFormatException x) {
455 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"), x);
456 }
457
458 if(ln.charAt(i + 1) != ':')
459 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
460 }
461
462 i = ln.indexOf(':');
463 if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
464 j = ln.indexOf(':', i + 1);
465 if(j == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
466
467 try { rs.setCode(Integer.parseInt(ln.substring(i + 1, j))); }
468 catch(NumberFormatException x) {
469 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"), x);
470 }
471
472 rs.setMessage(ln.substring(j + 1));
473 }
474
475 /**
476 * Parses error message.
477 * @param ln The error message to be parsed.
478 * @param rs A <code>ResultSet</code> instance where the error must be stored.
479 * @throws LscpException If LSCP protocol corruption occurs.
480 */
481 protected static void
482 parseError(String ln, ResultSet rs) throws LscpException {
483 if(!ln.startsWith("ERR:"))
484 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
485
486 int i = ln.indexOf(':', "ERR:".length());
487 if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
488
489 try { rs.setCode(Integer.parseInt(ln.substring("ERR:".length(), i))); }
490 catch(NumberFormatException x) {
491 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"), x);
492 }
493
494 rs.setMessage(ln.substring(i + 1));
495 }
496
497 /**
498 * Gets the info character string to the specified information category.
499 * @param resultSet A <code>String</code> array containing the information categories
500 * of a multi-line result set.
501 * @param category Specifies the category whose info character string to be returned.
502 * @return The info character string to the specified information category or
503 * <code>null</code> if the specified result set does not contain that category.
504 */
505 protected static String
506 getCategoryInfo(String[] resultSet, String category) {
507 String c = category + ": ";
508 for(String s : resultSet)
509 if(s.startsWith(c)) return s.substring(c.length(), s.length());
510
511 return null;
512 }
513
514 /**
515 * Eliminates the quotation marks if the string is quoted.
516 * @return New string without quotation marks if the string is quoted; else
517 * the same string is returned.
518 */
519 protected static String
520 removeQuotation(String s) {
521 if(s == null || s.length() < 2) return s;
522 char q = s.charAt(0);
523 char q2 = s.charAt(s.length() - 1);
524 if((q == '\'' && q2 == '\'') || (q == '"' && q2 == '"'))
525 return s.substring(1, s.length() - 1);
526
527 return s;
528 }
529
530 /**
531 * Returns the provided string with added escape sequences where necessary.
532 */
533 public static String
534 toEscapedString(Object obj) {
535 String s = obj.toString();
536 StringBuffer sb = new StringBuffer();
537 for(int i = 0; i < s.length(); i++) {
538 switch(s.charAt(i)) {
539 case '\n': sb.append("\\n"); break;
540 case '\r': sb.append("\\r"); break;
541 case '\f': sb.append("\\f"); break;
542 case '\t': sb.append("\\t"); break;
543 case 0x0B: sb.append("\\v"); break;
544 case '\'': sb.append("\\'"); break;
545 case '\"': sb.append("\\\""); break;
546 case '\\': sb.append("\\\\"); break;
547 default : sb.append(s.charAt(i));
548 }
549 }
550
551 return sb.toString();
552 }
553
554 /**
555 * Returns the provided file name with added escape sequences where necessary.
556 */
557 public static String
558 toEscapedFileName(Object obj) {
559 String s = obj.toString();
560 StringBuffer sb = new StringBuffer();
561 for(int i = 0; i < s.length(); i++) {
562 switch(s.charAt(i)) {
563 case '/' : sb.append("\\/"); break;
564 case '\n': sb.append("\\n"); break;
565 case '\r': sb.append("\\r"); break;
566 case '\f': sb.append("\\f"); break;
567 case '\t': sb.append("\\t"); break;
568 case 0x0B: sb.append("\\v"); break;
569 case '\'': sb.append("\\'"); break;
570 case '\"': sb.append("\\\""); break;
571 case '\\': sb.append("\\\\"); break;
572 default : sb.append(s.charAt(i));
573 }
574 }
575
576 return sb.toString();
577 }
578
579 /**
580 * Removes the escape sequences from the specified file name
581 * @return The provided file name with removed escape sequences.
582 */
583 public static String
584 toNonEscapedFileName(Object obj) {
585 String s = obj.toString();
586 StringBuffer sb = new StringBuffer();
587 for(int i = 0; i < s.length(); i++) {
588 char c = s.charAt(i);
589 if(c == '\\') {
590 if(i >= s.length()) {
591 Client.getLogger().info("Broken escape sequence");
592 break;
593 }
594 char c2 = s.charAt(++i);
595 if(c2 == '\'') sb.append('\'');
596 else if(c2 == '"') sb.append('"');
597 else if(c2 == '\\') sb.append('\\');
598 else if(c2 == 'r') sb.append('\r');
599 else if(c2 == 'n') sb.append('\n');
600 else if(c2 == '/') sb.append('/');
601 else Client.getLogger().info("Unknown escape sequence \\" + c2);
602 } else {
603 sb.append(c);
604 }
605 }
606
607 return sb.toString();
608 }
609
610 /**
611 * Removes the escape sequences from the string <code>obj.toString()</code>.
612 * @return The provided text with removed escape sequences.
613 */
614 public static String
615 toNonEscapedText(Object obj) {
616 String s = obj.toString();
617 StringBuffer sb = new StringBuffer();
618 for(int i = 0; i < s.length(); i++) {
619 char c = s.charAt(i);
620 if(c == '\\') {
621 if(i >= s.length()) {
622 Client.getLogger().info("Broken escape sequence");
623 break;
624 }
625 char c2 = s.charAt(++i);
626 if(c2 == '\'') sb.append('\'');
627 else if(c2 == '"') sb.append('"');
628 else if(c2 == '\\') sb.append('\\');
629 else if(c2 == 'r') sb.append('\r');
630 else if(c2 == 'n') sb.append('\n');
631 else Client.getLogger().info("Unknown escape sequence \\" + c2);
632 } else {
633 sb.append(c);
634 }
635 }
636
637 return sb.toString();
638 }
639
640 /**
641 * Determines whether the character at the specified position
642 * is escaped with backslash.
643 */
644 public static boolean
645 isEscaped(String s, int index) {
646 if (index < 0 || index >= s.length()) return false;
647 int count = 0;
648 for (int i = index - 1; i >= 0; i--) {
649 if (s.charAt(i) != '\\') break;
650 count++;
651 }
652 return count % 2 != 0;
653 }
654
655 /**
656 * Returns the index of the first occurrence of the specified non-escaped character
657 * in the specified string, starting at <b>index</b>, or -1 if nothing is found.
658 */
659 private static int
660 findNonEscapedChar(String s, int index, char c) {
661 if(s == null) return -1;
662 int pos = index;
663 if (pos < 0 || pos >= s.length()) return -1;
664
665 for(;;) {
666 int i = s.indexOf(c, pos);
667 if (i == -1) break;
668 if (!isEscaped(s, i)) return i;
669 pos = i + 1;
670 if (pos >= s.length()) break;
671 }
672
673 return -1;
674 }
675
676 /**
677 * Returns the index of the first occurrence of a file separator
678 * in the specified escaped path, starting at <b>index</b>, or -1 if nothing is found.
679 */
680 private static int
681 findFileSeparator(String path, int index) {
682 return findNonEscapedChar(path, index, '/');
683 }
684
685 /**
686 * Gets the position of the last file separator in the specified
687 * escaped path, or -1 if failed.
688 */
689 private static int
690 getLastFileSeparator(String path) {
691 if(path == null || path.length() == 0) return -1;
692 int pos = path.length() - 1;
693
694 for(;;) {
695 pos = path.lastIndexOf('/', pos);
696 if(pos == -1) return -1;
697 if(!isEscaped(path, pos)) return pos;
698 pos--;
699 }
700 }
701
702 /**
703 * Determines whether the specified escaped path ends with a file separator.
704 */
705 protected static boolean
706 hasEndingFileSeparator(String path) {
707 if(path == null || path.length() < 2) return false;
708
709 int last = path.length() - 1;
710 if(path.charAt(last) == '/' && !isEscaped(path, last)) return true;
711
712 return false;
713 }
714
715 /**
716 * If the specified escaped path ends with a file separator,
717 * a new string is returned with the ending file separator removed.
718 */
719 protected static String
720 removeEndingFileSeparator(String path) {
721 if(path == null || path.length() < 2) return path;
722
723 int last = path.length() - 1;
724 if(path.charAt(last) == '/' && !isEscaped(path, last)) {
725 path = path.substring(0, path.length() - 1);
726 }
727
728 return path;
729 }
730
731 /**
732 * Gets the parent directory of the specified escaped path.
733 */
734 public static String
735 getParentDirectory(String path) {
736 if(path == null || path.length() == 0) return null;
737 if(path.charAt(0) != '/') return null;
738 if(path.length() == 1) return null;
739
740 path = removeEndingFileSeparator(path);
741
742 int i = getLastFileSeparator(path);
743 if(i == 0) return "/";
744 return path.substring(0, i);
745 }
746
747 /**
748 * Extracts the file name from the specified escaped path.
749 * If the path does not ends with a file name, <code>null</code> is returned.
750 */
751 public static String
752 getFileName(String path) {
753 if(path == null || path.length() < 2) return null;
754 int i = getLastFileSeparator(path);
755 if(i == -1) return null;
756 if(i == path.length() - 1) return null;
757 return path.substring(i + 1);
758 }
759
760 /**
761 * Returns an array containing all directories in the specified escaped path.
762 */
763 public static String[]
764 getDirectoryList(String path) {
765 if(path == null || path.length() == 0) return null;
766 if(path.charAt(0) != '/') return null;
767 Vector<String> v = new Vector<String>();
768 v.add("/");
769 if(path.length() == 1) return v.toArray(new String[v.size()]);
770
771 if(!hasEndingFileSeparator(path)) path += "/";
772 int i = 1;
773 int j = findFileSeparator(path, i);
774
775 while(j != -1) {
776 v.add(path.substring(i, j));
777
778 i = j + 1;
779 if(i >= path.length()) return v.toArray(new String[v.size()]);
780 j = findFileSeparator(path, i);
781 }
782
783 return null;
784 }
785 }

  ViewVC Help
Powered by ViewVC