KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > init > UISMBundle


1 /**
2  * $Id: UISMBundle.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.init;
30
31 import java.io.ByteArrayInputStream JavaDoc;
32 import java.io.File JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.net.MalformedURLException JavaDoc;
35 import java.net.URL JavaDoc;
36 import java.util.Properties JavaDoc;
37 import java.util.PropertyResourceBundle JavaDoc;
38
39 import org.apache.tools.ant.AntClassLoader;
40 import org.apache.tools.ant.BuildException;
41 import org.apache.tools.ant.Project;
42 import org.apache.tools.ant.types.Path;
43 import org.apache.tools.ant.types.Reference;
44 import org.apache.tools.ant.util.ClasspathUtils;
45
46 import com.idaremedia.antx.AntX;
47 import com.idaremedia.antx.AntXFixture;
48 import com.idaremedia.antx.AssertableDataType;
49 import com.idaremedia.antx.FixtureComponent;
50 import com.idaremedia.antx.apis.AntLibFriendly;
51 import com.idaremedia.antx.apis.BuildError;
52 import com.idaremedia.antx.apis.ProblemHandler;
53 import com.idaremedia.antx.helpers.InputFileLoader;
54 import com.idaremedia.antx.helpers.Tk;
55 import com.idaremedia.antx.ownhelpers.CustomLoaderFactoryMethod;
56 import com.idaremedia.antx.ownhelpers.LocalTk;
57 import com.idaremedia.antx.parameters.CustomLoaderEnabled;
58 import com.idaremedia.antx.parameters.FlexExistenceEnabled;
59
60 /**
61  * Maintains the definition of a properties-based resource bundle for a UIStringManager.
62  * Usually defined &lt;msgsbundle&gt;. UISMBundles are also used by all tasks
63  * that generate UIStringManagers from a UISMSources.
64  * <p>
65  * UISMBundles are usually defined as part of a build-iterations's fixture and
66  * referred-to by target-based configuration tasks.
67  * <p>
68  * <b>Examples:</b><pre>
69  * &lt;msgsbundle id="compile.msgs"
70  * resource="resources/msgs/compile-msgs.properties"/&gt;
71  *
72  * &lt;msgsbundle id="subbuild.msgs" mustexist="yes"
73  * file="${build.root}/${module.id}/build-msgs.properties"/&gt;
74  * </pre>
75  *
76  * @since JWare/AntX 0.2
77  * @author ssmc, &copy;2002-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
78  * @version 0.5
79  * @.safety single
80  * @.group api,infra
81  * @.caveat For URL-based data files, assumes the Ant runtime is authorized on
82  * the targeted server(s).
83  **/

84
85 public class UISMBundle extends AssertableDataType
86     implements FixtureComponent, CustomLoaderEnabled, FlexExistenceEnabled,
87                UISMSource, Cloneable JavaDoc, AntLibFriendly
88 {
89     /**
90      * Initializes a new UISMBundle instance. The new instance is equivalent
91      * to an empty properties file.
92      **/

93     public UISMBundle()
94     {
95         super(AntX.uism);
96     }
97
98
99     /**
100      * Initializes a new UISMBundle instance with its 'mustExist' option
101      * predefined. Useful constructor when this item is embedded in another
102      * object.
103      * @see #setMustExist setMustExist(&#8230;)
104      **/

105     public UISMBundle(boolean mustExist)
106     {
107         super(AntX.uism);
108         m_failIfMissing = mustExist;
109     }
110
111
112     /**
113      * Capture our identifier for feedback since types don't always
114      * get correct location information.
115      **/

116     public void setId(String JavaDoc id)
117     {
118         m_Id= id;
119     }
120
121
122     /**
123      * Tries to return an unique identifier for this bundle. Looks
124      * for a build-script identifier({@linkplain #setId setId}); if none
125      * found, creates a unique string based on type's class name and
126      * instance reference.
127      **/

128     public final String JavaDoc getId()
129     {
130         if (m_Id!=null) {
131             return m_Id;
132         }
133         if (isReference()) {
134             return getBundleRef().getId();
135         }
136         return super.getId();
137     }
138
139
140     /**
141      * Tells this bundle it is part of another object's implementation.
142      * This bundle will defer resource loading to the controlling object's
143      * class loader if it exists.
144      * @param cLFactory bundle controller (non-null)
145      * @since JWare/AntX 0.4
146      **/

147     public void setController(CustomLoaderFactoryMethod cLFactory)
148     {
149         m_cLFactory = cLFactory;
150     }
151
152
153     /**
154      * Sets whether this bundle will fail if it cannot locate and
155      * load its strings from the specified location.
156      * @param mustExist <i>true</i> if resource bundle must be loaded
157      **/

158     public void setMustExist(boolean mustExist)
159     {
160         if (isReference()) {
161             throw tooManyAttributes();
162         }
163         m_failIfMissing = mustExist;
164         edited();
165     }
166
167
168     /**
169      * Returns <i>true</i> if the resource bundle specified for this item
170      * must exist (or a default must be specified in system properties).
171      * Defaults to <i>false</i>.
172      **/

173     public boolean getMustExist()
174     {
175         if (isReference()) {
176             return getBundleRef().getMustExist();
177         }
178         return m_failIfMissing;
179     }
180
181
182
183     /**
184      * Returns a new Properties object based on this bundle's properties
185      * contents. Never returns <i>null</i>.
186      * @param errH [optional] callback if load problem occurs
187      * @throws BuildException if unable to load resource-bundle information.
188      **/

189     public synchronized Properties JavaDoc newProperties(ProblemHandler errH)
190     {
191         if (isReference()) {
192             return getBundleRef().newProperties(errH);
193         }
194         if (!triedLoadOnce()) {
195             tryLoadSource(errH);
196         }
197         try {
198             Properties JavaDoc p= new Properties JavaDoc();
199             p.load(new ByteArrayInputStream JavaDoc(getBytes()));
200             return p;
201         } catch(IOException JavaDoc iox) {
202             throw new BuildError(iox.getMessage());//NB:never
203
}
204     }
205
206
207
208
209     /**
210      * Returns a new PropertyResourceBundle based on this bundle's properties
211      * contents. Never returns <i>null</i>.
212      * @param errH [optional] callback if load problem occurs
213      * @throws BuildException if unable to load resource-bundle information.
214      **/

215     public synchronized PropertyResourceBundle JavaDoc newPropertyBundle(ProblemHandler errH)
216     {
217         if (isReference()) {
218             PropertyResourceBundle JavaDoc rb = getBundleRef().newPropertyBundle(errH);
219
220             if (!m_isInited) {//NB:mark as installed if 1st time and OK
221
m_isInited=true;
222             }
223             return rb;
224         }
225
226         if (!triedLoadOnce()) {
227             tryLoadSource(errH);
228         }
229         try {
230             return new PropertyResourceBundle JavaDoc(new ByteArrayInputStream JavaDoc(getBytes()));
231         } catch(IOException JavaDoc iox) {
232             throw new BuildError(iox.getMessage());//NB:never
233
}
234     }
235
236
237     /**
238      * Returns a clone of this UISMBundle. Supports passing of UISMBundles between
239      * project and sub-projects. If this bundle is a reference to another object,
240      * that object's clone method is invoked.
241      * @since JWare/AntX 0.3
242      **/

243     public Object JavaDoc clone()
244     {
245         if (isReference()) {
246             return getBundleRef().clone();
247         }
248         try {
249             UISMBundle copy = (UISMBundle)super.clone();
250             if (m_file!=null) {
251                 copy.m_file = new File JavaDoc(m_file.getPath());
252             }
253             if (m_URL!=null) {
254                 copy.m_URL= new URL JavaDoc(m_URL.toString());
255             }
256             if (m_bytes.length>0) {
257                 byte[] newbytes = new byte[m_bytes.length];
258                 System.arraycopy(m_bytes,0,newbytes,0,m_bytes.length);
259                 copy.setBytes(newbytes);
260             }
261             return copy;
262         } catch (MalformedURLException JavaDoc mfx) {
263             throw new BuildException(mfx);
264         } catch(CloneNotSupportedException JavaDoc clnx) {
265             throw new Error JavaDoc(uistrs().get(AntX.CLONE_BROKEN_MSGID));
266         }
267     }
268
269 // ---------------------------------------------------------------------------------------
270
// Datasources as URLs
271
// ---------------------------------------------------------------------------------------
272

273     /**
274      * Sets this holder's resource bundle's location as a URL.
275      * @param urlstr URL string representation (non-null)
276      * @throws BuildException if this bundle is reference or another
277      * bundle or if another source has already been specified.
278      **/

279     public void setURL(String JavaDoc urlstr)
280     {
281         require_(urlstr!=null,"setURL- nonzro url");
282         if (isReference()) {
283             throw tooManyAttributes();
284         }
285         checkNewDatasource();
286         m_URLstr= urlstr;
287         m_URL= null;
288         edited(UISMTk.BY_URL);
289     }
290
291
292
293     /**
294      * Returns this holder's resource bundle's URL location. Returns
295      * <i>null</i> if never set or was set to an invalid URL string.
296      **/

297     public final URL JavaDoc getURL()
298     {
299         if (isReference()) {
300             return getBundleRef().getURL();
301         }
302         if (m_URL!=null) {
303             return m_URL;
304         }
305         if (m_URLstr!=null) {
306             try {
307                 m_URL = new URL JavaDoc(m_URLstr);
308             } catch(MalformedURLException JavaDoc mfx) {
309                 log(uistrs().get("task.uism.err.bad.url",m_URLstr), Project.MSG_ERR);
310             }
311         }
312         return m_URL;
313     }
314
315
316     /**
317      * Opens URL connection, copies returned output to this bundle as raw
318      * properties information. This method assumes URL's contents are a
319      * standard Properties file.
320      * @param url the url to be read (non-null)
321      * @return <i>true</i> if read and stored successfully
322      * @see InputFileLoader
323      **/

324     protected final boolean copyURLStreamToSelf(URL JavaDoc url)
325     {
326         boolean copied=false;
327         try {
328             setBytes(new InputFileLoader().loadURL(url));//NB:assumin iso8851-1
329
log("Copied UISM URL("+url+") to bundle",Project.MSG_DEBUG);
330             copied=true;
331         } catch(IOException JavaDoc iox) {
332             log(uistrs().get("task.uism.err.loading.url",url.toString()),
333                 Project.MSG_ERR);
334         }
335         return copied;
336     }
337
338
339     /**
340      * Shared grunt work for specify-by-url or specifiy-by-resource.
341      * @param url the url to be checked and/or loaded (non-null)
342      **/

343     protected final boolean handleThisURL(URL JavaDoc url)
344     {
345         File JavaDoc f = Tk.toFile(url);
346         if (f==null) {
347             return copyURLStreamToSelf(url);
348         } else if (f.canRead()) {
349             boolean OK = copyURLStreamToSelf(url);
350             if (OK) {
351                 m_file = f;
352             }
353             return OK;
354         } else {
355             log(uistrs().get("task.uism.err.bad.file",f.getPath()),
356                 Project.MSG_ERR);
357         }
358         return false;
359     }
360
361
362     /**
363      * Checks if this UISM bundle has been specified as a URL. If it has
364      * tries to load the URL's raw contents to this bundle holder.
365      * @return <i>true</i> if url was defined and was loaded.
366      **/

367     protected final boolean handleURL()
368     {
369         URL JavaDoc url = getURL();
370
371         return (url!=null) ? handleThisURL(url) : false;
372     }
373
374 // ---------------------------------------------------------------------------------------
375
// Datasources as Files
376
// ---------------------------------------------------------------------------------------
377

378     /**
379      * Sets this holder's resource bundle's location as a file.
380      * @param fp the readable file path (non-null)
381      * @throws BuildException if this bundle is reference or another
382      * bundle or if another source has already been specified.
383      **/

384     public void setFile(String JavaDoc fp)
385     {
386         require_(fp!=null,"setFil- nonzro filpath");
387         if (isReference()) {
388             throw tooManyAttributes();
389         }
390         checkNewDatasource();
391         m_file= getProject().resolveFile(fp);
392         edited(UISMTk.BY_FILE);
393     }
394
395
396     /**
397      * Returns this holder's resource bundle's file location. Returns
398      * <i>null</i> if never set (or determined from other datasource type).
399      **/

400     public final File JavaDoc getFile()
401     {
402         if (isReference()) {
403             return getBundleRef().getFile();
404         }
405         return m_file;
406     }
407
408
409     /**
410      * Checks if this holder's resource bundle has been specified as a file.
411      * If it has, tries to load the file's raw contents to this bundle holder.
412      * @return <i>true</i> if file was defined and was loaded.
413      **/

414     protected final boolean handleFile()
415     {
416         File JavaDoc f = getFile();
417         if (f!=null) {
418             if (f.canRead()) {
419                 try {
420                     URL JavaDoc furl = AntXFixture.fileUtils().getFileURL(f);
421                     boolean OK = copyURLStreamToSelf(furl);
422                     if (OK) {
423                         m_URL = furl;
424                     }
425                     return OK;
426                 } catch(MalformedURLException JavaDoc mfx) {
427                     log(uistrs().get("task.uism.err.bad.file",f.getPath()),
428                         Project.MSG_ERR);
429                 }
430             } else {
431                 log(uistrs().get("task.uism.err.bad.file",f.getPath()),
432                     Project.MSG_ERR);
433             }
434         }
435         return false;
436     }
437
438 // ---------------------------------------------------------------------------------------
439
// Datasources as Resources
440
// ---------------------------------------------------------------------------------------
441

442     /**
443      * Creates and returns a new classpath element from this
444      * bundle's custom resource search path. Returned path must be
445      * configured by caller.
446      **/

447     public Path createClassPath()
448     {
449         return getCLSpi(true).createClasspath();
450     }
451
452
453     /**
454      * Returns this bundle's custom classpath. Returns <i>null</i> if
455      * never created.
456      **/

457     public final Path getClassPath()
458     {
459         if (isReference()) {
460             return getBundleRef().getClassPath();
461         }
462         if (m_CLspi!=null) {
463             return m_CLspi.getClasspath();
464         }
465         return null;
466     }
467
468
469     /**
470      * Adds a new classpath element to this bundle's custom classpath.
471      * @param classpath additional classpath element (non-null)
472      */

473     public void setClassPath(Path classpath)
474     {
475         require_(classpath!=null,"setClzpath- nonzro path");
476         getCLSpi(false).setClasspath(classpath);
477     }
478
479
480     /**
481      * Adds a new classpath by-reference to this bundle's custom
482      * classpath.
483      * @param r reference to existing classpath item (non-null)
484      */

485     public void setClassPathRef(Reference r)
486     {
487         require_(r!=null,"setClzpathRef- nonzro ref");
488         getCLSpi(false).setClasspathref(r);
489     }
490
491
492     /**
493      * Tells this bundle to use an existing classloader to
494      * search for and load resources. If loader does not exist,
495      * and this bundle has a custom class path, a new class loader
496      * will be stored under this reference's id.
497      * @param r reference to an existing ClassLoader (non-null)
498      * @since JWare/AntX 0.4
499      **/

500     public void setLoaderRef(Reference r)
501     {
502         require_(r!=null,"setLodrRef- nonzro ref");
503         getCLSpi(false).setLoaderRef(r);
504     }
505
506
507     /**
508      * Returns this bundle's own loader identifier based on
509      * its <em>current</em> configuration. Returns <i>null</i>
510      * if never defined (directly or indirectly through a classpath
511      * reference).
512      * @since JWare/AntX 0.4
513      **/

514     public String JavaDoc getLoaderRefId()
515     {
516         if (isReference()) {
517             return getBundleRef().getLoaderRefId();
518         }
519         if (m_CLspi!=null) {
520             return m_CLspi.getClassLoadId();
521         }
522         return null;
523     }
524
525
526     /**
527      * Sets this holder's resource bundle's as a classpath-based
528      * resource base name.
529      **/

530     public void setResource(String JavaDoc rsrc)
531     {
532         require_(rsrc!=null,"setSysRsrc- nonzro rsrc");
533         if (isReference()) {
534             throw tooManyAttributes();
535         }
536         checkNewDatasource();
537         m_resource = rsrc;
538         edited(UISMTk.BY_REZ);
539     }
540
541
542     /**
543      * Returns this holder's resource bundle's as a classpath-based
544      * resource base name. Returns <i>null</i> if never set.
545      **/

546     public final String JavaDoc getResource()
547     {
548         if (isReference()) {
549             return getBundleRef().getResource();
550         }
551         return m_resource;
552     }
553
554
555     /**
556      * Shared grunt work for specify-by-resource.
557      * @param rsrc the resource to be checked and/or loaded (non-null)
558      **/

559     protected final boolean handleThisResource(String JavaDoc rsrc)
560     {
561         boolean OK=false;
562
563         AntClassLoader AcL=null;
564         ClassLoader JavaDoc cL=null;
565         URL JavaDoc url;
566         Project P= getProject();
567
568         if (m_cLFactory!=null) {
569             cL = m_cLFactory.getClassLoader();
570         }
571         if (cL==null) {
572             if (P!=null && m_CLspi!=null) {
573                 AcL = (AntClassLoader)m_CLspi.getClassLoader();
574                 cL = AcL;
575             } else {
576                 cL = this.getClass().getClassLoader();
577             }
578         }
579         if (cL==null) {
580             url = LocalTk.getSystemResource(rsrc, P);//?ever?
581
} else {
582             url = cL.getResource(rsrc);
583         }
584
585         if (url!=null) {
586             OK = handleThisURL(url);
587             if (OK) {
588                 m_URL = url;
589             }
590         } else {
591             log(uistrs().get("task.uism.err.bad.resource",rsrc),
592                 Project.MSG_ERR);
593         }
594
595         if (AcL!=null) {
596             if (m_CLspi.getClassLoadId()==null) {
597                 AcL.cleanup();
598             }
599             AcL=null;
600         }
601         return OK;
602     }
603
604
605     /**
606      * Checks if the UISM bundle has been specified as a class or system resource.
607      * If it has, tries to load the resource's raw contents to this bundle holder.
608      * @return <i>true</i> if resource defined, read, and loaded successfully.
609      **/

610     protected final boolean handleResource()
611     {
612         boolean OK=false;
613         String JavaDoc rsrc = getResource();
614
615         if (rsrc!=null) {
616             OK = handleThisResource(rsrc);
617         }
618
619         return OK;
620     }
621
622 // ---------------------------------------------------------------------------------------
623
// Loading Properties-Bundle to this in-memory holder:
624
// ---------------------------------------------------------------------------------------
625

626     /**
627      * Returns the UISMBundle referenced by this instance.
628      * @throws BuildException is this object is not a reference.
629      **/

630     protected final UISMBundle getBundleRef()
631     {
632         return (UISMBundle)getCheckedRef(UISMBundle.class,"msgsbundle");
633     }
634
635
636     /**
637      * Returns <i>true</i> if we've tried to load this bundle's raw
638      * properties information at least once.
639      **/

640     protected final boolean triedLoadOnce()
641     {
642         return m_isInited;
643     }
644
645
646     /**
647      * Returns this bundles custom class path helper. Never returns
648      * <i>null</i>.
649      * @.safety single
650      * @since JWare/AntX 0.4
651      **/

652     private final ClasspathUtils.Delegate getCLSpi(boolean subel)
653     {
654         if (isReference()) {
655             if (subel) {
656                 throw noChildrenAllowed();
657             }
658             throw tooManyAttributes();
659         }
660         if (m_CLspi==null) {
661             m_CLspi= ClasspathUtils.getDelegate(this);
662             edited();
663         }
664         return m_CLspi;
665     }
666
667
668     /**
669      * Tries to load the raw properties resource bundle into this memory
670      * holder. Loading order has following precedence:<ol>
671      * <li>File attribute</li>
672      * <li>Resource attribute</li>
673      * <li>URL attribute</li>
674      * <li>Resource named in AntX.DEFAUL_UISTRS_BUNDLE_PROP property</li>
675      * </ol>
676      **/

677     private void tryLoadSource(ProblemHandler errH) throws BuildException
678     {
679         if (!m_isInited) {
680             if (!handleFile() &&
681                 !handleResource() &&
682                 !handleURL()) {
683
684                 String JavaDoc defaultRsrc = null;
685                 Project P= getProject();
686                 if (P!=null) {
687                     defaultRsrc = P.getProperty(AntX.DEFAULT_UISTRS_BUNDLE_PROP);
688                 }
689                 if (defaultRsrc==null) {
690                     defaultRsrc = System.getProperty(AntX.DEFAULT_UISTRS_BUNDLE_PROP);
691                 }
692                 if (defaultRsrc!=null) {
693                     m_isInited = handleThisResource(defaultRsrc);
694                 }
695                 if (!m_isInited) {
696                     String JavaDoc ermsg = uistrs().get("task.uism.err.invalid.setup");
697                     log(ermsg, Project.MSG_ERR);
698                     if (errH!=null) {
699                         errH.problem(ermsg, Project.MSG_ERR);
700                     }
701                     if (getMustExist()) {
702                         throw new BuildException(ermsg);
703                     }
704                 }
705             }
706             m_isInited=true;
707         }
708     }
709
710
711     /**
712      * Called whenever a source-attribute is defined; ensure at most
713      * one source is defined.
714      **/

715     private void checkNewDatasource()
716     {
717         if (m_Nsources>0) {
718             throw UISMTk.tooManySources();
719         }
720         m_Nsources++;
721     }
722
723
724     /**
725      * Returns this bundle's raw properties definition information. Never
726      * returns <i>null</i> but can be empty byte array if never loaded
727      * or was unable to loade.
728      **/

729     private byte[] getBytes()
730     {
731         return m_bytes;
732     }
733
734
735     /**
736      * Changes this bundle's raw properties definition information.
737      * @.safety single
738      **/

739     protected final void setBytes(byte[] bytes)
740     {
741         require_(bytes!=null,"setBytes- nonzro byts");
742         m_bytes = bytes;
743     }
744
745
746     private File JavaDoc m_file;
747     private String JavaDoc m_URLstr;
748     private URL JavaDoc m_URL;
749     private String JavaDoc m_resource;
750     private ClasspathUtils.Delegate m_CLspi;//NB:lazy-inited
751
private boolean m_failIfMissing;//NB:=> empty bundle
752
private CustomLoaderFactoryMethod m_cLFactory;//NB:=>standalone-type
753

754     private boolean m_isInited;
755     private byte[] m_bytes= new byte[0];//NB:=> like empty bundle!
756
private int m_Nsources=0;//NB:number of sources defined (0..1)
757
private String JavaDoc m_Id;
758 }
759
760 /* end-of-UISMBundle.java */
761
Popular Tags