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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1346 - (hide 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 iliev 596 /*
2     * jlscp - a java LinuxSampler control protocol API
3     *
4 iliev 1326 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 596 *
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 iliev 1346 public final class Parser {
35 iliev 1139 /** Forbits the instantiatrion of this class */
36     private Parser() { }
37    
38 iliev 596 /**
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 iliev 1139 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 iliev 596 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 iliev 1139 while((idx = list.indexOf(separator, pos)) > 0) {
86 iliev 596 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 iliev 1139 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 iliev 596
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 iliev 1326
160 iliev 596 /**
161 iliev 1326 * Parses a comma separated list whose items are not encapsulated into apostrophes.
162 iliev 596 * @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 iliev 1326 list = removeQuotation(list);
169     return parseList(list);
170 iliev 1202 }
171    
172     /**
173 iliev 1346 * 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 iliev 1326 * 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 iliev 1202 * 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 iliev 1326 parseQuotedStringList(String list, char separator) throws LscpException {
242 iliev 596 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 iliev 1202 if(list.charAt(q2 + 1) != separator)
256 iliev 596 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 iliev 1326 s2S[0] = parseQuotedStringList(list);
273 iliev 596 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 iliev 1326 for(i = 0; i < v.size(); i++) s2S[i] = parseQuotedStringList(v.get(i));
290 iliev 596
291     return s2S;
292     }
293    
294 iliev 1139 /**
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 iliev 596 /** 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 iliev 784
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 iliev 1307
530     /**
531     * Returns the provided string with added escape sequences where necessary.
532     */
533 iliev 1346 public static String
534     toEscapedString(Object obj) {
535     String s = obj.toString();
536 iliev 1307 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 iliev 1346
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 iliev 596 }

  ViewVC Help
Powered by ViewVC