001/* ---------------------------------------------------------------------------- 002 The Kiwi Toolkit - A Java Class Library 003 Copyright (C) 1998-2004 Mark A. Lindner 004 005 This library is free software; you can redistribute it and/or 006 modify it under the terms of the GNU General Public License as 007 published by the Free Software Foundation; either version 2 of the 008 License, or (at your option) any later version. 009 010 This library is distributed in the hope that it will be useful, 011 but WITHOUT ANY WARRANTY; without even the implied warranty of 012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 General Public License for more details. 014 015 You should have received a copy of the GNU General Public License 016 along with this library; if not, write to the Free Software 017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 02111-1307, USA. 019 020 The author may be contacted at: mark_a_lindner@yahoo.com 021 ---------------------------------------------------------------------------- 022 $Log: ResourceManager.java,v $ 023 Revision 1.17 2004/05/05 21:22:45 markl 024 Comment header updates. 025 026 Revision 1.16 2003/01/19 09:42:04 markl 027 Throw exception if null or empty string passed in for resource name. 028 029 Revision 1.15 2002/08/11 09:57:21 markl 030 Version number change. 031 032 Revision 1.14 2002/08/11 09:48:54 markl 033 Added setter methods for resource paths. 034 035 Revision 1.13 2001/12/25 10:12:35 markl 036 Javadoc typo fix. 037 038 Revision 1.12 2001/08/28 20:28:21 markl 039 Fixes to defer access to Toolkit for situations where no X Display is 040 available. 041 042 Revision 1.11 2001/06/26 06:12:23 markl 043 Fixed javadoc. 044 045 Revision 1.10 2001/06/26 06:11:36 markl 046 Added getStream() method. 047 048 Revision 1.9 2001/03/12 03:16:50 markl 049 *** empty log message *** 050 051 Revision 1.8 1999/05/10 08:54:11 markl 052 Added color theme support. 053 054 Revision 1.7 1999/05/03 09:34:17 markl 055 Fixed javadoc comment. 056 057 Revision 1.6 1999/04/19 05:32:41 markl 058 Added LocaleData bundle support and bundle buffering. 059 060 Revision 1.5 1999/01/18 08:12:38 markl 061 fixed bugs in ResourceBundle methods 062 063 Revision 1.4 1999/01/17 08:32:57 markl 064 Added Locale awareness and new getResourceBundle() method. 065 066 Revision 1.3 1999/01/17 00:58:33 markl 067 Added ResourceBundle support 068 069 Revision 1.2 1999/01/10 03:55:05 markl 070 added GPL header & RCS tag 071 ---------------------------------------------------------------------------- 072*/ 073 074package kiwi.util; 075 076import java.awt.Image; 077import java.io.*; 078import java.util.*; 079import java.net.URL; 080import javax.swing.*; 081 082import kiwi.ui.*; 083 084/** This class provides base functionality for a resource manager; it includes 085 * support for the caching of images and sounds, and provides convenience 086 * methods for retrieving other types of resources. All resources are 087 * retrieved relative to an <i>anchor class</i>. The resource manager assumes 088 * that images will be within an "images" directory, textures within a 089 * "textures" directory, sounds within a "sounds" directory, URL-based 090 * references within an "html" directory, properties within a "properties" 091 * directory, resource bundles within a "locale" directory, and color theme 092 * definitions within a "themes" directory. All of these paths, however, are 093 * configurable. 094 * <p> 095 * The Kiwi library includes a resource library of its own; the resources 096 * within the library are accessible through the internal 097 * <code>ResourceManager</code>, a reference to which may be obtained via 098 * a call to <code>kiwi.util.KiwiUtils.getResourceManager()</code>. Links to 099 * index files of some of the resources are listed below: 100 * <p><ul> 101 * <li><a href="../../images_index.html">images</a> 102 * <li><a href="../../textures_index.html">textures</a> 103 * <li><a href="../../locale_index.html">resource bundles</a> 104 * <li><a href="../../sounds_index.html">sounds</a> 105 * </ul> 106 * 107 * @see kiwi.util.ResourceLoader 108 * 109 * @author Mark Lindner 110 */ 111 112public class ResourceManager 113 { 114 private Hashtable images, textures, sounds, icons, bundles; 115 private ResourceLoader loader; 116 private static ResourceManager kiwiResourceManager = null; 117 private static final String respathSeparator = "/"; 118 /** The default base path for images. */ 119 public static final String IMAGE_PATH = "images"; 120 /** The default base path for audio clips. */ 121 public static final String SOUND_PATH = "sounds"; 122 /** The default base path for HTML documents. */ 123 public static final String HTML_PATH = "html"; 124 /** The default base path for color themes. */ 125 public static final String THEME_PATH = "themes"; 126 /** The default base path for textures. */ 127 public static final String TEXTURE_PATH = "textures"; 128 /** The default base path for property files. */ 129 public static final String PROPERTY_PATH = "properties"; 130 /** The default base path for message bundles. */ 131 public static final String RESBUNDLE_PATH = "locale"; 132 /** The file extension for resource bundles. */ 133 public static final String RESBUNDLE_EXT = ".msg"; 134 /** The file extension for color themes. */ 135 public static final String THEME_EXT = ".thm"; 136 137 /** The base path for images. */ 138 protected String imagePath; 139 /** The base path for audio clips. */ 140 protected String soundPath; 141 /** The base path for HTML documents. */ 142 protected String htmlPath; 143 /** The base path for color themes. */ 144 protected String themePath; 145 /** The base path for textures. */ 146 protected String texturePath; 147 /** The base path for property files. */ 148 protected String propertyPath; 149 /** The base path for message bundles. */ 150 protected String resbundlePath; 151 152 /** Construct a new <code>ResourceManager</code>. 153 * 154 * @param clazz The resource anchor class. 155 */ 156 157 public ResourceManager(Class clazz) 158 { 159 loader = new ResourceLoader(clazz); 160 images = new Hashtable(); 161 icons = new Hashtable(); 162 textures = new Hashtable(); 163 sounds = new Hashtable(); 164 bundles = new Hashtable(); 165 166 setImagePath(IMAGE_PATH); 167 setSoundPath(SOUND_PATH); 168 setHTMLPath(HTML_PATH); 169 setThemePath(THEME_PATH); 170 setTexturePath(TEXTURE_PATH); 171 setPropertyPath(PROPERTY_PATH); 172 setResourceBundlePath(RESBUNDLE_PATH); 173 } 174 175 /* 176 */ 177 178 private String _checkPath(String path) 179 { 180 if(path == null) 181 return(respathSeparator); 182 183 return(path.endsWith(respathSeparator) ? path 184 : (path + respathSeparator)); 185 } 186 187 /** Set an alternate path (relative to the anchor class) for image and icon 188 * resources. 189 * 190 * @param path The new resource path. 191 * @since Kiwi 1.3.4 192 */ 193 194 public void setImagePath(String path) 195 { 196 imagePath = _checkPath(path); 197 } 198 199 /** Set an alternate path (relative to the anchor class) for audio clip 200 * resources. 201 * 202 * @param path The new resource path. 203 * @since Kiwi 1.3.4 204 */ 205 206 public void setSoundPath(String path) 207 { 208 soundPath = _checkPath(path); 209 } 210 211 /** Set an alternate path (relative to the anchor class) for HTML document 212 * resources. 213 * 214 * @param path The new resource path. 215 * @since Kiwi 1.3.4 216 */ 217 218 public void setHTMLPath(String path) 219 { 220 htmlPath = _checkPath(path); 221 } 222 223 /** Set an alternate path (relative to the anchor class) for theme 224 * resources. 225 * 226 * @param path The new resource path. 227 * @since Kiwi 1.3.4 228 */ 229 230 public void setThemePath(String path) 231 { 232 themePath = _checkPath(path); 233 } 234 235 /** Set an alternate path (relative to the anchor class) for texture 236 * resources. 237 * 238 * @param path The new resource path. 239 * @since Kiwi 1.3.4 240 */ 241 242 public void setTexturePath(String path) 243 { 244 texturePath = _checkPath(path); 245 } 246 247 /** Set an alternate path (relative to the anchor class) for property 248 * resources. 249 * 250 * @param path The new resource path. 251 * @since Kiwi 1.3.4 252 */ 253 254 public void setPropertyPath(String path) 255 { 256 propertyPath = _checkPath(path); 257 } 258 259 /** Set an alternate path (relative to the anchor class) for message bundle 260 * resources. 261 * 262 * @param path The new resource path. 263 * @since Kiwi 1.3.4 264 */ 265 266 public void setResourceBundlePath(String path) 267 { 268 resbundlePath = _checkPath(path); 269 } 270 271 /** Get a reference to the internal Kiwi resource manager. 272 */ 273 274 public static ResourceManager getKiwiResourceManager() 275 { 276 if(kiwiResourceManager == null) 277 kiwiResourceManager = new ResourceManager(kiwi.ResourceAnchor.class); 278 279 return(kiwiResourceManager); 280 } 281 282 /** Clear the image resource cache. */ 283 284 public void clearImageCache() 285 { 286 images.clear(); 287 } 288 289 /** Clear the icon resource cache. */ 290 291 public void clearIconCache() 292 { 293 icons.clear(); 294 } 295 296 /** Clear the texture resource cache. */ 297 298 public void clearTextureCache() 299 { 300 textures.clear(); 301 } 302 303 /** Clear the audio clip resource cache. */ 304 305 public void clearAudioClipCache() 306 { 307 sounds.clear(); 308 } 309 310 /** Clear the resource bundle cache. */ 311 312 public void clearResourceBundleCache() 313 { 314 bundles.clear(); 315 } 316 317 /** Retrieve an internal <code>Icon</code> resource. This is a convenience 318 * method that makes a call to <code>getImage()</code> and then wraps the 319 * result in a Swing <code>ImageIcon</code> object. 320 * 321 * @param name The name of the resource. 322 * @return An <code>Icon</code> for the specified image. If an icon for this 323 * image has previously been constructed, the cached copy is returned. 324 * 325 * @exception kiwi.util.ResourceNotFoundException If the resource was not 326 * found. 327 * @see javax.swing.ImageIcon 328 */ 329 330 public Icon getIcon(String name) 331 { 332 Icon icon = (Icon)icons.get(name); 333 if(icon != null) return(icon); 334 335 icon = new ImageIcon(getImage(name)); 336 icons.put(name, icon); 337 338 return(icon); 339 } 340 341 /** Retrieve an internal <code>Image</code> resource. If the named image has 342 * previously been loaded, a cached copy is returned. 343 * 344 * @param name The name of the resource. 345 * @return The <code>Image</code> object representing the resource. 346 * @exception kiwi.util.ResourceNotFoundException If the resource was not 347 * found. 348 */ 349 350 public Image getImage(String name) 351 { 352 checkResourceName(name); 353 354 Image image = (Image)images.get(name); 355 if(image != null) return(image); 356 357 String path = imagePath + name; 358 image = loader.getResourceAsImage(path); 359 if(image == null) 360 throw(new ResourceNotFoundException(path)); 361 images.put(name, image); 362 363 return(image); 364 } 365 366 /** Retrieve an internal texture resource. If the named texture has 367 * previously been loaded, a cached copy is returned. 368 * 369 * @param name The name of the resource. 370 * @return The <code>Image</code> object representing the resource. 371 * @exception kiwi.util.ResourceNotFoundException If the resource was not 372 * found. 373 */ 374 375 public Image getTexture(String name) 376 { 377 checkResourceName(name); 378 379 Image image = (Image)textures.get(name); 380 if(image != null) return(image); 381 382 String path = texturePath + name; 383 image = loader.getResourceAsImage(path); 384 if(image == null) 385 throw(new ResourceNotFoundException(path)); 386 textures.put(name, image); 387 388 return(image); 389 } 390 391 /** Retrieve an internal <code>URL</code> resource. 392 * 393 * @param name The name of the resource. 394 * @return A URL for the resource. 395 * @exception kiwi.util.ResourceNotFoundException If the resource was not 396 * found. 397 */ 398 399 public URL getURL(String name) 400 { 401 checkResourceName(name); 402 403 String path = htmlPath + name; 404 URL url = loader.getResourceAsURL(path); 405 if(url == null) 406 throw(new ResourceNotFoundException(path)); 407 408 return(url); 409 } 410 411 /** Retrieve an internal <code>AudioClip</code> resource. If the named sound 412 * has previously been loaded, a cached copy is returned. 413 * 414 * @param name The name of the resource. 415 * @return The <code>AudioClip</code> object representing the resource. 416 * @exception kiwi.util.ResourceNotFoundException If the resource was not 417 * found. 418 */ 419 420 public AudioClip getSound(String name) 421 { 422 checkResourceName(name); 423 424 String path = soundPath + name; 425 AudioClip clip = loader.getResourceAsAudioClip(soundPath + name); 426 if(clip == null) 427 throw(new ResourceNotFoundException(path)); 428 429 return(clip); 430 } 431 432 /** Get a reference to a <code>Properties</code> resource. 433 * 434 * @param name The name of the resource. 435 * @return The <code>Properties</code> object representing the resource. 436 * @exception kiwi.util.ResourceNotFoundException If the resource was not 437 * found. 438 */ 439 440 public Properties getProperties(String name) 441 { 442 checkResourceName(name); 443 444 Properties props = null; 445 String path = propertyPath + name; 446 447 try 448 { 449 props = loader.getResourceAsProperties(path); 450 } 451 catch(IOException ex) { } 452 453 if(props == null) 454 throw(new ResourceNotFoundException(path)); 455 456 return(props); 457 } 458 459 /** Get a reference to a <code>LocaleData</code> object for the default 460 * locale. The locale naming convention 461 * <i>basename_language_country_variant</i> is 462 * supported; a search is performed starting with the most specific name 463 * and ending with the most generic. 464 * 465 * @param name The name of the resource; this should be the base name of 466 * the resource bundle; the appropriate locale country, language, and 467 * variant codes and the ".msg" extension will be automatically 468 * appended to the name. 469 * @return The <code>LocaleData</code> object representing the resource. 470 * If the resource bundle has been previously loaded, a cached copy is 471 * returned. 472 * @exception kiwi.util.ResourceNotFoundException If the resource was not 473 * found. 474 */ 475 476 public LocaleData getResourceBundle(String name) 477 throws ResourceNotFoundException 478 { 479 return(getResourceBundle(name, Locale.getDefault())); 480 } 481 482 /** Get a reference to a <code>LocaleData</code> object for a specified 483 * locale. The locale naming convention 484 * <i>basename_language_country_variant</i> is 485 * supported; a search is performed starting with the most specific name 486 * and ending with the most generic. If the resource bundle has been 487 * previously loaded, a cached copy is returned. 488 * 489 * @param name The name of the resource; this should be the base name of 490 * the resource bundle; the appropriate locale contry, language, and 491 * variant codes and the ".msg" extension will be automatically 492 * appended to the name. 493 * @param locale The locale for the resource. 494 * @return The <code>LocaleData</code> object representing the resource. 495 * @exception kiwi.util.ResourceNotFoundException If the resource was not 496 * found. 497 */ 498 499 public LocaleData getResourceBundle(String name, Locale locale) 500 throws ResourceNotFoundException 501 { 502 checkResourceName(name); 503 504 String path = resbundlePath + name, cpath = null; 505 LocaleData bundle = null; 506 507 Stack paths = new Stack(); 508 paths.push(path + RESBUNDLE_EXT); 509 path += "_" + locale.getLanguage(); 510 paths.push(path + RESBUNDLE_EXT); 511 String country = locale.getCountry(); 512 if((country != null) && (country.length() > 0)) 513 { 514 path += "_" + country; 515 paths.push(path + RESBUNDLE_EXT); 516 String variant = locale.getVariant(); 517 if((variant != null) && (variant.length() > 0)) 518 { 519 path += "_" + variant; 520 paths.push(variant + RESBUNDLE_EXT); 521 } 522 } 523 524 while(!paths.empty()) 525 { 526 cpath = (String)paths.pop(); 527 528 bundle = (LocaleData)bundles.get(cpath); 529 if(bundle == null) 530 { 531 try 532 { 533 InputStream is = loader.getResourceAsStream(cpath); 534 bundle = new LocaleData(is); 535 bundles.put(cpath, bundle); 536 } 537 catch(IOException ex) 538 { 539 bundle = null; 540 } 541 } 542 543 if(bundle != null) break; 544 } 545 546 if(bundle == null) 547 throw(new ResourceNotFoundException(cpath)); 548 549 return(bundle); 550 } 551 552 /** Get a reference to a <code>ColorTheme</code> resource. 553 * 554 * @param name The name of the resource; this should be the base name of 555 * the color theme; the ".thm" extension will be automatically 556 * appended to the name. 557 * @return The <code>ColorTheme</code> object representing the resource. 558 * @exception kiwi.util.ResourceNotFoundException If the resource was not 559 * found. 560 */ 561 562 public ColorTheme getTheme(String name) 563 { 564 checkResourceName(name); 565 566 String path = themePath + name + THEME_EXT; 567 ColorTheme theme = null; 568 569 try 570 { 571 InputStream is = loader.getResourceAsStream(path); 572 Config cfg = new Config(); 573 cfg.load(is); 574 theme = new ColorTheme(cfg); 575 } 576 catch(IOException ex) 577 { 578 throw(new ResourceNotFoundException(path)); 579 } 580 581 return(theme); 582 } 583 584 /** Get a stream to a resource. 585 * 586 * @param name The name of the resource. 587 * @return An <code>InputStream</code> from which the resource can be read. 588 * @exception kiwi.util.ResourceNotFoundException If the resource was not 589 * found. 590 * @since Kiwi 1.3 591 */ 592 593 public InputStream getStream(String name) throws ResourceNotFoundException 594 { 595 checkResourceName(name); 596 597 InputStream is; 598 599 try 600 { 601 is = loader.getResourceAsStream(name); 602 } 603 catch(IOException ex) 604 { 605 throw(new ResourceNotFoundException(name)); 606 } 607 608 return(is); 609 } 610 611 /* 612 */ 613 614 private void checkResourceName(String name) throws IllegalArgumentException 615 { 616 if((name == null) || name.equals("")) 617 throw(new IllegalArgumentException("Null or empty resource name")); 618 } 619 620 } 621 622/* end of source file */