Util.java

00001 /*
00002  * Copyright (c) 2003-2006, KNOPFLERFISH project
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following
00007  * conditions are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  *
00012  * - Redistributions in binary form must reproduce the above
00013  *   copyright notice, this list of conditions and the following
00014  *   disclaimer in the documentation and/or other materials
00015  *   provided with the distribution.
00016  *
00017  * - Neither the name of the KNOPFLERFISH project nor the names of its
00018  *   contributors may be used to endorse or promote products derived
00019  *   from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00028  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00030  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00032  * OF THE POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00035 package org.knopflerfish.framework;
00036 
00037 import java.io.*;
00038 import java.util.List;
00039 import java.util.ArrayList;
00040 import java.util.HashMap;
00041 import java.util.Vector;
00042 import java.util.Iterator;
00043 import java.util.Dictionary;
00044 import java.util.Enumeration;
00045 
00046 public class Util {
00053   public static FileTree getFileStorage(String name) {
00054     // See if we have a storage directory
00055     String fwdir = System.getProperty("org.osgi.framework.dir");
00056     if (fwdir == null) {
00057       return null;
00058     }
00059     FileTree dir = new FileTree((new File(fwdir)).getAbsoluteFile(), name);
00060     if (dir != null) {
00061       if (dir.exists()) {
00062         if (!dir.isDirectory()) {
00063           throw new RuntimeException("Not a directory: " + dir);
00064         }
00065       } else {
00066         if (!dir.mkdirs()) {
00067           throw new RuntimeException("Cannot create directory: " + dir);
00068         }
00069       }
00070     }
00071     return dir;
00072   }
00073 
00074 
00084   public static int compareStringVersion(String ver1, String ver2)
00085     throws NumberFormatException {
00086     int i1, i2;
00087     while (ver1 != null || ver2 != null) {
00088       if (ver1 != null) {
00089         int d1 = ver1.indexOf(".");
00090         if (d1 == -1) {
00091           i1 = Integer.parseInt(ver1.trim());
00092           ver1 = null;
00093         } else {
00094           i1 = Integer.parseInt(ver1.substring(0, d1).trim());
00095           ver1 = ver1.substring(d1 + 1);
00096         }
00097       } else {
00098         i1 = 0;
00099       }
00100       if (ver2 != null) {
00101         int d2 = ver2.indexOf(".");
00102         if (d2 == -1) {
00103           i2 = Integer.parseInt(ver2.trim());
00104           ver2 = null;
00105         } else {
00106           i2 = Integer.parseInt(ver2.substring(0, d2).trim());
00107           ver2 = ver2.substring(d2 + 1);
00108         }
00109       } else {
00110         i2 = 0;
00111       }
00112       if (i1 < i2) {
00113         return -1;
00114       }
00115       if (i1 > i2) {
00116         return 1;
00117       }
00118     }
00119     return 0;
00120   }
00121 
00132   public static ArrayList parseEnumeration(String d, String s) {
00133     ArrayList result = new ArrayList();
00134     if (s != null) {
00135       AttributeTokenizer at = new AttributeTokenizer(s);
00136       do {
00137         String key = at.getKey();
00138         if (key == null) {
00139           throw new IllegalArgumentException("Directive " + d + ", unexpected character at: "
00140                                              + at.getRest());
00141         }
00142         if (!at.getEntryEnd()) {
00143           throw new IllegalArgumentException("Directive " + d + ", expected end of entry at: "
00144                                              + at.getRest());
00145         }
00146         int i = Math.abs(binarySearch(result, strComp, key) + 1);
00147         result.add(i, key);
00148       } while (!at.getEnd());
00149       return result;
00150     } else {
00151       return null;
00152     }
00153   }
00154 
00171   public static Iterator parseEntries(String a, String s, boolean single, boolean unique, boolean single_entry) {
00172     ArrayList result = new ArrayList();
00173     if (s != null) {
00174       AttributeTokenizer at = new AttributeTokenizer(s);
00175       do {
00176         ArrayList keys = new ArrayList();
00177         HashMap params = new HashMap();
00178         String key = at.getKey();
00179         if (key == null) {
00180           throw new IllegalArgumentException("Definition, " + a + ", expected key at: " + at.getRest());
00181         }
00182         if (!single) {
00183           keys.add(key);
00184           while ((key = at.getKey()) != null) {
00185             keys.add(key);
00186           }
00187         }
00188         String param;
00189         while ((param = at.getParam()) != null) {
00190           List old = (List)params.get(param);
00191           boolean is_directive = at.isDirective();
00192           if (old != null && unique) {
00193             throw new IllegalArgumentException("Definition, " + a + ", duplicate " +
00194                                                (is_directive ? "directive" : "attribute") +
00195                                                ": " + param);
00196           }
00197           String value = at.getValue();
00198           if (value == null) {
00199             throw new IllegalArgumentException("Definition, " + a + ", expected value at: " + at.getRest());
00200           }
00201           if (is_directive) {
00202             // NYI Handle directives and check them
00203             // This method has become very ugly, please rewrite.
00204           }
00205           if (unique) {
00206             params.put(param, value);
00207           } else {
00208             if (old == null) {
00209               old = new ArrayList();
00210               params.put(param, old);
00211             }
00212             old.add(value);
00213           }
00214         }
00215         if (at.getEntryEnd()) {
00216           if (single) {
00217             params.put("key", key);
00218           } else {
00219             params.put("keys", keys);
00220           }
00221           result.add(params);
00222         } else {
00223           throw new IllegalArgumentException("Definition, " + a + ", expected end of entry at: " + at.getRest());
00224         }
00225         if (single_entry && !at.getEnd()) {
00226           throw new IllegalArgumentException("Definition, " + a + ", expected end of single entry at: " + at.getRest());
00227         }
00228       } while (!at.getEnd());
00229     }
00230     return result.iterator();
00231   }
00232 
00239   static byte[] readResource(String name) throws IOException  {
00240     byte[] buf = new byte[1024];
00241 
00242     InputStream           in = Main.class.getResourceAsStream(name);
00243     ByteArrayOutputStream bout = new ByteArrayOutputStream();
00244     int n;
00245     while ((n = in.read(buf)) > 0) {
00246       bout.write(buf, 0, n);
00247     }
00248     try { in.close(); } catch (Exception ignored) { } 
00249 
00250     return bout.toByteArray();
00251   }
00252 
00257   protected static String  WHITESPACE = " \t\n\r";
00258   
00263   protected static char   CITCHAR    = '"';
00264   
00265   
00273   public static String [] splitwords(String s) {
00274     return splitwords(s, WHITESPACE);
00275   }
00276 
00284   public static String [] splitwords(String s, String whiteSpace) {
00285     return splitwords(s, whiteSpace, CITCHAR);
00286   }
00287 
00288   
00305   public static String [] splitwords(String s, 
00306                                      String whiteSpace,
00307                                      char   citChar) {
00308     boolean       bCit  = false;        // true when inside citation chars.
00309     Vector        v     = new Vector(); // (String) individual words after splitting
00310     StringBuffer  buf   = new StringBuffer(); 
00311     int           i     = 0; 
00312     
00313     while(i < s.length()) {
00314       char c = s.charAt(i);
00315 
00316       if(bCit || whiteSpace.indexOf(c) == -1) {
00317         // Build up word until we breaks on either a citation char or whitespace
00318         if(c == citChar) {
00319           bCit = !bCit;
00320         } else {
00321           if(buf == null) {
00322             buf = new StringBuffer();
00323           }
00324           buf.append(c);
00325         }
00326         i++;
00327       } else {  
00328         // found whitespace or end of citation, append word if we have one
00329         if(buf != null) {
00330           v.addElement(buf.toString());
00331           buf = null;
00332         }
00333 
00334         // and skip whitespace so we start clean on a word or citation char
00335         while((i < s.length()) && (-1 != whiteSpace.indexOf(s.charAt(i)))) {
00336           i++;
00337         }
00338       }
00339     }
00340 
00341     // Add possible remaining word
00342     if(buf != null) {
00343       v.addElement(buf.toString());
00344     }
00345     
00346     // Copy back into an array
00347     String [] r = new String[v.size()];
00348     v.copyInto(r);
00349     
00350     return r;
00351   }
00352 
00380   public static String replace(final String s, 
00381                                final String v1, 
00382                                final String v2) {
00383     
00384     // return quick when nothing to do
00385     if(s == null 
00386        || v1 == null 
00387        || v2 == null 
00388        || v1.length() == 0 
00389        || v1.equals(v2)) {
00390       return s;
00391     }
00392 
00393     int ix       = 0;
00394     int v1Len    = v1.length(); 
00395     int n        = 0;
00396 
00397     // count number of occurances to be able to correctly size
00398     // the resulting output char array
00399     while(-1 != (ix = s.indexOf(v1, ix))) {
00400       n++;
00401       ix += v1Len;
00402     }
00403 
00404     // No occurances at all, just return source string
00405     if(n == 0) {
00406       return s;
00407     }
00408 
00409     // Set up an output char array of correct size
00410     int     start  = 0;
00411     int     v2Len  = v2.length();
00412     char[]  r      = new char[s.length() + n * (v2Len - v1Len)];
00413     int     rPos   = 0;
00414 
00415     // for each occurance, copy v2 where v1 used to be
00416     while(-1 != (ix = s.indexOf(v1, start))) {
00417       while(start < ix) r[rPos++] = s.charAt(start++);
00418       for(int j = 0; j < v2Len; j++) {
00419         r[rPos++] = v2.charAt(j);
00420       }
00421       start += v1Len;
00422     }
00423 
00424     // ...and add all remaining chars
00425     ix = s.length(); 
00426     while(start < ix) r[rPos++] = s.charAt(start++);
00427     
00428     // ..ouch. this hurts.
00429     return new String(r);
00430   }
00431 
00432 
00433   public static String getContent(File f) {
00434     DataInputStream in = null;
00435     try {
00436       in = new DataInputStream(new FileInputStream(f));
00437       return in.readUTF();
00438     } catch (IOException ignore) {
00439     } finally {
00440       if (in != null) {
00441         try {
00442           in.close();
00443         } catch (IOException ignore) { }
00444       }
00445     }
00446     return null;
00447   }
00448 
00449   public static void putContent(File f, String content) throws IOException {
00450     putContent(f, content, true);
00451   }
00452   
00453   public static void putContent(File f, String content, boolean useUTF8) throws IOException {
00454     DataOutputStream out = null;
00455     try {
00456       out = new DataOutputStream(new FileOutputStream(f));
00457       if (useUTF8) {
00458         out.writeUTF(content);
00459       } else {
00460         out.writeChars(content);
00461       }
00462     } finally {
00463       if (out != null) {
00464         out.close();
00465       }
00466     }
00467   }
00468 
00469   public interface Comparator {
00470     public int compare(Object a, Object b);
00471   }
00472 
00479   static public void sort(List a, Comparator cf, boolean bReverse) {
00480     sort(a, 0, a.size() - 1, cf, bReverse ? -1 : 1);
00481   }
00482   
00486   static void sort(List a, int lo0, int hi0, Comparator cf, int k) {
00487     int lo = lo0;
00488     int hi = hi0;
00489     Object mid;
00490     
00491     if ( hi0 > lo0) {
00492       
00493       mid = a.get( ( lo0 + hi0 ) / 2 );
00494       
00495       while( lo <= hi ) {
00496         while( ( lo < hi0 ) && ( k * cf.compare(a.get(lo), mid) < 0 )) {
00497           ++lo;
00498         }
00499         
00500         while( ( hi > lo0 ) && ( k * cf.compare(a.get(hi), mid ) > 0 )) {
00501           --hi;
00502         }
00503         
00504         if( lo <= hi ) {
00505           swap(a, lo, hi);
00506           ++lo;
00507           --hi;
00508         }
00509       }
00510       
00511       if( lo0 < hi ) {
00512         sort( a, lo0, hi, cf, k );
00513       }
00514       
00515       if( lo < hi0 ) {
00516         sort( a, lo, hi0, cf, k );
00517       }
00518     }
00519   }
00520   
00521   private static void swap(List a, int i, int j) {
00522     Object tmp  = a.get(i); 
00523     a.set(i, a.get(j));
00524     a.set(j, tmp);
00525   }
00526 
00527 
00539   public static int binarySearch(List pl, Comparator c, Object p) {
00540     int l = 0;
00541     int u = pl.size()-1;
00542 
00543     while (l <= u) {
00544       int m = (l + u)/2;
00545       int v = c.compare(pl.get(m), p);
00546       if (v > 0) {
00547         l = m + 1;
00548       } else if (v < 0) {
00549         u = m - 1;
00550       } else {
00551         return m;
00552       }
00553     }
00554     return -(l + 1);  // key not found.
00555   }
00556 
00557   static final Comparator strComp = new Comparator() {
00567       public int compare(Object oa, Object ob) throws ClassCastException {
00568         String a = (String)oa;
00569         String b = (String)ob;
00570         return a.compareTo(b);
00571       }
00572     };
00573 
00574   private static final byte encTab[] = {
00575     0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,
00576     0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x61,0x62,0x63,0x64,0x65,0x66,
00577     0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
00578     0x77,0x78,0x79,0x7a,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2b,0x2f
00579   };
00580 
00581   private static final byte decTab[]={
00582     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00583     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00584     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
00585     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
00586     -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
00587     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
00588     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00589     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
00590   };
00591 
00592 
00593   public static String base64Encode(String s) throws IOException {
00594     return encode(s.getBytes(), 0);
00595   }
00596 
00602   //  public static String encode(byte[] in) throws IOException {
00603   //    return encode(in, 0);
00604   //  }
00605 
00612   public static String encode(byte[] in, int len) throws IOException {
00613     ByteArrayOutputStream baos = null;
00614     ByteArrayInputStream bais = null;
00615     try {
00616       baos = new ByteArrayOutputStream();
00617       bais = new ByteArrayInputStream(in);
00618       encode(bais, baos, len);
00619       // ASCII byte array to String
00620       return(new String(baos.toByteArray()));
00621     } finally {
00622       if (baos != null) baos.close();
00623       if (bais != null) bais.close();
00624     }
00625   }
00626 
00627   public static void encode(InputStream in, OutputStream out, int len) 
00628     throws IOException {
00629 
00630     // Check that length is a multiple of 4 bytes
00631     if(len%4!=0)
00632       throw new IllegalArgumentException("Length must be a multiple of 4");
00633 
00634     // Read input stream until end of file
00635     int bits=0;
00636     int nbits=0;
00637     int nbytes=0;
00638     int b;
00639 
00640     while( (b=in.read()) != -1) {
00641       bits=(bits<<8)|b;
00642       nbits+=8;
00643       while(nbits>=6) {
00644         nbits-=6;
00645         out.write(encTab[0x3f&(bits>>nbits)]);
00646         nbytes ++;
00647         // New line
00648         if (len !=0 && nbytes>=len) {
00649           out.write(0x0d);
00650           out.write(0x0a);
00651           nbytes -= len;
00652         }
00653       }
00654     }
00655 
00656     switch(nbits) {
00657     case 2:
00658       out.write(encTab[0x3f&(bits<<4)]);
00659       out.write(0x3d); // 0x3d = '='
00660       out.write(0x3d);
00661       break;
00662     case 4:
00663       out.write(encTab[0x3f&(bits<<2)]);
00664       out.write(0x3d);
00665       break;
00666     }
00667 
00668     if (len != 0) {
00669       if (nbytes != 0) {
00670         out.write(0x0d);
00671         out.write(0x0a);
00672       }
00673       out.write(0x0d);
00674       out.write(0x0a);
00675     }
00676   }
00677 
00678 
00684   static void mergeDictionaries(Dictionary target, Dictionary extra) {
00685     for (Enumeration e = extra.keys();
00686          e.hasMoreElements(); ) {
00687       Object key = e.nextElement();
00688       if (target.get(key) == null) {
00689         target.put(key, extra.get(key));
00690       }
00691     }
00692   }
00693 
00694 
00698   public static boolean filterMatch(String filter, String s) {
00699     return patSubstr(s.toCharArray(), 0, filter.toCharArray(), 0);
00700   }
00701 
00702 
00705   private static boolean patSubstr(char[] s, int si, char[] pat, int pi) {
00706     if (pat.length-pi == 0) 
00707       return s.length-si == 0;
00708     if (pat[pi] == '*') {
00709       pi++;
00710       for (;;) {
00711         if (patSubstr( s, si, pat, pi))
00712           return true;
00713         if (s.length-si == 0)
00714           return false;
00715         si++;
00716       }
00717     } else {
00718       if (s.length-si==0){
00719         return false;
00720       }
00721       if(s[si]!=pat[pi]){
00722         return false;
00723       }
00724       return patSubstr( s, ++si, pat, ++pi);
00725     }
00726   }
00727 
00728 
00729 
00730 }
00731 
00732 
00736 class AttributeTokenizer {
00737 
00738   String s;
00739   int length;
00740   int pos = 0;
00741 
00742   AttributeTokenizer(String input) {
00743     s = input;
00744     length = s.length();
00745   }
00746 
00747   String getWord() {
00748     skipWhite();
00749     boolean backslash = false;
00750     boolean quote = false;
00751     StringBuffer val = new StringBuffer();
00752     int end = 0;
00753   loop:
00754     for (; pos < length; pos++) {
00755       if (backslash) {
00756         backslash = false;
00757         val.append(s.charAt(pos));
00758       } else {
00759         char c = s.charAt(pos);
00760         switch (c) {
00761         case '"':
00762           quote = !quote;
00763           end = val.length();
00764           break;
00765         case '\\':
00766           backslash = true;
00767           break;
00768         case ',': case ':': case ';': case '=':
00769           if (!quote) {
00770             break loop;
00771           }
00772           // Fall through
00773         default:
00774           val.append(c);
00775           if (!Character.isWhitespace(c)) {
00776             end = val.length();
00777           }
00778           break;
00779         }
00780       }
00781     }
00782     if (quote || backslash || end == 0) {
00783       return null;
00784     }
00785     char [] res = new char [end];
00786     val.getChars(0, end, res, 0);
00787     return new String(res);
00788   }
00789 
00790   String getKey() {
00791     if (pos >= length) {
00792       return null;
00793     }
00794     int save = pos;
00795     if (s.charAt(pos) == ';') {
00796       pos++;
00797     }
00798     String res = getWord();
00799     if (res != null) {
00800       if (pos == length) {
00801         return res;
00802       }
00803       char c = s.charAt(pos);
00804       if (c == ';' || c == ',') {
00805         return res;
00806       }
00807     }
00808     pos = save;
00809     return null;
00810   }
00811 
00812   String getParam() {
00813     if (pos == length || s.charAt(pos) != ';') {
00814       return null;
00815     }
00816     int save = pos++;
00817     String res = getWord();
00818     if (res != null) {
00819       if (pos < length && s.charAt(pos) == '=') {
00820         return res;
00821       } if (pos + 1 < length && s.charAt(pos) == ':' && s.charAt(pos+1) == '=') {
00822         return res;
00823       }
00824     }
00825     pos = save;
00826     return null;
00827   }
00828 
00829   boolean isDirective() {
00830     if (pos + 1 < length && s.charAt(pos) == ':') {
00831       pos++;
00832       return true;
00833     } else {
00834       return false;
00835     }
00836   }
00837     
00838   String getValue() {
00839     if (s.charAt(pos) != '=') {
00840       return null;
00841     }
00842     int save = pos++;
00843     skipWhite();
00844     String val = getWord();
00845     if (val == null) {
00846       pos = save;
00847       return null;
00848     }
00849     return val;
00850   }
00851 
00852   boolean getEntryEnd() {
00853     int save = pos;
00854     skipWhite();
00855     if (pos == length) {
00856       return true;
00857     } else if (s.charAt(pos) == ',') {
00858       pos++;
00859       return true;
00860     } else {
00861       pos = save;
00862       return false;
00863     }
00864   }
00865 
00866   boolean getEnd() {
00867     int save = pos;
00868     skipWhite();
00869     if (pos == length) {
00870       return true;
00871     } else {
00872       pos = save;
00873       return false;
00874     }
00875   }
00876 
00877   String getRest() {
00878     String res = s.substring(pos).trim();
00879     return res.length() == 0 ? "<END OF LINE>" : res;
00880   }
00881 
00882   private void skipWhite() {
00883     for (; pos < length; pos++) {
00884       if (!Character.isWhitespace(s.charAt(pos))) {
00885         break;
00886       }
00887     }
00888   }
00889 
00890 
00891 
00892 }

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