gt:                     if(majorVersion == 0 && minorVersion == 0) {
context: /*
   * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Sun designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Sun in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  package com.sun.lwuit.util;
  
  import com.sun.lwuit.Display;
  import com.sun.lwuit.EncodedImage;
  import com.sun.lwuit.Font;
  import com.sun.lwuit.Image;
  import com.sun.lwuit.StaticAnimation;
  import com.sun.lwuit.plaf.Border;
  import com.sun.lwuit.plaf.Style;
  import java.io.ByteArrayInputStream;
  import java.io.DataInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Vector;
  
  /**
   * Loads resources from the binary resource file generated during the build process or via the LWUIT Designer.
   * A resource is loaded entirely into memory since random file access is not supported
   * in Java ME, any other approach would be inefficient. This means that memory must
   * be made available to accommodate the resource file. 
   * 
   * @author Shai Almog
   */
  public class Resources {
      /**
       * Magic numbers to prevent data corruption
       */
      static final byte MAGIC_THEME_LEGACY = (byte)0xF7;
      static final byte MAGIC_ANIMATION_LEGACY = (byte)0xF8;
      static final byte MAGIC_INDEXED_IMAGE_LEGACY = (byte)0xF4;
      static final byte MAGIC_FONT_LEGACY = (byte)0xF6;
      static final byte MAGIC_INDEXED_FONT_LEGACY = (byte)0xFB;
      static final byte MAGIC_IMAGE_LEGACY = (byte)0xF3;
  
  
      static final byte MAGIC_FONT = (byte)0xFC;
      static final byte MAGIC_IMAGE = (byte)0xFD;
      static final byte MAGIC_L10N = (byte)0xF9;
      static final byte MAGIC_DATA = (byte)0xFA;
      static final byte MAGIC_HEADER = (byte)0xFF;
  
      private short majorVersion;
      private short minorVersion;
  
      /**
       * Temporary member for compatibility with older versions, in future versions
       * this will superceed the MAGIC_THEME property
       */
      static final byte MAGIC_THEME = (byte)0xF2;
  
      static final int BORDER_TYPE_EMPTY = 0;
      static final int BORDER_TYPE_LINE = 1;
      static final int BORDER_TYPE_ROUNDED = 2;
      static final int BORDER_TYPE_ETCHED_LOWERED = 4;
      static final int BORDER_TYPE_ETCHED_RAISED = 5;
      static final int BORDER_TYPE_BEVEL_RAISED = 6;
      static final int BORDER_TYPE_BEVEL_LOWERED = 7;
      static final int BORDER_TYPE_IMAGE = 8;
  
      // for use by the resource editor
      private static Class classLoader = Resources.class;
  
      private String[] metaData;
  
      static void setClassLoader(Class cls) {
          classLoader = cls;
      }
      
      /**
       * Hashtable containing the mapping between element types and their names in the
       * resource hashtable
       */
      private Hashtable resourceTypes = new Hashtable();
      
      /**
       * A cache within the resource allowing us to preserve some resources in memory
       * so they can be utilized by a theme when it is loaded
       */
      private Hashtable resources = new Hashtable();
      
      private DataInputStream input; 
      
      // for internal use by the resource editor, creates an empty resource
      Resources() {
      }
      
      Resources(InputStream input) throws IOException {
          openFile(input);
      }
      
      void clear() {
          majorVersion = 0;
          minorVersion = 0;
          resourceTypes.clear();
          resources.clear();
          input = null;
      }
      
      /**
       * This method is used by the LWUIT Designer
       */
      void startingEntry(String id, byte magic) {
      }
  
      void openFile(InputStream input) throws IOException {
          clear();
          this.input = new DataInputStream(input);
          int resourceCount = this.input.readShort();
          if(resourceCount < 0) {
              throw new IOException("Invalid resource file!");
          }
          for(int iter = 0 ; iter < resourceCount ; iter++) {
              byte magic = this.input.readByte();
              String id = this.input.readUTF();
              startingEntry(id, magic);
              switch(magic) {
                  case MAGIC_HEADER:
                      readHeader();
                      continue;
                  case MAGIC_THEME:
                      setResource(id, MAGIC_THEME, loadTheme(id, magic == MAGIC_THEME));
                      continue;
                  case MAGIC_IMAGE:
                      setResource(id, magic, createImage());
                      continue;
                  case MAGIC_FONT:
                      setResource(id, magic, loadFont(this.input, id, false));
                      continue;
                  case MAGIC_DATA:
                      setResource(id, magic, createData());
                      continue;
                  case MAGIC_L10N:
                      setResource(id, magic, loadL10N());
                      continue;
  
                  // legacy file support to be removed
                  case MAGIC_IMAGE_LEGACY:
                      setResource(id, MAGIC_IMAGE, createImage());
                      continue;
                  case MAGIC_INDEXED_IMAGE_LEGACY:
                      setResource(id, MAGIC_IMAGE, createPackedImage8());
                      continue;
                  case MAGIC_THEME_LEGACY:
                      setResource(id, MAGIC_THEME, loadTheme(id, magic == MAGIC_THEME));
                      continue;
                  case MAGIC_FONT_LEGACY:
                      setResource(id, MAGIC_FONT, loadFont(this.input, id, false));
                      continue;
                  case MAGIC_INDEXED_FONT_LEGACY:
                      setResource(id, MAGIC_FONT, loadFont(this.input, id, true));
                      continue;
                  case MAGIC_ANIMATION_LEGACY:
                      setResource(id, MAGIC_IMAGE, loadAnimation(this.input));
                      continue;
                  default:
                      throw new IOException("Corrupt theme file unrecognized magic number: " + Integer.toHexString(magic & 0xff));
              }
          }
      }
      
      /**
       * Reads the header of the resource file
       */
      private void readHeader() throws IOException {
          int size = input.readShort();
          majorVersion = input.readShort();
          minorVersion = input.readShort();
          
          metaData = new String[input.readShort()];
          for(int iter = 0 ; iter < metaData.length ; iter++) {
              metaData[iter] = input.readUTF();
          }
      }
  
      /**
       * Returns the version number for this resource file. 
       * This value relates to the value from the header defined by the resource file
       * specification. 0 is returned for legacy versions of the resource file format.
       * 
       * @return major version number for the resource file
       */
      public int getMajorVersion() {
          return majorVersion;
      }
  
      /**
       * Returns the minor version number for this resource file
       * This value relates to the value from the header defined by the resource file
       * specification. 
       *
       * @return minor version number for the resource file
       */
      public int getMinorVersion() {
          return minorVersion;
      }
  
      /**
       * Returns optional meta-data associated with the resource file
       *
       * @return optional meta-data associated with the file
       */
      public String[] getMetaData() {
          return metaData;
      }
  
      /**
       * Returns the names of the resources within this bundle
       * 
       * @return array of names of all the resources in this bundle
       */
      public String[] getResourceNames() {
          String[] arr = new String[resourceTypes.size()];
          Enumeration e = resourceTypes.keys();
          for(int iter = 0 ; iter < arr.length ; iter++) {
              arr[iter] = (String)e.nextElement();
          }
          return arr;
      }
  
      /**
       * Returns the names of the data resources within this bundle
       * 
       * @return array of names of the data resources in this bundle
       */
      public String[] getDataResourceNames() {
          return getResourceTypeNames(MAGIC_DATA);
      }
  
      /**
       * For internal use only
       */
      void setResource(String id, byte type, Object value) {
          if(value == null) {
              resources.remove(id);
              resourceTypes.remove(id);
          } else {
              resources.put(id, value);
              resourceTypes.put(id, new Byte(type));
          }
      }
      
  
      /**
       * Returns the names of the localization bundles within this bundle
       * 
       * @return array of names of the localization resources in this bundle
       */
      public String[] getL10NResourceNames() {
          return getResourceTypeNames(MAGIC_L10N);
      }
  
      /**
       * Returns the names of the fonts within this bundle
       * 
       * @return array of names of the font resources in this bundle
       */
      public String[] getFontResourceNames() {
          Vector vec = new Vector();
          Enumeration e = resourceTypes.keys();
          while(e.hasMoreElements()) {
              String c = (String)e.nextElement();
              if(isFont(c)) {
                  vec.addElement(c);
              }
          }
          return toStringArray(vec);
      }
  
      /**
       * Returns the names of the images within this bundle
       * 
       * @return array of names of the image resources in this bundle
       */
      public String[] getThemeResourceNames() {
          Vector vec = new Vector();
          Enumeration e = resourceTypes.keys();
          while(e.hasMoreElements()) {
              String c = (String)e.nextElement();
              if(isTheme(c)) {
                  vec.addElement(c);
              }
          }
          return toStringArray(vec);
      }
  
      /**
       * Returns the names of the images within this bundle
       * 
       * @return array of names of the image resources in this bundle
       */
      public String[] getImageResourceNames() {
          Vector vec = new Vector();
          Enumeration e = resourceTypes.keys();
          while(e.hasMoreElements()) {
              String c = (String)e.nextElement();
              if(isImage(c)) {
                  vec.addElement(c);
              }
          }
          return toStringArray(vec);
      }
  
      /**
       * Returns the names of the animations within this bundle
       * 
       * @return array of names of the animation resources in this bundle
       * @deprecated use getImageResourceNames instead
       */
      public String[] getAnimationResourceNames() {
          return getResourceTypeNames(MAGIC_ANIMATION_LEGACY);
      }
      
      /**
       * For internal use only
       */
      byte getResourceType(String name) {
          return ((Byte)resourceTypes.get(name)).byteValue();
      }
      
      private String[] getResourceTypeNames(byte b) {
          Vector vec = new Vector();
          Enumeration e = resourceTypes.keys();
          while(e.hasMoreElements()) {
              String c = (String)e.nextElement();
              if(((Byte)resourceTypes.get(c)).byteValue() == b) {
                  vec.addElement(c);
              }
          }
          return toStringArray(vec);
      }
  
      private static String[] toStringArray(Vector v) {
          String[] s = new String[v.size()];
          for(int iter = 0 ; iter < s.length ; iter++) {
              s[iter] = (String)v.elementAt(iter);
          }
          return s;
      }
  
      /**
       * Returns true if this is a generic data resource
       * 
       * @param name the name of the resource
       * @return true if the resource is a data resource
       * @throws NullPointerException if the resource doesn't exist
       */
      public boolean isL10N(String name) {
          byte b = ((Byte)resourceTypes.get(name)).byteValue();
          return b == MAGIC_L10N;
      }
      
      /**
       * Returns true if this is a theme resource
       * 
       * @param name the name of the resource
       * @return true if the resource is a theme
       * @throws NullPointerException if the resource doesn't exist
       */
      public boolean isTheme(String name) {
          byte b = ((Byte)resourceTypes.get(name)).byteValue();
          return b == MAGIC_THEME_LEGACY || b == MAGIC_THEME;
      }
  
      /**
       * Returns true if this is a font resource
       * 
       * @param name the name of the resource
       * @return true if the resource is a font
       * @throws NullPointerException if the resource doesn't exist
       */
      public boolean isFont(String name) {
          byte b = ((Byte)resourceTypes.get(name)).byteValue();
          return b == MAGIC_FONT || b == MAGIC_FONT_LEGACY || b == MAGIC_INDEXED_FONT_LEGACY;
      }
  
      /**
       * Returns true if this is an animation resource
       * 
       * @param name the name of the resource
       * @return true if the resource is an animation
       * @throws NullPointerException if the resource doesn't exist
       * @deprecated animations are no longer distinguished from images in the resource file, use Image.isAnimation instead
       */
      public boolean isAnimation(String name) {
          byte b = ((Byte)resourceTypes.get(name)).byteValue();
          return b == MAGIC_ANIMATION_LEGACY;
      }
  
      /**
       * Returns true if this is a data resource
       * 
       * @param name the name of the resource
       * @return true if the resource is a data resource
       * @throws NullPointerException if the resource doesn't exist
       */
      public boolean isData(String name) {
          byte b = ((Byte)resourceTypes.get(name)).byteValue();
          return b == MAGIC_DATA;
      }
  
      /**
       * Returns true if this is an image resource
       * 
       * @param name the name of the resource
       * @return true if the resource is an image
       * @throws NullPointerException if the resource doesn't exist
       */
      public boolean isImage(String name) {
          byte b = ((Byte)resourceTypes.get(name)).byteValue();
          return b == MAGIC_IMAGE_LEGACY || b == MAGIC_ANIMATION_LEGACY || b == MAGIC_INDEXED_IMAGE_LEGACY || b == MAGIC_IMAGE;
      }
      
      /**
       * Creates a resource object from the local JAR resource identifier
       * 
       * @param resource a local reference to a resource using the syntax of Class.getResourceAsStream(String)
       * @return a resource object
       * @throws java.io.IOException if opening/reading the resource fails
       */
      public static Resources open(String resource) throws IOException {
          try {
              InputStream is = Display.getInstance().getResourceAsStream(classLoader, resource);
              Resources r = new Resources(is);
              is.close();
              return r;
          } catch(RuntimeException err) {
              // intercept exceptions since user code might not deal well with runtime exceptions 
              err.printStackTrace();
              throw new IOException(err.getMessage());
          }
      }
  
      StaticAnimation loadAnimation(DataInputStream input) throws IOException {
          return StaticAnimation.createAnimation(input);
      }
      
      /**
       * Creates a resource object from the given input stream
       * 
       * @param resource stream from which to read the resource
       * @return a resource object
       * @throws java.io.IOException if opening/reading the resource fails
       */
      public static Resources open(InputStream resource) throws IOException {
          return new Resources(resource);
      }
  
      /**
       * Returns the image resource from the file
       * 
       * @param id name of the image resource
       * @return cached image instance
       */
      public Image getImage(String id) {
          return (Image)resources.get(id);
      }
  
      /**
       * Returns the animation resource from the file
       * 
       * @param id name of the animation resource
       * @return cached image instance
       * @deprecated use getImage(String) instead
       */
      public StaticAnimation getAnimation(String id) {
          return (StaticAnimation)resources.get(id);
      }
      
      /**
       * Returns the data resource from the file
       * 
       * @param id name of the data resource
       * @return newly created input stream that allows reading the data of the resource
       */
      public InputStream getData(String id) {
          return new ByteArrayInputStream((byte[])resources.get(id));
      }
      
      /**
       * Returns a hashmap containing localized String key/value pairs for the given locale name
       * 
       * @param id the name of the locale resource
       * @param locale name of the locale resource
       * @return Hashtable containing key value pairs for localized data
       */
      public Hashtable getL10N(String id, String locale) {
          return (Hashtable)((Hashtable)resources.get(id)).get(locale);
      }
  
      /**
       * Returns an enumration of the locales supported by this resource id
       * 
       * @param id the name of the locale resource
       * @return enumeration of strings containing bundle names
       */
      public Enumeration listL10NLocales(String id) {
          return ((Hashtable)resources.get(id)).keys();
      }
  
      /**
       * Returns the font resource from the file
       * 
       * @param id name of the font resource
       * @return cached font instance
       */
      public Font getFont(String id) {
          return (Font)resources.get(id);
      }
      
      /**
       * Returns the theme resource from the file
       * 
       * @param id name of the theme resource
       * @return cached theme instance
       */
      public Hashtable getTheme(String id) {
          Hashtable h = (Hashtable)resources.get(id);
          
          // theme can be null in valid use cases such as the resource editor
          if(h != null && h.containsKey("uninitialized")) {
              Enumeration e = h.keys();
              while(e.hasMoreElements()) {
                  String key = (String)e.nextElement();
                  if(key.endsWith("font") || (key.endsWith("Image") && !key.endsWith("scaledImage"))) {
                      Object value = h.get(key);
                      if(value == null) {
                          throw new IllegalArgumentException("Couldn't find resource: " + key);
                      }
                      
                      // the resource was not already loaded when we loaded the theme
                      // it must be loaded now so we can resolve the temporary name
                      if(value instanceof String) {
                          Object o = resources.get(value);
                          if(o == null) {
                              throw new IllegalArgumentException("Theme entry for " + key + " could not be found: " + value);
                          }
                          h.put(key, o);
                      }
                  }
                  // if this is a border we might need to do additional work for older versions
                  // of LWUIT and for the case of an image border where the images might not have
                  // been loaded yet when the border was created
                  if(key.endsWith("order")) {
                      Border b = confirmBorder(h, key);
  