1 /*
   2  * Licensed to the Apache Software Foundation (ASF) under one or more
   3  * contributor license agreements.  See the NOTICE file distributed with
   4  * this work for additional information regarding copyright ownership.
   5  * The ASF licenses this file to You under the Apache License, Version 2.0
   6  * (the "License"); you may not use this file except in compliance with
   7  * the License.  You may obtain a copy of the License at
   8  *
   9  *      http://www.apache.org/licenses/LICENSE-2.0
  10  *
  11  * Unless required by applicable law or agreed to in writing, software
  12  * distributed under the License is distributed on an "AS IS" BASIS,
  13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14  * See the License for the specific language governing permissions and
  15  * limitations under the License.
  16  */
  17 
  18 package com.sun.org.apache.xml.internal.resolver;
  19 
  20 import java.util.Hashtable;
  21 import java.util.Vector;
  22 
  23 /**
  24  * Represents a Catalog entry.
  25  *
  26  * <p>Instances of this class represent individual entries
  27  * in a Catalog.</p>
  28  *
  29  * <p>Each catalog entry has a unique name and is associated with
  30  * an arbitrary number of arguments (all strings). For example, the
  31  * TR9401 catalog entry "PUBLIC" has two arguments, a public identifier
  32  * and a system identifier. Each entry has a unique numeric type,
  33  * assigned automatically when the entry type is created.</p>
  34  *
  35  * <p>The number and type of catalog entries is maintained
  36  * <em>statically</em>. Catalog classes, or their subclasses, can add
  37  * new entry types, but all Catalog objects share the same global pool
  38  * of types.</p>
  39  *
  40  * <p>Initially there are no valid entries.</p>
  41  *
  42  * @see Catalog
  43  *
  44  * @author Norman Walsh
  45  * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
  46  *
  47  */
  48 public class CatalogEntry {
  49   /** The nextEntry is the ordinal number of the next entry type. */
  50   static int nextEntry = 0;
  51 
  52   /**
  53    * The entryTypes vector maps catalog entry names
  54    * (e.g., 'BASE' or 'SYSTEM') to their type (1, 2, etc.).
  55    * Names are case sensitive.
  56    */
  57   static final Hashtable entryTypes = new Hashtable();
  58 
  59   /** The entryTypes vector maps catalog entry types to the
  60       number of arguments they're required to have. */
  61   static final Vector entryArgs = new Vector();
  62 
  63   /**
  64    * Adds a new catalog entry type.
  65    *
  66    * @param name The name of the catalog entry type. This must be
  67    * unique among all types and is case-sensitive. (Adding a duplicate
  68    * name effectively replaces the old type with the new type.)
  69    * @param numArgs The number of arguments that this entry type
  70    * is required to have. There is no provision for variable numbers
  71    * of arguments.
  72    * @return The type for the new entry.
  73    */
  74   public static int addEntryType(String name, int numArgs) {
  75     entryTypes.put(name, new Integer(nextEntry));
  76     entryArgs.add(nextEntry, new Integer(numArgs));
  77     nextEntry++;
  78 
  79     return nextEntry-1;
  80   }
  81 
  82   /**
  83    * Lookup an entry type
  84    *
  85    * @param name The name of the catalog entry type.
  86    * @return The type of the catalog entry with the specified name.
  87    * @throws InvalidCatalogEntryTypeException if no entry has the
  88    * specified name.
  89    */
  90   public static int getEntryType(String name)
  91     throws CatalogException {
  92     if (!entryTypes.containsKey(name)) {
  93       throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
  94     }
  95 
  96     Integer iType = (Integer) entryTypes.get(name);
  97 
  98     if (iType == null) {
  99       throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
 100     }
 101 
 102     return iType.intValue();
 103   }
 104 
 105   /**
 106    * Find out how many arguments an entry is required to have.
 107    *
 108    * @param name The name of the catalog entry type.
 109    * @return The number of arguments that entry type is required to have.
 110    * @throws InvalidCatalogEntryTypeException if no entry has the
 111    * specified name.
 112    */
 113   public static int getEntryArgCount(String name)
 114     throws CatalogException {
 115     return getEntryArgCount(getEntryType(name));
 116   }
 117 
 118   /**
 119    * Find out how many arguments an entry is required to have.
 120    *
 121    * @param type A valid catalog entry type.
 122    * @return The number of arguments that entry type is required to have.
 123    * @throws InvalidCatalogEntryTypeException if the type is invalid.
 124    */
 125   public static int getEntryArgCount(int type)
 126     throws CatalogException {
 127     try {
 128       Integer iArgs = (Integer) entryArgs.get(type);
 129       return iArgs.intValue();
 130     } catch (ArrayIndexOutOfBoundsException e) {
 131       throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
 132     }
 133   }
 134 
 135   /** The entry type of this entry */
 136   protected int entryType = 0;
 137 
 138   /** The arguments associated with this entry */
 139   protected Vector args = null;
 140 
 141   /**
 142    * Null constructor; something for subclasses to call.
 143    */
 144   public CatalogEntry() {}
 145 
 146   /**
 147    * Construct a catalog entry of the specified type.
 148    *
 149    * @param name The name of the entry type
 150    * @param args A String Vector of arguments
 151    * @throws InvalidCatalogEntryTypeException if no such entry type
 152    * exists.
 153    * @throws InvalidCatalogEntryException if the wrong number of arguments
 154    * is passed.
 155    */
 156   public CatalogEntry(String name, Vector args)
 157     throws CatalogException {
 158     Integer iType = (Integer) entryTypes.get(name);
 159 
 160     if (iType == null) {
 161       throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
 162     }
 163 
 164     int type = iType.intValue();
 165 
 166     try {
 167       Integer iArgs = (Integer) entryArgs.get(type);
 168       if (iArgs.intValue() != args.size()) {
 169         throw new CatalogException(CatalogException.INVALID_ENTRY);
 170       }
 171     } catch (ArrayIndexOutOfBoundsException e) {
 172       throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
 173     }
 174 
 175     entryType = type;
 176     this.args = args;
 177   }
 178 
 179   /**
 180    * Construct a catalog entry of the specified type.
 181    *
 182    * @param type The entry type
 183    * @param args A String Vector of arguments
 184    * @throws InvalidCatalogEntryTypeException if no such entry type
 185    * exists.
 186    * @throws InvalidCatalogEntryException if the wrong number of arguments
 187    * is passed.
 188    */
 189   public CatalogEntry(int type, Vector args)
 190     throws CatalogException {
 191     try {
 192       Integer iArgs = (Integer) entryArgs.get(type);
 193       if (iArgs.intValue() != args.size()) {
 194         throw new CatalogException(CatalogException.INVALID_ENTRY);
 195       }
 196     } catch (ArrayIndexOutOfBoundsException e) {
 197       throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
 198     }
 199 
 200     entryType = type;
 201     this.args = args;
 202   }
 203 
 204   /**
 205    * Get the entry type.
 206    *
 207    * @return The entry type of the CatalogEntry
 208    */
 209   public int getEntryType() {
 210     return entryType;
 211   }
 212 
 213   /**
 214    * Get an entry argument.
 215    *
 216    * @param argNum The argument number (arguments are numbered from 0).
 217    * @return The specified argument or null if an invalid argNum is
 218    * provided.
 219    */
 220   public String getEntryArg(int argNum) {
 221     try {
 222       String arg = (String) args.get(argNum);
 223       return arg;
 224     } catch (ArrayIndexOutOfBoundsException e) {
 225       return null;
 226     }
 227   }
 228 
 229   /**
 230    * Set an entry argument.
 231    *
 232    * <p>Catalogs sometimes need to adjust the catlog entry parameters,
 233    * for example to make a relative URI absolute with respect to the
 234    * current base URI. But in general, this function should only be
 235    * called shortly after object creation to do some sort of cleanup.
 236    * Catalog entries should not mutate over time.</p>
 237    *
 238    * @param argNum The argument number (arguments are numbered from 0).
 239    * @throws ArrayIndexOutOfBoundsException if an invalid argument
 240    * number is provided.
 241    */
 242   public void setEntryArg(int argNum, String newspec)
 243     throws ArrayIndexOutOfBoundsException {
 244     args.set(argNum, newspec);
 245   }
 246 }