001: package net.xoetrope.xui;
002:
003: import java.applet.Applet;
004: import java.io.BufferedInputStream;
005: import java.io.BufferedOutputStream;
006: import java.io.BufferedReader;
007: import java.io.File;
008: import java.io.FileInputStream;
009: import java.io.FileNotFoundException;
010: import java.io.FileOutputStream;
011: import java.io.InputStream;
012: import java.io.InputStreamReader;
013: import java.io.OutputStream;
014: import java.io.UnsupportedEncodingException;
015: import java.net.MalformedURLException;
016: import java.net.URL;
017: import java.util.Vector;
018:
019: import java.awt.Frame;
020: import java.awt.Image;
021: import java.awt.Toolkit;
022: import java.awt.Window;
023:
024: import net.xoetrope.debug.DebugLogger;
025: import net.xoetrope.xui.build.BuildProperties;
026: import java.io.IOException;
027: import net.xoetrope.xui.helper.*;
028: import java.util.ResourceBundle;
029: import net.xoetrope.xui.helper.ResourceBundleLoader;
030: import java.util.PropertyResourceBundle;
031: import java.util.Hashtable;
032:
033: /**
034: * A class used to manage access to resources. This class wraps access to
035: * resources such as the files, images, readers and application objects such as
036: * Window and Frame references.<br>
037: * File access is provided so that the resource manager can determine the
038: * source of the file by searching the classpath.
039: * <p>Copyright (c) Xoetrope Ltd., 1998-2003<br>
040: * License: see license.txt
041: * $Revision: 1.30 $
042: */
043: public class XResourceManager {
044: protected static String defaultFile;
045: protected static String defaultEncoding;
046: protected static String basePackageName = XPage.XUI_AWT_PACKAGE;
047: protected URL documentBase = null;
048: protected static Applet app = null;
049: protected static Window appWindow = null;
050: protected static Frame appFrame = null;
051: protected static Vector customClassLoaders = new Vector();
052: protected static ResourceBundleLoader resourceBundleLoader;
053: protected static Hashtable bundles;
054: protected static Hashtable imageCache;
055:
056: /**
057: * Constructs a new resource manager
058: */
059: protected XResourceManager() {
060: defaultEncoding = "UTF8";
061: }
062:
063: /**
064: * Gets an instance of the resource manager
065: * @return the XResourceManager instance
066: * 'deprecated since 1.0.3
067: */
068: public static XResourceManager getInstance() {
069: return XProjectManager.getResourceManager();
070: }
071:
072: /**
073: * Loads an image resource
074: * @param name the image resource name
075: * @return the image
076: */
077: public static Image getImage(String name) {
078: if (name == null)
079: return null;
080:
081: XResourceManager rm = XProjectManager.getResourceManager();
082: URL jarSource = rm.getUrl(name);
083:
084: Image result = null;
085: if (jarSource != null)
086: result = Toolkit.getDefaultToolkit().getImage(jarSource);
087:
088: try {
089: if (result == null) {
090: URL url = new URL(rm.documentBase, name);
091: if (url != null)
092: result = Toolkit.getDefaultToolkit().getImage(url);
093: }
094: } catch (MalformedURLException ex) {
095: URL url = ClassLoader.getSystemResource(name);
096: if (url != null)
097: result = Toolkit.getDefaultToolkit().getImage(url);
098: } finally {
099: if (BuildProperties.DEBUG) {
100: if (result == null)
101: DebugLogger
102: .logWarning("Cannot load image: " + name);
103: }
104: }
105:
106: return result;
107: }
108:
109: /**
110: * Loads an image resource in a background thread
111: * @param holder the component containing to display the image
112: * @param name the image resource name
113: * @return the image
114: */
115: public static synchronized void getImage(XImageHolder holder,
116: String name) {
117: if (name == null)
118: return;
119: // Image result = XResourceManager.getImage( name ); // 114
120: // if ( holder != null ) // 114
121: // ( ( XImageHolder )holder ).setImage( result ); // 114
122: // } // 114
123:
124: final String imageName = name;
125: final SwingWorker worker = new SwingWorker() {
126: Image result = null;
127:
128: public Object construct() {
129: if (imageCache != null)
130: result = (Image) imageCache.get(imageName);
131:
132: if (result == null)
133: result = createImage(getInstance()
134: .getBufferedInputStream(imageName));
135:
136: if ((result != null) && (imageCache != null))
137: imageCache.put(imageName, result);
138:
139: return result; //return value not used by this program
140: }
141:
142: //Runs on the event-dispatching thread.
143: public void finished() {
144: Object holder = getExtraValue();
145: if (holder != null)
146: ((XImageHolder) holder).setImage(result);
147: }
148: };
149: worker.setExtraValue(holder);
150: worker.start();
151: }
152:
153: /**
154: * Sets the startup file and loads the associated resource.
155: * @param file the name of the startup resource file.
156: * @deprecated since 1.0.3 use XProject.setStatupFile
157: */
158: public static void setStartupFile(String fileName) {
159: XProjectManager.getCurrentProject().setStartupFile(fileName);
160:
161: String sp = getStartupParam("CacheImages");
162: if ((sp != null) && !sp.equals("false"))
163: imageCache = new Hashtable();
164: }
165:
166: /**
167: * Gets a startup parameter
168: * @param name the paramenter name
169: * @return the value
170: * @deprecated since 1.0.3 use XProject.getStartupParam
171: */
172: public static String getStartupParam(String name) {
173: return XProjectManager.getCurrentProject()
174: .getStartupParam(name);
175: }
176:
177: /**
178: * Gets a startup parameter
179: * @param name the paramenter name
180: * @return the value
181: * @deprecated since 1.0.3 use XProject.getStartupParamAsInt
182: */
183: public static int getStartupParamAsInt(String name) {
184: return XProjectManager.getCurrentProject()
185: .getStartupParamAsInt(name);
186: }
187:
188: /**
189: * Gets a stream for a resource
190: * @param fileName the resource file name
191: * @return the InputStream
192: */
193: public InputStream getInputStream(String fileName) {
194: FileInputStream result = null;
195: ClassLoader cl = getClass().getClassLoader();
196: if (cl != null) {
197: try {
198: if (BuildProperties.DEBUG) {
199: try {
200: URL url = cl.getResource(fileName);
201: if (url != null)
202: DebugLogger.trace("Opening resource "
203: + url.toExternalForm());
204: } catch (Exception ex3) {
205: DebugLogger.trace("Opening resource file:"
206: + fileName);
207: }
208: }
209: InputStream is = cl.getResourceAsStream(fileName);
210: if (is == null) {
211: int numClassLoaders = customClassLoaders.size();
212: if (numClassLoaders > 0) {
213: for (int i = 0; i < numClassLoaders; i++) {
214: is = ((ClassLoader) customClassLoaders
215: .elementAt(i))
216: .getResourceAsStream(fileName);
217: if (is != null)
218: break;
219: }
220: }
221: if (is == null)
222: DebugLogger
223: .logWarning("File not loaded from classpath: "
224: + fileName);
225: }
226: if (is != null)
227: return is;
228: } catch (Exception ex1) {
229: ex1.printStackTrace();
230: }
231: }
232:
233: // Try a file stream
234: if (BuildProperties.DEBUG)
235: DebugLogger.trace("Opening file:" + fileName);
236: try {
237: return new FileInputStream(fileName);
238: } catch (FileNotFoundException ex) {
239: try {
240: return new FileInputStream(new URL(documentBase,
241: fileName).getFile());
242: } catch (Exception ex2) {
243: try {
244: return ClassLoader
245: .getSystemResourceAsStream(fileName);
246: } catch (Exception ex4) {
247: }
248: }
249: if (BuildProperties.DEBUG) {
250: DebugLogger.logError("File load FAILED: " + fileName);
251: System.out.println(ex.getMessage());
252: return null;
253: }
254: }
255:
256: return null;
257: }
258:
259: /**
260: * Gets a buffered stream for a resource
261: * @param s the resource name
262: * @return the input stream
263: */
264: public BufferedInputStream getBufferedInputStream(String s) {
265: return new BufferedInputStream(getInputStream(s));
266: }
267:
268: /**
269: * Gets a URL for a resource
270: * @param fileName the resource file name
271: * @return the InputStream
272: */
273: public URL getUrl(String fileName) {
274: ClassLoader cl = getClass().getClassLoader();
275: URL resUrl = null;
276: if (cl != null) {
277: try {
278: resUrl = cl.getResource(fileName);
279: if (resUrl == null) {
280: int numClassLoaders = customClassLoaders.size();
281: for (int i = 0; i < numClassLoaders; i++) {
282: resUrl = ((ClassLoader) customClassLoaders
283: .elementAt(i)).getResource(fileName);
284: if (resUrl != null)
285: break;
286: }
287: }
288: if (BuildProperties.DEBUG) {
289: if (resUrl == null)
290: DebugLogger
291: .logWarning("File not loaded from classpath: "
292: + fileName);
293: }
294: } catch (Exception ex1) {
295: ex1.printStackTrace();
296: }
297: }
298:
299: try {
300: if (resUrl == null)
301: resUrl = new URL(documentBase, fileName);
302: } catch (Exception ex) {
303: }
304:
305: return resUrl;
306: }
307:
308: /**
309: * Add a custom class loader. Customer class loaders are sometimes added to
310: * help locate resources in file structures, jars, remote locations etc...
311: * @param c the classloader
312: */
313: public static void addCustomClassLoader(ClassLoader c) {
314: customClassLoaders.addElement(c);
315: }
316:
317: /**
318: * Gets a stream for a file
319: * @param file the file
320: * @return the input stream
321: */
322: public InputStream getInputStream(File file) {
323: try {
324: if (BuildProperties.DEBUG)
325: DebugLogger.trace("Opening file:"
326: + file.getAbsolutePath() + ", exists:"
327: + file.exists());
328:
329: return new FileInputStream(file);
330: } catch (FileNotFoundException ex) {
331: if (BuildProperties.DEBUG)
332: DebugLogger.logError("File open failed:"
333: + file.getAbsolutePath());
334: return null;
335: }
336: }
337:
338: /**
339: * Gets a buffered stream for a file
340: * @param file the file
341: * @return the input stream
342: */
343: public BufferedInputStream getBufferedInputStream(File file) {
344: return new BufferedInputStream(getInputStream(file));
345: }
346:
347: /**
348: * Gets a BufferedReader for a resource
349: * @param file the resource file name
350: * @return the BufferedReader
351: */
352: public static BufferedReader getBufferedReader(String file)
353: throws Exception {
354: InputStream is;
355: BufferedReader r = null;
356: try {
357: is = XProjectManager.getResourceManager().getInputStream(
358: file);
359: r = new BufferedReader(new InputStreamReader(is));
360: } catch (Exception ex) {
361: throw (ex);
362: }
363: return r;
364: }
365:
366: /**
367: * Gets a BufferedReader for a resource
368: * @param file the resource file name
369: * @param encoding the input encoding e.g. "UTF8" or null for the default
370: * encoding (UTF8 unless it has been changed)
371: * @return the BufferedReader
372: */
373: public static BufferedReader getBufferedReader(String file,
374: String encoding) throws Exception {
375: if (encoding == null)
376: encoding = defaultEncoding;
377:
378: InputStream is;
379: BufferedReader r = null;
380: try {
381: is = XProjectManager.getResourceManager().getInputStream(
382: file);
383: if (is != null) {
384: InputStreamReader isr = new InputStreamReader(is,
385: encoding);
386: r = new BufferedReader(isr);
387: }
388: } catch (UnsupportedEncodingException ex) {
389: throw new Exception("Encoding " + encoding
390: + " not supported for file '" + file + "'");
391: } catch (Exception ex) {
392: throw new Exception("Could not access file '" + file + "'");
393: }
394: return r;
395: }
396:
397: /**
398: * Gets a BufferedReader for a resource
399: * @param file the resource file
400: * @param encoding the input encoding e.g. "UTF8" or null for the default
401: * encoding (UTF8 unless it has been changed)
402: * @return the BufferedReader
403: */
404: public static BufferedReader getBufferedReader(File file,
405: String encoding) throws Exception {
406: if (encoding == null)
407: encoding = defaultEncoding;
408:
409: InputStream is;
410: BufferedReader r = null;
411: try {
412: is = XProjectManager.getResourceManager().getInputStream(
413: file);
414: InputStreamReader isr = new InputStreamReader(is, encoding);
415: r = new BufferedReader(isr);
416: } catch (UnsupportedEncodingException ex) {
417: throw new Exception("Encoding " + encoding
418: + " not supported for file '" + file + "'");
419: } catch (Exception ex) {
420: throw new Exception("Could not access file '" + file + "'");
421: }
422: return r;
423: }
424:
425: /**
426: * Gets a stream for a file
427: * @param file the file
428: * @return the output stream
429: */
430: public static OutputStream getOutputStream(String file) {
431: return getOutputStream(file, true);
432: }
433:
434: /**
435: * Gets a buffered stream for a file
436: * @param file the file
437: * @return the output stream
438: */
439: public static BufferedOutputStream getBufferedOutputStream(
440: String file) {
441: return new BufferedOutputStream(getOutputStream(file));
442: }
443:
444: /**
445: * Gets a stream for a file
446: * @param file the file
447: * @param useProjectParent use the projects default file specification to locate the file
448: * @return the output stream
449: */
450: public static OutputStream getOutputStream(String file,
451: boolean useProjectParent) {
452: try {
453: if (XProjectManager.getResourceManager().getClass()
454: .getClassLoader() == null) {
455: return new FileOutputStream(file);
456: } else {
457: if (useProjectParent) {
458: File f = new File(defaultFile);
459: return new FileOutputStream(new File(f, file));
460: } else
461: return new FileOutputStream(new File(file));
462: }
463: } catch (Exception ex) {
464: ex.printStackTrace();
465: return null;
466: }
467: }
468:
469: /**
470: * Gets a buffered stream for a file
471: * @param file the file
472: * @param useProjectParent use the projects default file specification to locate the file
473: * @return the output stream
474: */
475: public static BufferedOutputStream getBufferedOutputStream(
476: String file, boolean useProjectParent) {
477: return new BufferedOutputStream(getOutputStream(file,
478: useProjectParent));
479: }
480:
481: /**
482: * Set the default package name. The default package name is used when
483: * constructing widgets.
484: * @param pn
485: */
486: public static void setPackageName(String pn) {
487: basePackageName = pn;
488: }
489:
490: /**
491: * Get the default package name
492: * @return the default package name
493: */
494: public static String getPackageName() {
495: return basePackageName;
496: }
497:
498: /**
499: * Get the applet document base.
500: * @return the url
501: */
502: public URL getDocumentBase() {
503: return documentBase;
504: }
505:
506: /**
507: * Set/Record the URL from which the applet was loaded
508: * @param u
509: */
510: public void setDocumentBase(URL u) {
511: documentBase = u;
512: }
513:
514: /**
515: * Set tbe applet reference
516: * @param applet
517: */
518: public static void setApplet(Applet applet) {
519: app = applet;
520: }
521:
522: /**
523: * Set the main Frame reference
524: * @param frame
525: */
526: public static void setAppFrame(Frame frame) {
527: appFrame = frame;
528: }
529:
530: /**
531: * Set the main Window reference
532: * @param window
533: */
534: public static void setAppWindow(Window window) {
535: appWindow = window;
536: }
537:
538: /**
539: * Get a reference to the applet object
540: * @return a reference to the applet
541: */
542: public static Applet getApplet() {
543: return app;
544: }
545:
546: /**
547: * Get a areference to the applet's Frame
548: * @return a reference to the frame
549: */
550: public static Frame getAppFrame() {
551: return appFrame;
552: }
553:
554: /**
555: * Get a reference to the application's main Window
556: * @return a reference to the Window
557: */
558: public static Window getAppWindow() {
559: return appWindow;
560: }
561:
562: /**
563: * Reset the reference to the resourceManager singleton
564: */
565: public static void reset() {
566: XProjectManager.resetResourceManager();
567: }
568:
569: // Taken from java.io.File in JDK 1.4
570: protected static String slashify(String path, boolean isDirectory) {
571: String p = path;
572: if (File.separatorChar != '/')
573: p = p.replace(File.separatorChar, '/');
574: if (!p.startsWith("/"))
575: p = "/" + p;
576: if (!p.endsWith("/") && isDirectory)
577: p = p + "/";
578: return p;
579: }
580:
581: /**
582: * Returns an Image, or null if the path was invalid.
583: */
584: protected static Image createImage(InputStream imgStream) {
585: int MAX_IMAGE_SIZE = 75000; //Change this to the size of
586: //your biggest image, in bytes.
587: int count = 0;
588: if (imgStream != null) {
589: byte buf[] = new byte[MAX_IMAGE_SIZE];
590: try {
591: count = imgStream.read(buf);
592: } catch (IOException ieo) {
593: System.err.println("Couldn't read stream from file");
594: }
595:
596: try {
597: imgStream.close();
598: } catch (IOException ieo) {
599: System.err.println("Can't close file");
600: }
601:
602: if (count <= 0) {
603: System.err.println("Empty file");
604: return null;
605: }
606: return Toolkit.getDefaultToolkit().createImage(buf);
607: }
608: return null;
609: }
610:
611: /**
612: * Get the default file encoding (UTF8 unless modified)
613: * @return the encoding
614: */
615: public static String getDefaultEncoding() {
616: return defaultEncoding;
617: }
618:
619: /**
620: * Set the default file encoding (UTF8 unless modified)
621: * @see http://java.sun.com/j2se/1.4.2/docs/guide/intl/encoding.doc.html
622: * @param the encoding e.g. "UTF8" or "ISO-8859-1"
623: */
624: public static void setDefaultEncoding(String encoding) {
625: if (encoding != null)
626: defaultEncoding = encoding;
627: }
628:
629: /**
630: * Set the object to load language resource bundles
631: * @param loader the new loader
632: */
633: public static void setResourceBundleLoader(
634: ResourceBundleLoader loader) {
635: resourceBundleLoader = loader;
636: }
637:
638: /**
639: * Get the resource bundle loader
640: * @return the loader
641: */
642: public static ResourceBundleLoader getResourceBundleLoader() {
643: return resourceBundleLoader;
644: }
645:
646: /**
647: * Get a resource bundle
648: * @param name the unqualified name of the resource bundle
649: */
650: public static ResourceBundle getResourceBundle(String name) {
651: if (bundles == null)
652: bundles = new Hashtable();
653:
654: if (name == null)
655: name = "unnamed";
656:
657: Object res = bundles.get(name);
658: if (res == null) {
659: try {
660: if (resourceBundleLoader != null)
661: res = resourceBundleLoader.getResourceBundle(name);
662:
663: res = new PropertyResourceBundle(getInstance()
664: .getInputStream(name + ".properties"));
665: } catch (Exception ex) {
666: if (BuildProperties.DEBUG)
667: DebugLogger
668: .logWarning("Could not load the ResourceBundle: "
669: + name);
670: return null;
671: }
672: bundles.put(name, res);
673: }
674: return (ResourceBundle) res;
675: }
676:
677: /**
678: * Set the default file/directory specification used to locate files by the
679: * getOutputStream( String file, boolean useProjectParent ) method
680: * @param file the file or directory specification
681: */
682: public void setDefaultFile(String file) {
683: defaultFile = file;
684: }
685: }
|