KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > helpers > Tk


1 /**
2  * $Id: Tk.java 180 2007-03-15 12:56:38Z ssmc $
3  * Copyright 2002-2004 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your option) any
9  * later version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://www.jware.info EMAIL- inquiries@jware.info
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx.helpers;
30
31 import java.lang.reflect.Field JavaDoc;
32 import java.lang.reflect.Method JavaDoc;
33 import java.lang.reflect.Modifier JavaDoc;
34 import java.io.BufferedReader JavaDoc;
35 import java.io.File JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.InputStreamReader JavaDoc;
38 import java.io.OutputStream JavaDoc;
39 import java.net.URL JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Collections JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Locale JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.StringTokenizer JavaDoc;
46
47 import org.apache.tools.ant.Location;
48 import org.apache.tools.ant.Project;
49 import org.apache.tools.ant.taskdefs.Property;
50 import org.apache.tools.ant.types.EnumeratedAttribute;
51 import org.apache.tools.ant.util.LoaderUtils;
52
53 import com.idaremedia.apis.FixtureStarter;
54
55 import com.idaremedia.antx.apis.Requester;
56
57 /**
58  * Collection of independent, common utility algorithms. Snatched from JWare/foundation.
59  * <b>These helper methods <em>must</em> remain independent of other AntX classes.</b>
60  *
61  * @since JWare/AntX 0.1
62  * @author ssmc, &copy;2002-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
63  * @version 0.5
64  * @.safety multiple
65  * @.group impl,helper
66  **/

67
68 public final class Tk
69 {
70     /** A marker for an undefined integer value. **/
71     public static final int NO_INT= Integer.MAX_VALUE;
72
73     /** A marker for an undefined long, timestamp, or date value. **/
74     public static final long NO_NUM= Long.MAX_VALUE;
75
76
77     /** A marker for an undefined long, timestamp, or date value
78      * as a <span class="src">Long</span> object.
79      * @since JWare/AntX 0.5
80      **/

81     public static final Long JavaDoc NO_NUM_NUM= new Long JavaDoc(Long.MAX_VALUE);
82
83
84
85     /**
86      * Checks if the given string is all whitespace. Note: if the given
87      * string is either <i>null</i> or the empty string it's considered
88      * white space.
89      * @param s the string to check
90      * @return <i>true</i> if whitespace (including <i>null</i> and empty)
91      **/

92     public static boolean isWhitespace(String JavaDoc s)
93     {
94         int n=0;
95         if (s==null || (n=s.length())==0) {
96             return true;
97         }
98         for (int i=0; i<n;i++) {
99             if (!Character.isWhitespace(s.charAt(i))) {
100                 return false;
101             }
102         }
103         return true;
104     }
105
106
107
108     /**
109      * Strips the given string of all whitespace characters (as defined
110      * by java method <span class="src">Character.isWhitespace</span>).
111      * Returns original string if no whitespace detected.
112      * @param s the string to check
113      * @return new stripped string of original if no whitespace
114      **/

115     public static String JavaDoc stripWhitespace(String JavaDoc s)
116     {
117         StringBuffer JavaDoc sb=null;
118
119         int n=0;
120         if (s==null || (n=s.length())==0) {
121             return s;
122         }
123
124         char c;
125         for (int i=0; i<n;i++) {
126             c = s.charAt(i);
127             if (!Character.isWhitespace(c)) {
128                 if (sb==null) {
129                     sb= new StringBuffer JavaDoc(n);
130                 }
131                 sb.append(c);
132             }
133         }
134         return (sb!=null) ? sb.toString() : s;
135     }
136
137
138
139     /**
140      * Helper that extracts a list of individual names from a delimited
141      * list of names. Caller assumes ownership of returned (single-threaded)
142      * list.
143      * @param delimitedList delimited list
144      * @param delim the delimiter string
145      **/

146     public final static List JavaDoc splitList(String JavaDoc delimitedList, String JavaDoc delim)
147     {
148         StringTokenizer JavaDoc st= new StringTokenizer JavaDoc(delimitedList,delim);
149         int N= st.countTokens();
150         List JavaDoc l= new ArrayList JavaDoc(Math.max(N,4));
151         while (st.hasMoreTokens()) {
152             l.add(st.nextToken());
153         }
154         return l;
155     }
156
157
158     /**
159      * Variant of {@linkplain #splitList(String,String) splitList(&#8230;)}
160      * that expects a comma-delimited list.
161      * @param delimitedList the comma-delimited list
162      **/

163     public final static List JavaDoc splitList(String JavaDoc delimitedList)
164     {
165         return splitList(delimitedList,",");
166     }
167
168
169     /**
170      * Using specified string, returns best-guess conversion for
171      * an assertable's CV label.
172      **/

173     public static String JavaDoc cvlabelFrom(String JavaDoc iam)
174     {
175         if (iam==null) {
176             iam="";
177         } else if (iam.endsWith(".")) {
178             iam = iam.substring(0,iam.length()-1)+":";
179         } else if (!iam.endsWith(":")){
180             iam += ":";
181         }
182         return iam;
183     }
184
185
186     /**
187      * Converts a string to its US lowercase equivalent. Normalizes
188      * to lowercase the standard way Ant does. If incoming string
189      * is <i>null</i>, this method returns <i>null</i>.
190      * @param s the string to lowercase
191      **/

192     public static String JavaDoc lowercaseFrom(String JavaDoc s)
193     {
194         if (s==null) {
195             return null;
196         }
197         return String.valueOf(s).toLowerCase(Locale.US);
198     }
199
200
201
202     /**
203      * Converts a string to its US lowercase equivalent. Normalizes
204      * to lowercase the standard way Ant does. If incoming string
205      * is <i>null</i> this method returns the string
206      * "<span class="src">null</span>".
207      * @param s the string to lowercase
208      * @since JWare/AntX 0.4
209      **/

210     public static String JavaDoc lowercaseFromNoNull(String JavaDoc s)
211     {
212         return String.valueOf(s).toLowerCase(Locale.US);
213     }
214
215
216
217     /**
218      * Returns a generic system identity string for given object.
219      * @param thing the thing to be stringified (can be <i>null</i>)
220      * @since JWare/AntX 0.4
221      **/

222     public static String JavaDoc identityStringFrom(Object JavaDoc thing)
223     {
224         if (thing==null) {
225             return Strings.NULL;
226         }
227         return thing.getClass().getName()
228             +"@"
229             +System.identityHashCode(thing);
230     }
231
232
233
234     /**
235      * Tries to obtain the result of an object's
236      * <span class="src">toString()</span> handling. If the object's
237      * handling generates an exception (often the case in Ant 1.6+)
238      * this method returns a generic system identity string.
239      * @param thing the thing to be stringified (can be <i>null</i>)
240      * @param P [optional] project for problem logging purposes
241      * @since JWare/AntX 0.4
242      **/

243     public static String JavaDoc stringFrom(Object JavaDoc thing, Project P)
244     {
245         try {
246             return String.valueOf(thing);
247         } catch(RuntimeException JavaDoc rtX) {
248             if (P!=null) {
249                 P.log(rtX.getMessage(),Project.MSG_INFO);
250             }
251             return identityStringFrom(thing);
252         }
253     }
254
255
256     /**
257      * Converts given object to an <code>int</code> or a default value
258      * <code>defi</code> if given object is <i>null</i> or not parseable.
259      * Understands various string representations like octal,
260      * hexidecimal, etc.
261      *
262      * @param o the conversion source
263      * @param defi the default value
264      * @return the value as an integer or <code>defi</code>
265      **/

266     public static int integerFrom(Object JavaDoc o, int defi)
267     {
268         int i= defi;
269         if (o!=null) {
270             try {
271                 if (o instanceof Number JavaDoc) {
272                     i= ((Number JavaDoc)o).intValue();
273                 } else if (o instanceof Boolean JavaDoc) {
274                     i= ((Boolean JavaDoc)o).booleanValue()==true ? 1 : 0;
275                 } else {
276                     i= Integer.decode(o.toString()).intValue();
277                 }
278             }
279             catch (NumberFormatException JavaDoc nx) {/*burp*/}
280         }
281         return i;
282     }
283
284
285     /**
286      * Converts given object to a <code>long</code> or a default value
287      * <code>defl</code> if given object is <i>null</i> or not parseable.
288      *
289      * @param o the conversion source
290      * @param defl the default value
291      * @return the value as a long or <code>defl</code>
292      **/

293     public static long longFrom(Object JavaDoc o, long defl)
294     {
295         long l= defl;
296         if (o!=null) {
297             try {
298                 if (o instanceof Number JavaDoc) {
299                     l= ((Number JavaDoc)o).longValue();
300                 } else if (o instanceof Boolean JavaDoc) {
301                     l= ((Boolean JavaDoc)o).booleanValue()==true ? 1 : 0;
302                 } else {
303                     l= Long.decode(o.toString()).longValue();
304                 }
305             }
306             catch (NumberFormatException JavaDoc nx) {/*burp*/}
307         }
308         return l;
309     }
310
311
312
313     /**
314      * Converts a string value to a number (long|float) or returns a symbolic
315      * {@linkplain Tk#NO_NUM_NUM NO_NUM_NUM} if string could not be converted.
316      * @param valu the numeric value as a string (all of string is read).
317      * @since JWare/AntX 0.5
318      **/

319     public static Number JavaDoc numberFrom(String JavaDoc valu)
320     {
321         Number JavaDoc n = Tk.NO_NUM_NUM;
322         long l = Tk.longFrom(valu,Tk.NO_NUM);
323         if (l!=Tk.NO_NUM) {
324             n = new Long JavaDoc(l);
325         } else {
326             try {
327                 n = Double.valueOf(valu);
328             } catch(NumberFormatException JavaDoc nfx) {/*burp*/}
329         }
330         return n;
331     }
332
333
334
335     /**
336      * Wrapper for Project.toBoolean that handles <i>null</i>
337      * string values.
338      * @param s string to be evaluated (can be <i>null</i>)
339      **/

340     public static boolean booleanFrom(String JavaDoc s)
341     {
342         Boolean JavaDoc B = string2PosBool(s);
343         return (B==null) ? false : B.booleanValue();
344     }
345
346
347     /**
348      * Converts a string form (possibly <i>null</i>) to a positive <i>Boolean</i>
349      * value. Usually used by interactive frontends in testing. Considers any
350      * of the following to be <i>true</i> (case is ignored): "<i>true</i>",
351      * "<i>on</i>", "<i>1</i>", "<i>ok</i>", or "<i>yes</i>". No matches
352      * return <i>false</i>.
353      * @param s stringified value
354      * @return <i>null</i> if <code>s</code> is <i>null</i> or whitespace.
355      * Returns <i>false</i> if s not recognized as a positive boolean
356      **/

357     public static final Boolean JavaDoc string2PosBool(String JavaDoc s)
358     {
359         if (Tk.isWhitespace(s)) {
360             return null;
361         }
362         s= Tk.lowercaseFrom(s);
363         if (s.length()>4) {//=="true".length()
364
return Boolean.FALSE;
365         }
366         if (s.equals("true")) {
367             return Boolean.TRUE;
368         }
369         if (s.equals("1")) {
370             return Boolean.TRUE;
371         }
372         if (s.equals("on")) {
373             return Boolean.TRUE;
374         }
375         if (s.equals("yes")) {
376             return Boolean.TRUE;
377         }
378         if (s.equals("t")) {
379             return Boolean.TRUE;
380         }
381         if (s.equals("ok")) {
382             return Boolean.TRUE;
383         }
384         return Boolean.FALSE;
385     }
386
387
388     /**
389      * Converts a string form (possibly <i>null</i>) to a negative <i>Boolean</i>
390      * value. Usually used by interactive frontends in testing. Considers any
391      * of the following to be <i>false</i> (case is ignored): "<i>false</i>",
392      * "<i>off</i>", "<i>0</i>", "<i>none</i>", or "<i>no</i>".
393      * @param s stringified value
394      * @return <i>null</i> if <code>s</code> is <i>null</i> or whitespace.
395      * Returns <i>true</i> if is not recognized as a negative boolean
396      **/

397     public static final Boolean JavaDoc string2NegBool(String JavaDoc s)
398     {
399         if (Tk.isWhitespace(s)) {
400             return null;
401         }
402         s= Tk.lowercaseFrom(s);
403         if (s.length()>5) {//=="false".length()
404
return Boolean.TRUE;
405         }
406         if (s.equals("false")) {
407             return Boolean.FALSE;
408         }
409         if (s.equals("0")) {
410             return Boolean.FALSE;
411         }
412         if (s.equals("off")) {
413             return Boolean.FALSE;
414         }
415         if (s.equals("no")) {
416             return Boolean.FALSE;
417         }
418         if (s.equals("none")) {
419             return Boolean.FALSE;
420         }
421         if (s.equals("f")) {
422             return Boolean.FALSE;
423         }
424         if (s.equals("notok")) {
425             return Boolean.FALSE;
426         }
427         return Boolean.TRUE;
428     }
429
430
431     /**
432      * Returns the leaf of a class's name. If the leaf partion of the
433      * class name includes the '$' character (as for inner or anonymous
434      * classes), all occurances of '$' are replaced by a '-'
435      * character.
436      * @param cls the class (non-null)
437      **/

438     public static String JavaDoc leafNameFrom(Class JavaDoc cls)
439     {
440         if (cls==null) {
441             throw new IllegalArgumentException JavaDoc("leafFrom- NULL class");
442         }
443         String JavaDoc cn = cls.getName();
444         int i= cn.lastIndexOf('.');
445         if (i != -1) {
446             return cn.substring(i+1).replace('$','-');
447         }
448         return cn;
449     }
450
451
452     /**
453      * Helper to initialize an enumeration value at construction w/o
454      * dealing with check build exception.
455      * @return <i>true</i> if no barfage on <i>setValue</i>
456      **/

457     public static boolean initEnum(EnumeratedAttribute e, String JavaDoc ini)
458     {
459         try {
460             e.setValue(ini);
461         } catch(Exception JavaDoc x) {
462             return false;
463         }
464         return true;
465     }
466
467
468
469     /**
470      * Helper to convert a file URL to a File object's name.
471      **/

472     public static String JavaDoc toFilename(URL JavaDoc url)
473     {
474         if (!url.getProtocol().equals("file")) {
475             if (url.getProtocol().equals("jar")) {
476                 String JavaDoc fn = url.getPath();
477                 if (fn.startsWith("file:")) {
478                     return fn.substring(5).replace
479                         ('/', File.separatorChar).replace('|', ':');
480                 }
481             }
482             return null;
483         }
484         return url.getPath().replace('/', File.separatorChar).replace('|', ':');
485     }
486
487
488
489     /**
490      * Helper to convert a file URL to a Java/IO File object.
491      **/

492     public static File JavaDoc toFile(URL JavaDoc url)
493     {
494         String JavaDoc fn = toFilename(url);
495         return (fn==null) ? null : new File JavaDoc(fn);
496     }
497
498
499
500     /**
501      * Quietly closes an opened input stream. Any I/O or security
502      * exceptions are ignored.
503      * @param input the stream to close (non-null)
504      * @return <i>true</i> if no problems encountered
505      * @since JWare/AntX 0.5
506      **/

507     public static boolean closeQuietly(InputStream JavaDoc input)
508     {
509         try {
510             input.close();
511             return true;
512         } catch(Exception JavaDoc ioX) {
513             return false;
514         }
515     }
516     
517
518
519     /**
520      * Quietly closes an opened output stream. Any I/O or security
521      * exceptions are ignored.
522      * @param output the stream to close (non-null)
523      * @return <i>true</i> if no problems encountered
524      * @since JWare/AntX 0.5
525      **/

526     public static boolean closeQuietly(OutputStream JavaDoc output)
527     {
528         try {
529             output.close();
530             return true;
531         } catch(Exception JavaDoc ioX) {
532             return false;
533         }
534     }
535
536
537
538     /**
539      * Copies the configuration of one property to another. Often used
540      * when calling a target and caller needs to pass on custom property
541      * information to target.
542      * @param source source property (non-null)
543      * @param dest destination property (non-null)
544      **/

545     public static void transferProperty(Property source, Property dest)
546     {
547         if (source==null || dest==null) {
548             throw new IllegalArgumentException JavaDoc("transferProperty- NULL source or dest");
549         }
550
551         if (source.getName()!=null) {//possible if file|rez|prefix
552
dest.setName(source.getName());
553         }
554         if (source.getRefid()!=null) {
555             dest.setRefid(source.getRefid());
556         }
557         if (source.getValue()!=null) {//NB:also covers locations
558
dest.setValue(source.getValue());
559         }
560         if (source.getFile()!=null) {
561             dest.setFile(source.getFile());
562         }
563         if (source.getUrl()!=null) {
564             dest.setUrl(source.getUrl());//copy?
565
}
566         if (source.getResource()!=null) {
567             dest.setResource(source.getResource());
568         }
569         if (source.getEnvironment()!=null) {
570             dest.setEnvironment(source.getEnvironment());
571         }
572         if (source.getPrefix()!=null) {
573             dest.setPrefix(source.getPrefix());
574         }
575         if (source.getClasspath()!=null) {
576             dest.setClasspath(source.getClasspath());
577         }
578
579     }
580
581
582
583     /**
584      * Retrieves a property from either an existing project or the default
585      * Java system object if necessary. The System is only checked if the
586      * project is <i>null</i> or does not contain the named property.
587      * @param P [optional] executing project
588      * @param property the property's name
589      * @return property value (can be <i>null</i>)
590      **/

591     public static final String JavaDoc getTheProperty(Project P, String JavaDoc property)
592     {
593         String JavaDoc value=null;
594
595         if (P!=null) {
596             value = P.getProperty(property);
597         }
598         if (value==null) {
599             value = FixtureStarter.getProperty(property);
600         }
601         return value;
602     }
603
604
605
606     /**
607      * Helper to set a property based on an existing project. If passthru
608      * is <i>true</i> then sets property in velcro mode-- the setting
609      * sticks forever (including to sub-antcalls). Tries to set a System
610      * property if project is <i>null</i>.
611      * @param P [optional] executing project
612      * @param property the property's name (non-null)
613      * @param value the property's value (non-null)
614      * @throws java.lang.SecurityException if not permission to set System
615      * properties
616      **/

617     public static final void setTheProperty(Project P, String JavaDoc property,
618                                             String JavaDoc value, boolean passthru)
619     {
620         if (P!=null) {
621             if (passthru) {
622                 P.setUserProperty(property,value);//like velcro...
623
} else {
624                 P.setNewProperty(property, value);
625             }
626         } else {
627             System.setProperty(property,value);//NB:Need proper perms
628
FixtureStarter.unsetProperty(property);//NB:do *after* system-set OK
629
}
630     }
631
632
633     /**
634      * Makes a Location string human-readable (manageable).
635      * @param l the location to be stringified (non-null)
636      **/

637     public static String JavaDoc shortStringFrom(Location l)
638     {
639         if (l==null || Location.UNKNOWN_LOCATION.equals(l)) {
640             return Strings.UNDEFINED;
641         }
642         String JavaDoc fileline = l.toString();
643         int i= fileline.lastIndexOf(':');
644         if (i>0) {
645             fileline= fileline.substring(0,i);
646         }
647         int N= fileline.length();
648         if (N>41) {
649             fileline= "..."+fileline.substring(N-38);
650         }
651         return fileline;
652     }
653
654
655     /**
656      * Makes a Location string human-readable (manageable) if
657      * application's defaults allow it.
658      * @param prefer <i>true</i> if shortening is allowed
659      * @param l the location to be stringified (non-null)
660      * @since JWare/AntX 0.5
661      **/

662     public static String JavaDoc shortStringFrom(boolean prefer, Location l)
663     {
664         if (prefer) {
665             return shortStringFrom(l);
666         }
667         if (Location.UNKNOWN_LOCATION.equals(l)) {
668             return Strings.UNDEFINED;
669         }
670         return l.toString();
671     }
672
673
674     /**
675      * Resolves any property references in given string iff any
676      * exist. If no references (or string is <i>null</i>), returns
677      * the same string.
678      * @param P [optional] the project from which properties read
679      * @param value the template value (non-null)
680      * @throws NullPointerException if project is <i>null</i>
681      * @since JWare/AntX 0.4
682      **/

683     public static String JavaDoc resolveString(Project P, String JavaDoc value)
684     {
685         if (value==null || P==null) {
686             return value;
687         }
688         if (value.indexOf("${")>=0) {
689             value = P.replaceProperties(value);//expensiv:mem+time
690
}
691         return value;
692     }
693
694
695     /**
696      * Resolves any property or attribute references in given
697      * string iff any exist. If no references (or string is
698      * <i>null</i>), returns the same string. Basically tries to
699      * avoid overhead of <span class="src">Project.replaceProperties</span>
700      * in cases where there are a lot of properties to test.
701      * @param P [optional] the project from which properties read
702      * @param value the template value (non-null)
703      * @param altForm <i>true</i> if we should look for "@{" marker
704      * as well as standard "${" marker (like in macros)
705      * @throws NullPointerException if project is <i>null</i>
706      * @since JWare/AntX 0.4
707      **/

708     public static String JavaDoc resolveString(Project P, String JavaDoc value,
709                                        boolean altForm)
710     {
711         if (value==null || P==null) {
712             return value;
713         }
714         //1. Check for the AntX 0.5 value-URI preferred form first.
715
if (altForm) {
716             //Like Ant's property reference this is not nestable!
717
if (value.indexOf("@(")>=0) {
718                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc(value.length());
719                 char[] cs = getChars(value);
720                 int i,j=0,n;
721                 do {
722                     i= value.indexOf("@(",j);
723                     if (i>=0) {
724                         n= value.indexOf(')',i+2);
725                         if (n<0) {
726                             return value;//*=> is BROKEN; like Ant*
727
}
728                         sb.append(cs,j,i-j);
729                         sb.append("${");
730                         i += 2;
731                         sb.append(cs,i,n-i);
732                         sb.append("}");
733                         j= n+1;
734                     } else {
735                         sb.append(cs,j,cs.length-j);
736                         break;
737                     }
738                 } while(true);
739                 value = sb.toString();
740             }
741         }
742         //2. Check for the AntX 0.4 form second.
743
if (altForm && value.indexOf("@{",0)>=0) {//simple version
744
StringBuffer JavaDoc sb = new StringBuffer JavaDoc(value.length());
745             char[] cs = getChars(value);
746             int i=0,j=0;
747             do {
748                 i= value.indexOf("@{",j);
749                 if (i>=0) {
750                     sb.append(cs,j,i-j);
751                     sb.append("${");
752                     j= i+2;
753                 } else {
754                     sb.append(cs,j,cs.length-j);
755                     break;
756                 }
757             } while (true);
758             value = P.replaceProperties(sb.toString());
759
760         } else {
761             if (value.indexOf("${",0)>=0) {
762                 value = P.replaceProperties(value);
763             }
764         }
765         return value;
766     }
767
768
769     /**
770      * Returns character buffer containing contents of a string.
771      * @since JWare/AntX 0.4
772      * @throws NullPointerException if string is <i>null</i>
773      **/

774     public static char[] getChars(String JavaDoc s)
775     {
776         char[] cs = new char[s.length()];
777         s.getChars(0,s.length(),cs,0);
778         return cs;
779     }
780
781
782
783     /**
784      * Returns a readonly variant of the incoming map, returning
785      * the same map if it is already unmodifiable. If the given
786      * map is <i>null</i>, this method returns <i>null</i> unless
787      * told not to explicitly. This method lessens object creation
788      * when you need to generate lots of readonly views of maps
789      * that might already be readonly.
790      * @param in the map to examine (and possibly wrap)
791      * @param noNull <i>true</i> if null inputs should be mapped
792      * to the standard empty readonly map.
793      * @since JWare/AntX 0.4
794      **/

795     public static Map JavaDoc readonlyFrom(Map JavaDoc in, boolean noNull)
796     {
797         if (in==null) {
798             return noNull ? Collections.EMPTY_MAP : null;
799         }
800         if (in==Collections.EMPTY_MAP) {
801             return in;
802         }
803         if (in.getClass()==READONLYMAP.getClass()) {
804             return in;
805         }
806         return Collections.unmodifiableMap(in);
807     }
808
809
810
811     /**
812      * Tries to run a declared method on a given object. The specified
813      * method should be unique (from combination of name and parameters).
814      * Caller must have permission to set method accessibility. This method
815      * assumes the void signature if either <i>signature</i> or
816      * <i>argv</i> is <i>null</i>. This method does not allow you to run
817      * private <em>inherited</em> methods; however, you can run non-public
818      * methods on the object's immediate class.
819      * @param object object (non-null)
820      * @param methodname name of method (non-null)
821      * @param signature [optional] method signature (ordered,non-null)
822      * @param argv [optional] parameter list (ordered,non-null)
823      * @throws Exception if unable to invoke specified method
824      * @since JWare/AntX 0.4 (from JWare/core 0.7)
825      **/

826     public final static Object JavaDoc invokeit(Object JavaDoc object, String JavaDoc methodname,
827                                         Class JavaDoc[] signature, Object JavaDoc[] argv)
828         throws Exception JavaDoc
829     {
830         Class JavaDoc objectclass = object.getClass();
831         Method JavaDoc method=null;
832         try {
833             method = objectclass.getMethod(methodname,signature);//NB:90+%
834
} catch(NoSuchMethodException JavaDoc nsmx) {
835             try {
836                 method = objectclass.getDeclaredMethod(methodname,signature);//NB:95+%
837
} catch(NoSuchMethodException JavaDoc nsdmx) {
838                 Class JavaDoc parent = objectclass.getSuperclass();//NB:98+%
839
while (parent!=null) {
840                     try {
841                         method = parent.getDeclaredMethod(methodname,signature);
842                         if (Modifier.isPrivate(method.getModifiers())) {//?package too?
843
method=null;
844                         }
845                         break;
846                     } catch(NoSuchMethodException JavaDoc igx) {/*burp*/}
847                     parent = parent.getSuperclass();
848                 }
849                 if (method==null) {
850                     throw nsmx;
851                 }
852             }//2nd
853
}//1st
854

855         boolean is = method.isAccessible();
856         if (!is) {
857             method.setAccessible(true);
858         }
859         try {
860             return method.invoke(object,argv);
861         } finally {
862             if (!is) {
863                 method.setAccessible(false);
864             }
865         }
866     }
867
868
869
870     /**
871      * Utility to extract a named field's information from a class.
872      * Caller must have required security permissions for this method to work.
873      * The returned field may or may not be accessible by caller. Does not
874      * work for interface-bound fields.
875      * @param clazz class under test (non-null)
876      * @param fieldname field interested in finding (non-null)
877      * @return Field information
878      * @throws NoSuchFieldException if field not found in class or superclasses.
879      * @throws IllegalArgumentException if either clazz or fieldname invalid.
880      * @since JWare/AntX 0.5
881      **/

882     public static Field JavaDoc findField(Class JavaDoc clazz, final String JavaDoc fieldname)
883         throws NoSuchFieldException JavaDoc
884     {
885         if (clazz==null || isWhitespace(fieldname)) {
886             throw new IllegalArgumentException JavaDoc("findField- invalid class or fieldname");
887         }
888         do {
889             try {
890                 return clazz.getDeclaredField(fieldname);
891             } catch(NoSuchFieldException JavaDoc nsfx) {/*burp*/}
892             
893             clazz = clazz.getSuperclass();
894             if (clazz==null) {
895                 throw new NoSuchFieldException JavaDoc(fieldname);
896             }
897         } while(true);
898     }
899
900
901
902     /**
903       * Checks if the two given strings are semantically equal, optionally
904       * taking case into account. This method does call <span class="src">a</span>
905       * object's <span class="src">equals</span> method. Two <i>null</i> objects
906       * are considered equal.
907       * @param a first string (primary)
908       * @param b second string
909       * @param caseins <i>true</i> if comparision should ignore case
910       * @return <i>true</i> if equal strings
911       **/

912      public static boolean equalStrings(String JavaDoc a, String JavaDoc b, boolean caseins)
913      {
914          if (a==null) {
915              return b==null;
916          }
917          if (b==null) {
918              return false;
919          }
920          if (a==b) {
921              return true;
922          }
923          return caseins ? a.equalsIgnoreCase(b) : a.equals(b);
924      }
925
926
927      /**
928       * Same as {@linkplain #equalStrings(String, String, boolean) equalStrings}
929       * but with default casesensitive string comparision.
930       **/

931      public static boolean equalStrings(String JavaDoc a, String JavaDoc b)
932      {
933          return equalStrings(a,b,false);
934      }
935
936
937
938
939
940     /**
941      * Helper for obtaining a hash value of object which could be <i>null</i>.
942      * Note that because the JDK has no proper implementation of
943      * <span class="src">equals</span> or <span class="src">hashCode</span> for
944      * Java arrays, we normalize array hashValues to allow the hashCode of
945      * equal arrays (manually determined) to match (thereby not violating
946      * the JLS).
947      **/

948     public static int hashOf(Object JavaDoc o)
949     {
950         if (o==null) {
951             return 191;//?!better choice?!
952
}
953         if (o.getClass().isArray()) {
954             return o.getClass().getComponentType().hashCode();
955         }
956         return o.hashCode();
957     }
958
959
960
961     /**
962      * Looks for an application supplied implementation for a named SPI. This
963      * method first checks the system properties for a property of same name
964      * as SPI class. If not found, this method does the usua
965      * <span class="src">META-INF/services/{spi-class-name}</span> lookup.
966      * @param spiName class name of SPI to implement (non-null)
967      * @param clnt problem handler (non-null)
968      * @return fully qualified class name of matching implementation or <i>null</i>
969      * if no match found.
970      * @since JWare/AntX 0.5
971      **/

972     public final static String JavaDoc loadSpiImpl(String JavaDoc spiName, Requester clnt)
973     {
974         String JavaDoc classname = System.getProperty(spiName);
975         if (!Tk.isWhitespace(classname)) {
976             return classname;
977         }
978
979         String JavaDoc serviceId = "META-INF/services/"+spiName;
980         try {
981             ClassLoader JavaDoc cL = LoaderUtils.getContextClassLoader();
982             InputStream JavaDoc is = null;
983             if (cL!=null) {
984                 is = cL.getResourceAsStream(serviceId);
985             }
986             if (is==null) {
987                 is = ClassLoader.getSystemResourceAsStream(serviceId);
988             }
989             // [From Ant] This code is needed by EBCDIC and other
990
// unicode deficient system although service provider
991
// guidelines seez should be UTF-16 encoding (ssmc)
992
if (is!=null) {
993                 InputStreamReader JavaDoc isr;
994                 try {
995                     isr = new InputStreamReader JavaDoc(is,"UTF-8");
996                 } catch (java.io.UnsupportedEncodingException JavaDoc e) {
997                     isr = new InputStreamReader JavaDoc(is);
998                 }
999                 BufferedReader JavaDoc rd= new BufferedReader JavaDoc(isr);
1000                classname = rd.readLine();
1001                rd.close();
1002
1003                if (!Tk.isWhitespace(classname)) {
1004                    return classname;
1005                }
1006            }
1007        } catch (Exception JavaDoc anyX) {
1008            clnt.problem(anyX.getLocalizedMessage(),Project.MSG_WARN);
1009        }
1010
1011        return null;
1012    }
1013
1014
1015
1016    /**
1017     * Like {@linkplain #loadSpiImpl(String,Requester)
1018     * loadSpiImpl(String,&#8230;)} using the given SPI abstract class's
1019     * name as lookup key.
1020     * @param spiClass SPI class to implement (non-null)
1021     * @param clnt problem handler (non-null)
1022     * @return fully qualified class name of matching implementation or <i>null</i>
1023     * if no match found.
1024     * @since JWare/AntX 0.5
1025     **/

1026    public final static String JavaDoc loadSpiImpl(Class JavaDoc spiClass, Requester clnt)
1027    {
1028        return loadSpiImpl(spiClass.getName(),clnt);
1029    }
1030
1031
1032
1033    /** Prevent This. **/
1034    private Tk()
1035    {
1036    }
1037
1038
1039
1040    /** So we can determine what the JRE's standard
1041     * "unmodifiableMap" class is.
1042     **/

1043    private static final Map JavaDoc READONLYMAP=
1044        Collections.unmodifiableMap(Collections.EMPTY_MAP);
1045}
1046
1047/* end-of-Tk.java */
1048
Popular Tags