001 /*
002 * Copyright (c) Holger Pfaff - http://pfaff.ws
003 *
004 * This software maybe used for any purpose provided the
005 * above copyright notice is retained. It is supplied as is.
006 * No warranty expressed or implied - Use at your own risk.
007 */
008
009 import java.util.Vector;
010 import java.util.Hashtable;
011 import java.util.Enumeration;
012 import java.util.PropertyResourceBundle;
013
014 /**
015 * (#)Util.java
016 * @author Holger Pfaff
017 * @version 3.2 19-Mar-2004<br><br>
018 *
019 * Various utility routines for use with j-awt
020 */
021
022 public class Util {
023
024 /**
025 * Find index of Object within array
026 *
027 * @return index or -1 on failure
028 *
029 * @param array the array to search within
030 * @param obj the object to search for
031 */
032 static int indexOf(Object[] array, Object obj) {
033 return indexOf(array, obj, 0);
034 }
035
036 /**
037 * Find index of Object within array
038 * starting at a specified index
039 *
040 * @return index or -1 on failure
041 *
042 * @param array the array to search within
043 * @param obj the object to search for
044 * @param start index to start from
045 */
046 static int indexOf(Object[] array, Object obj, int start) {
047 if(array != null) {
048 for(int i = start; i < array.length; ++i) {
049 if(array[i].equals(obj)) return i;
050 }
051 }
052 return -1;
053 }
054
055 /**
056 * Convert an arbitrary array of Objects into a Vector
057 *
058 * @return resulting Vector
059 *
060 * @param array the array to convert
061 */
062 static Vector array2Vector(Object[] array) {
063 return array2Vector(array, 0);
064 }
065
066 /**
067 * Convert an arbitrary array of Objects into a Vector
068 * starting at a specified index
069 *
070 * @return resulting Vector
071 *
072 * @param array the array to convert
073 * @param start the index to start from
074 */
075 static Vector array2Vector(Object[] array, int start) {
076 Vector v = new Vector();
077 if(array != null) {
078 for(int i = start; i < array.length; ++i) {
079 v.addElement(array[i]);
080 }
081 }
082 return v;
083 }
084
085 /**
086 * Convert an arbitrary Enumeration into an Array of Strings
087 *
088 * @return resulting String array
089 *
090 * @param e the enumeration to convert
091 */
092 public static String[] enum2Array(Enumeration e) {
093 Vector v = enum2Vector(e);
094 String[] r = new String[v.size()];
095 for(int i =0; i < r.length; ++i) {
096 r[i] = v.elementAt(i).toString();
097 }
098 return r;
099 }
100
101 /**
102 * Convert an arbitrary Enumeration into a Vector
103 *
104 * @return resulting Vector
105 *
106 * @param e the enumeration to convert
107 */
108 public static Vector enum2Vector(Enumeration e) {
109 Vector r = new Vector();
110 while(e.hasMoreElements()) {
111 r.addElement(e.nextElement());
112 }
113 return r;
114 }
115
116 /**
117 * Convert an arbitrary Enumeration into a single String
118 * separated with a specified delimiter character
119 *
120 * @return resulting String
121 *
122 * @param e the enumeration to convert
123 * @param dl the delimiter to use
124 */
125 public static String enum2String(Enumeration e, String dl) {
126 String r = e.hasMoreElements() ? e.nextElement().toString() : "";
127 while(e.hasMoreElements()) {
128 r += dl + e.nextElement().toString();
129 }
130 return r;
131 }
132
133 /**
134 * Invoke an arbitrary method of an Object<br>
135 * <code>Util.invoke(myclass, "printx hello world")</code> would call
136 * method printx of object myclass with "printx" "hello" "world" as arguments.
137 * Method printx should be defined as <code>public void printx(Vector argv)</code>
138 *
139 * @param o class instance to use
140 * @param argv the argument vector as blank separated string
141 */
142 static void invoke(Object o, String argv) {
143 invoke(o, new StringSplitter(argv, " ", false).toVector());
144 }
145
146 /**
147 * Invoke an arbitrary method of an Object<br>
148 *
149 * @param o class instance to use
150 * @param argv the arguments as a Vector list
151 */
152 static void invoke(Object o, Vector argv) {
153 try {
154 Class argt[] = {Vector.class};
155 Object args[] = {argv};
156 o.getClass().getMethod((String) argv.elementAt(0), argt).invoke(o, args);
157 } catch(Exception x) {
158 Debug.debug(Util.class, x);
159 }
160 }
161
162 /**
163 * Get contents of a properties file as a Hashtable. Tries to load
164 * <name>.properties first then <name>_<lang>.properties. If that fails
165 * try to load default lang "en". Depending on JVM used the properties
166 * file has to reside within the jar archive of the current applet
167 *
168 * @return Hashtable containing key/value pairs from properties files
169 *
170 * @param name name of properties to load
171 * @param lang language of properties to load
172 */
173 static Hashtable getResourceHash(String name, String lang) {
174 Hashtable h = new Hashtable();
175 Util.putResourceHash(name, h, h);
176 if(Util.putResourceHash(name + "_" + lang, h, null) == null) {
177 Util.putResourceHash(name + "_en", h, null);
178 }
179 return h;
180 }
181
182 /**
183 * Convert content of a specific property file to a hashtable. This method
184 * get called by getResourceHash() to actually do the work.
185 *
186 * @return Hashtable containing key/value pairs from properties file
187 *
188 * @param name name of properties to load
189 * @param h hashtable to put values in
190 * @param dh default hashtable to return in case of errors
191 */
192 static Hashtable putResourceHash(String name, Hashtable h, Hashtable dh) {
193 try {
194 PropertyResourceBundle r = new PropertyResourceBundle(Util.class.getResourceAsStream(name + ".properties"));
195 for(Enumeration e = r.getKeys(); e.hasMoreElements(); ) {
196 String k = (String) e.nextElement();
197 h.put(k, r.getObject(k));
198 }
199 return h;
200 } catch(Exception x) {
201 Debug.debug(Util.class, x);
202 return dh;
203 }
204 }
205
206 /**
207 * Do shell-style pattern matching for ?, \, [], and * characters.
208 * Negate a class with ^ is also possible. Char ranges should work fine
209 * as long as you stick to ascii chars. As java uses Unicode all other
210 * ranges might not work as expected.
211 * Original version written in C by Rich $alz.
212 *
213 * @return 0 = false, no match 1 = true, matches 2 = abort, no match, invalid syntax
214 *
215 * @param text text to find pattern in
216 * @param pattern pattern to search for
217 *
218 */
219 static int match(String text, String pattern) {
220 char[] T = text.toCharArray();
221 char[] P = pattern.toCharArray();
222 int t = 0; // current pointer within <text>
223 int p = 0; // current pointer within <pattern>
224 int m = 0; // does it match (0,1,2)
225 for(; p < P.length; t++, p++) {
226 if(t == T.length && P[p] != '*') return 2;
227 switch(P[p]) {
228 case '\\': // literal match with following character. Fallthrough
229 p++;
230 default: // match one char
231 if(p == P.length || T[t] != P[p]) return 0;
232 continue;
233 case '?': // match anything
234 continue;
235 case '*': // match everything
236 while(++p < P.length && P[p] == '*') continue; // consecutive stars act just like one
237 if(p == P.length) return 1; // trailing star matches everything
238 while(t < T.length) { // match the rest recursive
239 if((m = match(text.substring(t++), pattern.substring(p))) != 0) return m;
240 }
241 return 2;
242 case '[': // match char ranges (beware: java uses unicode!)
243 char l = ' ';
244 int r = p < P.length - 2 && P[p + 1] == '^' ? 1 : 0;
245 if(r == 1) p++; // inverted matching ?
246 for(m = 0; ++p < P.length && P[p] != ']'; l = P[p]) {
247 if(P[p] == '-' ? ++p <= P.length && T[t] <= P[p] && T[t] >= l : T[t] == P[p]) m = 1;
248 }
249 if(m == r) return 0;
250 continue;
251 }
252 }
253 return t == T.length ? 1 : 0;
254 }
255 }