Utils.java

00001 // Utils - assorted static utility routines
00002 //
00003 // Copyright (C)1996,1998 by Jef Poskanzer <jef@acme.com>.  All rights reserved.
00004 //
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions
00007 // are met:
00008 // 1. Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 // 2. Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //
00014 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00015 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00016 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00017 // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00018 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00019 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00020 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00021 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00022 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00023 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00024 // SUCH DAMAGE.
00025 //
00026 // Visit the ACME Labs Java page for up-to-date versions of this and other
00027 // fine Java utilities: http://www.acme.com/java/
00028 
00029 package Acme;
00030 
00031 import java.util.*;
00032 import java.io.*;
00033 import java.net.*;
00034 import java.text.SimpleDateFormat;
00035 
00037 // <P>
00038 // Whenever I come up with a static routine that might be of general use,
00039 // I put it here.  So far the class includes:
00040 // <UL>
00041 // <LI> some string routines that were left out of java.lang.String
00042 // <LI> a general array-to-string routine
00043 // <LI> a fixed version of java.io.InputStream's byte-array read routine
00044 // <LI> a bunch of URL-hacking routines
00045 // <LI> some easy-to-use wrappers for Runtime.exec
00046 // <LI> a debugging routine to dump the current call stack
00047 // <LI> a URLDecoder to match java.net.URLEncoder
00048 // </UL>
00049 // and lots more.
00050 // <P>
00051 // <A HREF="/resources/classes/Acme/Utils.java">Fetch the software.</A><BR>
00052 // <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>
00053 
00054 public class Utils {
00055 
00057         // six months of now, Mmm dd hh:ss, else Mmm dd  yyyy.
00058         static final SimpleDateFormat shortfmt = new SimpleDateFormat("MMM dd HH:mm");
00059         static final SimpleDateFormat longfmt = new SimpleDateFormat("MMM dd yyyy");
00060 
00061         public static String lsDateStr(Date date) {
00062                 if (Math.abs(System.currentTimeMillis() - date.getTime()) < 183L * 24L * 60L * 60L * 1000L)
00063                         return shortfmt.format(date);
00064                 else
00065                         return longfmt.format(date);
00066         }
00067 
00069         public static String pluralStr(long n) {
00070                 if (n == 1)
00071                         return "";
00072                 else
00073                         return "s";
00074         }
00075 
00076         // Various interval constants.  Some are only approximate.
00077         public static final long INT_SECOND = 1000L;
00078         public static final long INT_MINUTE = INT_SECOND * 60L;
00079         public static final long INT_HOUR = INT_MINUTE * 60L;
00080         public static final long INT_DAY = INT_HOUR * 24L;
00081         public static final long INT_WEEK = INT_DAY * 7L;
00082         public static final long INT_MONTH = INT_DAY * 30L;
00083         public static final long INT_YEAR = INT_DAY * 365L;
00084         public static final long INT_DECADE = INT_DAY * 3652L;
00085 
00087         // @param interval the interval, in milliseconds
00088         public static String intervalStr(long interval) {
00089                 long decades, years, months, weeks, days, hours, minutes, seconds, millis;
00090 
00091                 decades = interval / INT_DECADE;
00092                 interval -= decades * INT_DECADE;
00093                 years = interval / INT_YEAR;
00094                 interval -= years * INT_YEAR;
00095                 months = interval / INT_MONTH;
00096                 interval -= months * INT_MONTH;
00097                 weeks = interval / INT_WEEK;
00098                 interval -= weeks * INT_WEEK;
00099                 days = interval / INT_DAY;
00100                 interval -= days * INT_DAY;
00101                 hours = interval / INT_HOUR;
00102                 interval -= hours * INT_HOUR;
00103                 minutes = interval / INT_MINUTE;
00104                 interval -= minutes * INT_MINUTE;
00105                 seconds = interval / INT_SECOND;
00106                 interval -= seconds * INT_SECOND;
00107                 millis = interval;
00108 
00109                 if (decades > 0)
00110                         if (years == 0)
00111                                 return decades + " decade" + pluralStr(decades);
00112                         else
00113                                 return decades + " decade" + pluralStr(decades) + ", " + years + " years" + pluralStr(years);
00114                 else if (years > 0)
00115                         if (months == 0)
00116                                 return years + " year" + pluralStr(years);
00117                         else
00118                                 return years + " year" + pluralStr(years) + ", " + months + " month" + pluralStr(months);
00119                 else if (months > 0)
00120                         if (weeks == 0)
00121                                 return months + " month" + pluralStr(months);
00122                         else
00123                                 return months + " month" + pluralStr(months) + ", " + weeks + " week" + pluralStr(weeks);
00124                 else if (weeks > 0)
00125                         if (days == 0)
00126                                 return weeks + " week" + pluralStr(weeks);
00127                         else
00128                                 return weeks + " week" + pluralStr(weeks) + ", " + days + " day" + pluralStr(days);
00129                 else if (days > 0)
00130                         if (hours == 0)
00131                                 return days + " day" + pluralStr(days);
00132                         else
00133                                 return days + " day" + pluralStr(days) + ", " + hours + " hour" + pluralStr(hours);
00134                 else if (hours > 0)
00135                         if (minutes == 0)
00136                                 return hours + " hour" + pluralStr(hours);
00137                         else
00138                                 return hours + " hour" + pluralStr(hours) + ", " + minutes + " minute" + pluralStr(minutes);
00139                 else if (minutes > 0)
00140                         if (seconds == 0)
00141                                 return minutes + " minute" + pluralStr(minutes);
00142                         else
00143                                 return minutes + " minute" + pluralStr(minutes) + ", " + seconds + " second" + pluralStr(seconds);
00144                 else if (seconds > 0)
00145                         if (millis == 0)
00146                                 return seconds + " second" + pluralStr(seconds);
00147                         else
00148                                 return seconds + " second" + pluralStr(seconds) + ", " + millis + " millisecond" + pluralStr(millis);
00149                 else
00150                         return millis + " millisecond" + pluralStr(millis);
00151         }
00152 
00154         // entirely of characters from charSet.
00155         public static int strSpan(String str, String charSet) {
00156                 return strSpan(str, charSet, 0);
00157         }
00158 
00160         // entirely of characters from charSet, starting at the given index.
00161         public static int strSpan(String str, String charSet, int fromIdx) {
00162                 int i;
00163                 for (i = fromIdx; i < str.length(); ++i)
00164                         if (charSet.indexOf(str.charAt(i)) == -1)
00165                                 break;
00166                 return i - fromIdx;
00167         }
00168 
00170         // entirely of characters NOT from charSet.
00171         public static int strCSpan(String str, String charSet) {
00172                 return strCSpan(str, charSet, 0);
00173         }
00174 
00176         // entirely of characters NOT from charSet, starting at the given index.
00177         public static int strCSpan(String str, String charSet, int fromIdx) {
00178                 int i;
00179                 for (i = fromIdx; i < str.length(); ++i)
00180                         if (charSet.indexOf(str.charAt(i)) != -1)
00181                                 break;
00182                 return i - fromIdx;
00183         }
00184 
00186         // Only does ? and *, and multiple patterns separated by |.
00187         public static boolean match(String pattern, String string) {
00188                 for (int p = 0;; ++p) {
00189                         for (int s = 0;; ++p, ++s) {
00190                                 boolean sEnd = (s >= string.length());
00191                                 boolean pEnd = (p >= pattern.length() || pattern.charAt(p) == '|');
00192                                 if (sEnd && pEnd)
00193                                         return true;
00194                                 if (sEnd || pEnd)
00195                                         break;
00196                                 if (pattern.charAt(p) == '?')
00197                                         continue;
00198                                 if (pattern.charAt(p) == '*') {
00199                                         int i;
00200                                         ++p;
00201                                         for (i = string.length(); i >= s; --i)
00202                                                 if (match(pattern.substring(p), string.substring(i))) /* not quite right */
00203                                                         return true;
00204                                         break;
00205                                 }
00206                                 if (pattern.charAt(p) != string.charAt(s))
00207                                         break;
00208                         }
00209                         p = pattern.indexOf('|', p);
00210                         if (p == -1)
00211                                 return false;
00212                 }
00213         }
00214 
00216         // pattern.  Only does ? and *, and multiple patterns separated by |.
00217         public static int matchSpan(String pattern, String string) {
00218                 int result = 0;
00219                 StringTokenizer st = new StringTokenizer(pattern, "|");
00220 
00221                 while (st.hasMoreTokens()) {
00222                         int len = matchSpan1(st.nextToken(), string);
00223                         if (len > result)
00224                                 result = len;
00225                 }
00226                 return result;
00227         }
00228 
00229         static int matchSpan1(String pattern, String string) {
00230                 int p = 0;
00231                 for (; p < string.length() && p < pattern.length(); p++) {
00232                         if (pattern.charAt(p) == string.charAt(p))
00233                                 continue;
00234                         if (pattern.charAt(p) == '*')
00235                                 return p - 1;
00236                         return 0;
00237                 }
00238                 return p < (pattern.length() - 1) ? -1 : p;
00239         }
00240 
00242         public static int sameSpan(String str1, String str2) {
00243                 int i;
00244                 for (i = 0; i < str1.length() && i < str2.length() && str1.charAt(i) == str2.charAt(i); ++i)
00245                         ;
00246                 return i;
00247         }
00248 
00250         public static int charCount(String str, char c) {
00251                 int n = 0;
00252                 for (int i = 0; i < str.length(); ++i)
00253                         if (str.charAt(i) == c)
00254                                 ++n;
00255                 return n;
00256         }
00257 
00259         // to split it up at whitespace.
00260         public static String[] splitStr(String str) {
00261                 StringTokenizer st = new StringTokenizer(str);
00262                 int n = st.countTokens();
00263                 String[] strs = new String[n];
00264                 for (int i = 0; i < n; ++i)
00265                         strs[i] = st.nextToken();
00266                 return strs;
00267         }
00268 
00270         // the specified character.  This does not use StringTokenizer,
00271         // and therefore can handle empty fields.
00272         public static String[] splitStr(String str, char delim) {
00273                 int n = 1;
00274                 int index = -1;
00275                 while (true) {
00276                         index = str.indexOf(delim, index + 1);
00277                         if (index == -1)
00278                                 break;
00279                         ++n;
00280                 }
00281                 String[] strs = new String[n];
00282                 index = -1;
00283                 for (int i = 0; i < n - 1; ++i) {
00284                         int nextIndex = str.indexOf(delim, index + 1);
00285                         strs[i] = str.substring(index + 1, nextIndex);
00286                         index = nextIndex;
00287                 }
00288                 strs[n - 1] = str.substring(index + 1);
00289                 return strs;
00290         }
00291 
00293         // separated by spaces.
00294         public static String flattenStrarr(String[] strs) {
00295                 StringBuffer sb = new StringBuffer();
00296                 for (int i = 0; i < strs.length; ++i) {
00297                         if (i > 0)
00298                                 sb.append(' ');
00299                         sb.append(strs[i]);
00300                 }
00301                 return sb.toString();
00302         }
00303 
00305         // Java currently has no general sort function.  Sorting Strings is
00306         // common enough that it's worth making a special case.
00307         public static void sortStrings(String[] strings) {
00308                 // Just does a bubblesort.
00309                 for (int i = 0; i < strings.length - 1; ++i) {
00310                         for (int j = i + 1; j < strings.length; ++j) {
00311                                 if (strings[i].compareTo(strings[j]) > 0) {
00312                                         String t = strings[i];
00313                                         strings[i] = strings[j];
00314                                         strings[j] = t;
00315                                 }
00316                         }
00317                 }
00318         }
00319 
00321         // Returns -1 if the String is not found.
00322         public static int indexOfString(String[] strings, String string) {
00323                 for (int i = 0; i < strings.length; ++i)
00324                         if (string.equals(strings[i]))
00325                                 return i;
00326                 return -1;
00327         }
00328 
00330         // Returns -1 if the String is not found.
00331         public static int indexOfStringIgnoreCase(String[] strings, String string) {
00332                 for (int i = 0; i < strings.length; ++i)
00333                         if (string.equalsIgnoreCase(strings[i]))
00334                                 return i;
00335                 return -1;
00336         }
00337 
00339         public static boolean equalsStrings(String[] strings1, String[] strings2) {
00340                 if (strings1.length != strings2.length)
00341                         return false;
00342                 for (int i = 0; i < strings1.length; ++i)
00343                         if (!strings1[i].equals(strings2[i]))
00344                                 return false;
00345                 return true;
00346         }
00347 
00349         // of Math.pow().  Throws ArithmeticException if b is negative.
00350         public static long pow(long a, long b) throws ArithmeticException {
00351                 if (b < 0)
00352                         throw new ArithmeticException();
00353                 long r = 1;
00354                 while (b != 0) {
00355                         if (odd(b))
00356                                 r *= a;
00357                         b >>>= 1;
00358                         a *= a;
00359                 }
00360                 return r;
00361         }
00362 
00364         public static int parseInt(String str, int def) {
00365                 try {
00366                         return Integer.parseInt(str);
00367                 } catch (Exception e) {
00368                         return def;
00369                 }
00370         }
00371 
00373         public static long parseLong(String str, long def) {
00374                 try {
00375                         return Long.parseLong(str);
00376                 } catch (Exception e) {
00377                         return def;
00378                 }
00379         }
00380 
00382         // type, including nested arrays.  Sample output:
00383         // <BLOCKQUOTE><CODE><PRE>
00384         // byte[]:    { (byte)0, (byte)1, (byte)2 }
00385         // char[]:    { '0', '1', '2' }
00386         // short[]:   { (short)0, (short)1, (short)2 }
00387         // int[]:     { 0, 1, 2 }
00388         // long[]:    { 0L, 1L, 2L }
00389         // float[]:   { 0F, 1F, 2F }
00390         // double[]:  { 0D, 1D, 2D }
00391         // String[]:  { "0", "1", "2" }
00392         // int[][]:   { { 0, 1, 2 }, { 3, 4, 5 } }
00393         // </PRE></CODE></BLOCKQUOTE>
00394         public static String arrayToString(Object o) {
00395                 if (o == null)
00396                         return "null";
00397                 String cl = o.getClass().getName();
00398                 if (!cl.startsWith("["))
00399                         // It's not an array; just call its toString method.
00400                         return o.toString();
00401                 StringBuffer sb = new StringBuffer("{ ");
00402                 if (o instanceof byte[]) {
00403                         byte[] ba = (byte[]) o;
00404                         for (int i = 0; i < ba.length; ++i) {
00405                                 if (i > 0)
00406                                         sb.append(", ");
00407                                 sb.append("(byte)");
00408                                 sb.append(ba[i]);
00409                         }
00410                 } else if (o instanceof char[]) {
00411                         char[] ca = (char[]) o;
00412                         for (int i = 0; i < ca.length; ++i) {
00413                                 if (i > 0)
00414                                         sb.append(", ");
00415                                 sb.append("'");
00416                                 sb.append(ca[i]);
00417                                 sb.append("'");
00418                         }
00419                 } else if (o instanceof short[]) {
00420                         short[] sa = (short[]) o;
00421                         for (int i = 0; i < sa.length; ++i) {
00422                                 if (i > 0)
00423                                         sb.append(", ");
00424                                 sb.append("(short)");
00425                                 sb.append(sa[i]);
00426                         }
00427                 } else if (o instanceof int[]) {
00428                         int[] ia = (int[]) o;
00429                         for (int i = 0; i < ia.length; ++i) {
00430                                 if (i > 0)
00431                                         sb.append(", ");
00432                                 sb.append(ia[i]);
00433                         }
00434                 } else if (o instanceof long[]) {
00435                         long[] la = (long[]) o;
00436                         for (int i = 0; i < la.length; ++i) {
00437                                 if (i > 0)
00438                                         sb.append(", ");
00439                                 sb.append(la[i]);
00440                                 sb.append("L");
00441                         }
00442                 } else if (o instanceof float[]) {
00443                         float[] fa = (float[]) o;
00444                         for (int i = 0; i < fa.length; ++i) {
00445                                 if (i > 0)
00446                                         sb.append(", ");
00447                                 sb.append(fa[i]);
00448                                 sb.append("F");
00449                         }
00450                 } else if (o instanceof double[]) {
00451                         double[] da = (double[]) o;
00452                         for (int i = 0; i < da.length; ++i) {
00453                                 if (i > 0)
00454                                         sb.append(", ");
00455                                 sb.append(da[i]);
00456                                 sb.append("D");
00457                         }
00458                 } else if (o instanceof String) {
00459                         // Special-case Strings so we can surround them with quotes.
00460                         String[] sa = (String[]) o;
00461                         for (int i = 0; i < sa.length; ++i) {
00462                                 if (i > 0)
00463                                         sb.append(", ");
00464                                 sb.append("\"");
00465                                 sb.append(sa[i]);
00466                                 sb.append("\"");
00467                         }
00468                 } else if (cl.startsWith("[L")) {
00469                         // Some random class.
00470                         Object[] oa = (Object[]) o;
00471                         for (int i = 0; i < oa.length; ++i) {
00472                                 if (i > 0)
00473                                         sb.append(", ");
00474                                 sb.append(oa[i]);
00475                         }
00476                 } else if (cl.startsWith("[[")) {
00477                         // Nested arrays.
00478                         Object[] aa = (Object[]) o;
00479                         for (int i = 0; i < aa.length; ++i) {
00480                                 if (i > 0)
00481                                         sb.append(", ");
00482                                 sb.append(arrayToString(aa[i]));
00483                         }
00484                 } else
00485                         sb.append("(unknown array type)");
00486                 sb.append(" }");
00487                 return sb.toString();
00488         }
00489 
00491         // An instanceof that works on Class objects at runtime, instead
00492         // of type descriptors at compile time.
00493         public static boolean instanceOf(Object o, Class cl) {
00494                 // Null check.
00495                 if (o == null || cl == null)
00496                         return false;
00497                 Class ocl = o.getClass();
00498                 // Check if they are the same class.
00499                 if (ocl.equals(cl))
00500                         return true;
00501                 // If the class is not itself an interface, then check its interfaces.
00502                 if (!cl.isInterface()) {
00503                         Class ifs[] = cl.getInterfaces();
00504                         for (int i = 0; i < ifs.length; ++i)
00505                                 if (instanceOf(o, ifs[i]))
00506                                         return true;
00507                 }
00508                 // And check supeclasses.
00509                 Class scl = cl.getSuperclass();
00510                 if (scl != null)
00511                         if (instanceOf(o, scl))
00512                                 return true;
00513                 // Guess not.
00514                 return false;
00515         }
00516 
00518         public static boolean even(long n) {
00519                 return (n & 1) == 0;
00520         }
00521 
00523         public static boolean odd(long n) {
00524                 return (n & 1) != 0;
00525         }
00526 
00528         public static int countOnes(byte n) {
00529                 return countOnes(n & 0xffL);
00530         }
00531 
00533         public static int countOnes(int n) {
00534                 return countOnes(n & 0xffffffffL);
00535         }
00536 
00538         public static int countOnes(long n) {
00539                 // There are faster ways to do this, all the way up to looking
00540                 // up bytes in a 256-element table.  But this is not too bad.
00541                 int count = 0;
00542                 while (n != 0) {
00543                         if (odd(n))
00544                                 ++count;
00545                         n >>>= 1;
00546                 }
00547                 return count;
00548         }
00549 
00551         // standard version catches and ignores IOExceptions from below.
00552         // This version sends them on to the caller.
00553         public static int read(InputStream in, byte[] b, int off, int len) throws IOException {
00554                 if (len <= 0)
00555                         return 0;
00556                 int c = in.read();
00557                 if (c == -1)
00558                         return -1;
00559                 if (b != null)
00560                         b[off] = (byte) c;
00561                 int i;
00562                 for (i = 1; i < len; ++i) {
00563                         c = in.read();
00564                         if (c == -1)
00565                                 break;
00566                         if (b != null)
00567                                 b[off + i] = (byte) c;
00568                 }
00569                 return i;
00570         }
00571 
00573         // of sometimes terminating early.
00574         // @return -1 on EOF, otherwise len
00575         public static int readFully(InputStream in, byte[] b, int off, int len) throws IOException {
00576                 int l, r;
00577                 for (l = 0; l < len;) {
00578                         r = read(in, b, l, len - l);
00579                         if (r == -1)
00580                                 return -1;
00581                         l += r;
00582                 }
00583                 return len;
00584         }
00585 
00587         // a directory then make sure there's a trailing slash.
00588         public static URL plainUrl(URL context, String urlStr) throws MalformedURLException {
00589                 URL url = new URL(context, urlStr);
00590                 String fileStr = url.getFile();
00591                 int i = fileStr.indexOf('?');
00592                 if (i != -1)
00593                         fileStr = fileStr.substring(0, i);
00594                 url = new URL(url.getProtocol(), url.getHost(), url.getPort(), fileStr);
00595                 if ((!fileStr.endsWith("/")) && urlStrIsDir(url.toExternalForm())) {
00596                         fileStr = fileStr + "/";
00597                         url = new URL(url.getProtocol(), url.getHost(), url.getPort(), fileStr);
00598                 }
00599                 return url;
00600         }
00601 
00603         // a directory then make sure there's a trailing slash.
00604         public static URL plainUrl(String urlStr) throws MalformedURLException {
00605                 return plainUrl(null, urlStr);
00606         }
00607 
00609         // if the URL points to a directory, you get that directory; if the
00610         // URL points to a file, you get the directory the file is in.
00611         public static String baseUrlStr(String urlStr) {
00612                 if (urlStr.endsWith("/"))
00613                         return urlStr;
00614                 if (urlStrIsDir(urlStr))
00615                         return urlStr + "/";
00616                 return urlStr.substring(0, urlStr.lastIndexOf('/') + 1);
00617         }
00618 
00620         public static String fixDirUrlStr(String urlStr) {
00621                 if (urlStr.endsWith("/"))
00622                         return urlStr;
00623                 if (urlStrIsDir(urlStr))
00624                         return urlStr + "/";
00625                 return urlStr;
00626         }
00627 
00629         // Web servers are lenient and accept directory-URLs without
00630         // the trailing slash.  What they actually do is return a
00631         // redirect to the same URL with the trailing slash appended.
00632         // Unfortunately, Java doesn't let us see that such a redirect
00633         // happened.  Instead we have to figure out it's a directory
00634         // indirectly and heuristically.
00635         public static boolean urlStrIsDir(String urlStr) {
00636                 // If it ends with a slash, it's probably a directory.
00637                 if (urlStr.endsWith("/"))
00638                         return true;
00639 
00640                 // If the last component has a dot, it's probably not a directory.
00641                 int lastSlash = urlStr.lastIndexOf('/');
00642                 int lastPeriod = urlStr.lastIndexOf('.');
00643                 if (lastPeriod != -1 && (lastSlash == -1 || lastPeriod > lastSlash))
00644                         return false;
00645 
00646                 // Otherwise, append a slash and try to connect.  This is
00647                 // fairly expensive.
00648                 String urlStrWithSlash = urlStr + "/";
00649                 try {
00650                         URL url = new URL(urlStrWithSlash);
00651                         InputStream f = url.openStream();
00652                         f.close();
00653                         // Worked fine - it's probably a directory.
00654                         return true;
00655                 } catch (Exception e) {
00656                         // Got an error - must not be a directory.
00657                         return false;
00658                 }
00659         }
00660 
00661         // Figures out whether a URL is absolute or not.
00662         public static boolean urlStrIsAbsolute(String urlStr) {
00663                 if (urlStr.startsWith("/") || urlStr.indexOf(":/") != -1)
00664                         return true;
00665                 // Should handle :8000/ and such too.
00666                 return false;
00667         }
00668 
00669         // Returns an equivalent URL string that is guaranteed to be absolute.
00670         public static String absoluteUrlStr(String urlStr, URL contextUrl) throws MalformedURLException {
00671                 URL url = new URL(contextUrl, urlStr);
00672                 return url.toExternalForm();
00673         }
00674 
00676         // already a decoder in the standard library is a mystery to me.
00677         public static String urlDecoder(String encoded) throws UnsupportedEncodingException {
00678                 StringBuffer decoded = new StringBuffer();
00679                 int len = encoded.length();
00680                 for (int i = 0; i < len; ++i) {
00681                         if (encoded.charAt(i) == '%' && i + 2 < len) {
00682                                 int d1 = Character.digit(encoded.charAt(i + 1), 16);
00683                                 int d2 = Character.digit(encoded.charAt(i + 2), 16);
00684                                 if (d1 != -1 && d2 != -1)
00685                                         decoded.append((char) ((d1 << 4) + d2));
00686                                 i += 2;
00687                         } else if (encoded.charAt(i) == '+')
00688                                 decoded.append(' ');
00689                         else
00690                                 decoded.append(encoded.charAt(i));
00691                 }
00692                 return decoded.toString();
00693         }
00694 
00696         public static boolean arraycontains(Object[] array, Object element) {
00697                 for (int i = 0; i < array.length; ++i)
00698                         if (array[i].equals(element))
00699                                 return true;
00700                 return false;
00701         }
00702 
00704         // <P>
00705         // This routine runs the specified command, waits for it to
00706         // finish, and returns the exit status.
00707         // This is like the Unix system() routine.  Unlike the Unix version,
00708         // though, stdout and stderr get thrown away unless you redirect them.
00709         public static int system(String cmd) {
00710                 try {
00711                         return runCommand(cmd).waitFor();
00712                 } catch (IOException e) {
00713                         return -1;
00714                 } catch (InterruptedException e) {
00715                         return -1;
00716                 }
00717         }
00718 
00720         // <P>
00721         // This routine runs the specified command, and returns an InputStream
00722         // for reading the output of the program.
00723         // <P>
00724         // <B>WARNING:</B> In JDK1.0.2 there is a serious bug in the process
00725         // IO routines, such that reading all the way to the end of a process's
00726         // output will invariably get you an IOException( "read error" ).
00727         // In some cases you will also <B>lose</B> the last bufferload of
00728         // the output.  The workaround is to add a " ; sleep 1" to the end of
00729         // your command, and to ignore the "read error" IOException.
00730         public static InputStream popenr(String cmd) {
00731                 try {
00732                         return runCommand(cmd).getInputStream();
00733                 } catch (IOException e) {
00734                         return null;
00735                 }
00736         }
00737 
00739         // <P>
00740         // This routine runs the specified command, and returns an OutputStream
00741         // for writing the program's input.
00742         public static OutputStream popenw(String cmd) {
00743                 try {
00744                         return runCommand(cmd).getOutputStream();
00745                 } catch (IOException e) {
00746                         return null;
00747                 }
00748         }
00749 
00751         // <P>
00752         // This routine runs the specified command, and returns a Process
00753         // object so you can do what you like with it.
00754         // <P>
00755         // <B>WARNING:</B> In JDK1.0.2 there is a serious bug in the process
00756         // IO routines, such that reading all the way to the end of a process's
00757         // output will invariably get you an IOException( "read error" ).
00758         // In some cases you will also <B>lose</B> the last bufferload of
00759         // the output.  The workaround is to add a " ; sleep 1" to the end of
00760         // your command, and to ignore the "read error" IOException.
00761         public static Process runCommand(String cmd) throws IOException {
00762                 Runtime runtime = Runtime.getRuntime();
00763                 String[] shCmd = new String[3];
00764                 shCmd[0] = "/bin/sh";
00765                 shCmd[1] = "-c";
00766                 shCmd[2] = cmd;
00767                 return runtime.exec(shCmd);
00768         }
00769 
00771         public static void copyStream(InputStream in, OutputStream out) throws IOException {
00772                 byte[] buf = new byte[4096];
00773                 int len;
00774                 while ((len = in.read(buf)) != -1)
00775                         out.write(buf, 0, len);
00776         }
00777 
00779         public static void copyStream(Reader in, Writer out) throws IOException {
00780                 char[] buf = new char[4096];
00781                 int len;
00782                 while ((len = in.read(buf)) != -1)
00783                         out.write(buf, 0, len);
00784         }
00785 
00787         public static void copyStream(InputStream in, Writer out) throws IOException {
00788                 byte[] buf1 = new byte[4096];
00789                 char[] buf2 = new char[4096];
00790                 int len, i;
00791                 while ((len = in.read(buf1)) != -1) {
00792                         for (i = 0; i < len; ++i)
00793                                 buf2[i] = (char) buf1[i];
00794                         out.write(buf2, 0, len);
00795                 }
00796         }
00797 
00799         public static void copyStream(Reader in, OutputStream out) throws IOException {
00800                 char[] buf1 = new char[4096];
00801                 byte[] buf2 = new byte[4096];
00802                 int len, i;
00803                 while ((len = in.read(buf1)) != -1) {
00804                         for (i = 0; i < len; ++i)
00805                                 buf2[i] = (byte) buf1[i];
00806                         out.write(buf2, 0, len);
00807                 }
00808         }
00809 
00811         public static void dumpStack(PrintStream p) {
00812                 (new Throwable()).printStackTrace(p);
00813         }
00814 
00816         public static void dumpStack() {
00817                 (new Throwable()).printStackTrace();
00818         }
00819 
00821         public static void putAll(Hashtable _dest, Hashtable _src) {
00822         }
00823 
00824 }

Generated on Mon Jan 11 21:19:17 2010 for OpenMobileIS by  doxygen 1.5.4