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.io.IOException;
  21 import java.io.InputStream;
  22 import java.io.FileNotFoundException;
  23 import java.util.Enumeration;
  24 import java.util.Vector;
  25 import java.net.URL;
  26 import java.net.URLConnection;
  27 import java.net.MalformedURLException;
  28 import javax.xml.parsers.SAXParserFactory;
  29 import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
  30 import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
  31 import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader;
  32 import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader;
  33 import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader;
  34 
  35 /**
  36  * An extension to OASIS Open Catalog files, this class supports
  37  * suffix-based matching and an external RFC2483 resolver.
  38  *
  39  * @see Catalog
  40  * @deprecated The JDK internal Catalog API in package
  41  * {@code com.sun.org.apache.xml.internal.resolver}
  42  * is encapsulated in JDK 9. The entire implementation under the package is now
  43  * deprecated and subject to removal in a future release. Users of the API
  44  * should migrate to the {@linkplain javax.xml.catalog new public API}.
  45  * <p>
  46  * The new Catalog API is supported throughout the JDK XML Processors, which allows
  47  * the use of Catalog by simply setting a path to a Catalog file as a property.
  48  *
  49  * @author Norman Walsh
  50  * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
  51  *
  52  * @version 1.0
  53  */
  54 @Deprecated(since="9", forRemoval=true)
  55 public class Resolver extends Catalog {
  56   /**
  57    * The URISUFFIX Catalog Entry type.
  58    *
  59    * <p>URI suffix entries match URIs that end in a specified suffix.</p>
  60    */
  61   public static final int URISUFFIX = CatalogEntry.addEntryType("URISUFFIX", 2);
  62 
  63   /**
  64    * The SYSTEMSUFFIX Catalog Entry type.
  65    *
  66    * <p>System suffix entries match system identifiers that end in a
  67    * specified suffix.</p>
  68    */
  69   public static final int SYSTEMSUFFIX = CatalogEntry.addEntryType("SYSTEMSUFFIX", 2);
  70 
  71   /**
  72    * The RESOLVER Catalog Entry type.
  73    *
  74    * <p>A hook for providing support for web-based backup resolvers.</p>
  75    */
  76   public static final int RESOLVER = CatalogEntry.addEntryType("RESOLVER", 1);
  77 
  78   /**
  79    * The SYSTEMREVERSE Catalog Entry type.
  80    *
  81    * <p>This is a bit of a hack. There's no actual SYSTEMREVERSE entry,
  82    * but this entry type is used to indicate that a reverse lookup is
  83    * being performed. (This allows the Resolver to implement
  84    * RFC2483 I2N and I2NS.)
  85    */
  86   public static final int SYSTEMREVERSE
  87     = CatalogEntry.addEntryType("SYSTEMREVERSE", 1);
  88 
  89   /**
  90    * Setup readers.
  91    */
  92   public void setupReaders() {
  93     SAXParserFactory spf = catalogManager.useServicesMechanism() ?
  94                     SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
  95     spf.setNamespaceAware(true);
  96     spf.setValidating(false);
  97 
  98     SAXCatalogReader saxReader = new SAXCatalogReader(spf);
  99 
 100     saxReader.setCatalogParser(null, "XCatalog",
 101                                "com.sun.org.apache.xml.internal.resolver.readers.XCatalogReader");
 102 
 103     saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName,
 104                                "catalog",
 105                                "com.sun.org.apache.xml.internal.resolver.readers.ExtendedXMLCatalogReader");
 106 
 107     addReader("application/xml", saxReader);
 108 
 109     TR9401CatalogReader textReader = new TR9401CatalogReader();
 110     addReader("text/plain", textReader);
 111   }
 112 
 113   /**
 114    * Cleanup and process a Catalog entry.
 115    *
 116    * <p>This method processes each Catalog entry, changing mapped
 117    * relative system identifiers into absolute ones (based on the current
 118    * base URI), and maintaining other information about the current
 119    * catalog.</p>
 120    *
 121    * @param entry The CatalogEntry to process.
 122    */
 123   public void addEntry(CatalogEntry entry) {
 124     int type = entry.getEntryType();
 125 
 126     if (type == URISUFFIX) {
 127       String suffix = normalizeURI(entry.getEntryArg(0));
 128       String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
 129 
 130       entry.setEntryArg(1, fsi);
 131 
 132       catalogManager.debug.message(4, "URISUFFIX", suffix, fsi);
 133     } else if (type == SYSTEMSUFFIX) {
 134       String suffix = normalizeURI(entry.getEntryArg(0));
 135       String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
 136 
 137       entry.setEntryArg(1, fsi);
 138 
 139       catalogManager.debug.message(4, "SYSTEMSUFFIX", suffix, fsi);
 140     }
 141 
 142     super.addEntry(entry);
 143   }
 144 
 145   /**
 146    * Return the applicable URI.
 147    *
 148    * <p>If a URI entry exists in the Catalog
 149    * for the URI specified, return the mapped value.</p>
 150    *
 151    * <p>In the Resolver (as opposed to the Catalog) class, if the
 152    * URI isn't found by the usual algorithm, URISUFFIX entries are
 153    * considered.</p>
 154    *
 155    * <p>URI comparison is case sensitive.</p>
 156    *
 157    * @param uri The URI to locate in the catalog.
 158    *
 159    * @return The resolved URI.
 160    *
 161    * @throws MalformedURLException The system identifier of a
 162    * subordinate catalog cannot be turned into a valid URL.
 163    * @throws IOException Error reading subordinate catalog file.
 164    */
 165   public String resolveURI(String uri)
 166     throws MalformedURLException, IOException {
 167 
 168     String resolved = super.resolveURI(uri);
 169     if (resolved != null) {
 170       return resolved;
 171     }
 172 
 173     Enumeration en = catalogEntries.elements();
 174     while (en.hasMoreElements()) {
 175       CatalogEntry e = (CatalogEntry) en.nextElement();
 176       if (e.getEntryType() == RESOLVER) {
 177         resolved = resolveExternalSystem(uri, e.getEntryArg(0));
 178         if (resolved != null) {
 179           return resolved;
 180         }
 181       } else if (e.getEntryType() == URISUFFIX) {
 182         String suffix = e.getEntryArg(0);
 183         String result = e.getEntryArg(1);
 184 
 185         if (suffix.length() <= uri.length()
 186             && uri.substring(uri.length()-suffix.length()).equals(suffix)) {
 187           return result;
 188         }
 189       }
 190     }
 191 
 192     // Otherwise, look in the subordinate catalogs
 193     return resolveSubordinateCatalogs(Catalog.URI,
 194                                       null,
 195                                       null,
 196                                       uri);
 197   }
 198 
 199   /**
 200    * Return the applicable SYSTEM system identifier, resorting
 201    * to external RESOLVERs if necessary.
 202    *
 203    * <p>If a SYSTEM entry exists in the Catalog
 204    * for the system ID specified, return the mapped value.</p>
 205    *
 206    * <p>In the Resolver (as opposed to the Catalog) class, if the
 207    * URI isn't found by the usual algorithm, SYSTEMSUFFIX entries are
 208    * considered.</p>
 209    *
 210    * <p>On Windows-based operating systems, the comparison between
 211    * the system identifier provided and the SYSTEM entries in the
 212    * Catalog is case-insensitive.</p>
 213    *
 214    * @param systemId The system ID to locate in the catalog.
 215    *
 216    * @return The system identifier to use for systemId.
 217    *
 218    * @throws MalformedURLException The formal system identifier of a
 219    * subordinate catalog cannot be turned into a valid URL.
 220    * @throws IOException Error reading subordinate catalog file.
 221    */
 222   public String resolveSystem(String systemId)
 223     throws MalformedURLException, IOException {
 224 
 225     String resolved = super.resolveSystem(systemId);
 226     if (resolved != null) {
 227       return resolved;
 228     }
 229 
 230     Enumeration en = catalogEntries.elements();
 231     while (en.hasMoreElements()) {
 232       CatalogEntry e = (CatalogEntry) en.nextElement();
 233       if (e.getEntryType() == RESOLVER) {
 234         resolved = resolveExternalSystem(systemId, e.getEntryArg(0));
 235         if (resolved != null) {
 236           return resolved;
 237         }
 238       } else if (e.getEntryType() == SYSTEMSUFFIX) {
 239         String suffix = e.getEntryArg(0);
 240         String result = e.getEntryArg(1);
 241 
 242         if (suffix.length() <= systemId.length()
 243             && systemId.substring(systemId.length()-suffix.length()).equals(suffix)) {
 244           return result;
 245         }
 246       }
 247     }
 248 
 249     return resolveSubordinateCatalogs(Catalog.SYSTEM,
 250                                       null,
 251                                       null,
 252                                       systemId);
 253   }
 254 
 255   /**
 256    * Return the applicable PUBLIC or SYSTEM identifier, resorting
 257    * to external resolvers if necessary.
 258    *
 259    * <p>This method searches the Catalog and returns the system
 260    * identifier specified for the given system or
 261    * public identifiers. If
 262    * no appropriate PUBLIC or SYSTEM entry is found in the Catalog,
 263    * null is returned.</p>
 264    *
 265    * <p>Note that a system or public identifier in the current catalog
 266    * (or subordinate catalogs) will be used in preference to an
 267    * external resolver. Further, if a systemId is present, the external
 268    * resolver(s) will be queried for that before the publicId.</p>
 269    *
 270    * @param publicId The public identifier to locate in the catalog.
 271    * Public identifiers are normalized before comparison.
 272    * @param systemId The nominal system identifier for the entity
 273    * in question (as provided in the source document).
 274    *
 275    * @throws MalformedURLException The formal system identifier of a
 276    * subordinate catalog cannot be turned into a valid URL.
 277    * @throws IOException Error reading subordinate catalog file.
 278    *
 279    * @return The system identifier to use.
 280    * Note that the nominal system identifier is not returned if a
 281    * match is not found in the catalog, instead null is returned
 282    * to indicate that no match was found.
 283    */
 284   public String resolvePublic(String publicId, String systemId)
 285     throws MalformedURLException, IOException {
 286 
 287     String resolved = super.resolvePublic(publicId, systemId);
 288     if (resolved != null) {
 289       return resolved;
 290     }
 291 
 292     Enumeration en = catalogEntries.elements();
 293     while (en.hasMoreElements()) {
 294       CatalogEntry e = (CatalogEntry) en.nextElement();
 295       if (e.getEntryType() == RESOLVER) {
 296         if (systemId != null) {
 297           resolved = resolveExternalSystem(systemId,
 298                                            e.getEntryArg(0));
 299           if (resolved != null) {
 300             return resolved;
 301           }
 302         }
 303         resolved = resolveExternalPublic(publicId, e.getEntryArg(0));
 304         if (resolved != null) {
 305           return resolved;
 306         }
 307       }
 308     }
 309 
 310     return resolveSubordinateCatalogs(Catalog.PUBLIC,
 311                                       null,
 312                                       publicId,
 313                                       systemId);
 314   }
 315 
 316     /**
 317      * Query an external RFC2483 resolver for a system identifier.
 318      *
 319      * @param systemId The system ID to locate.
 320      * @param resolver The name of the resolver to use.
 321      *
 322      * @return The system identifier to use for the systemId.
 323      */
 324     protected String resolveExternalSystem(String systemId, String resolver)
 325         throws MalformedURLException, IOException {
 326         Resolver r = queryResolver(resolver, "i2l", systemId, null);
 327         if (r != null) {
 328             return r.resolveSystem(systemId);
 329         } else {
 330             return null;
 331         }
 332     }
 333 
 334     /**
 335      * Query an external RFC2483 resolver for a public identifier.
 336      *
 337      * @param publicId The system ID to locate.
 338      * @param resolver The name of the resolver to use.
 339      *
 340      * @return The system identifier to use for the systemId.
 341      */
 342     protected String resolveExternalPublic(String publicId, String resolver)
 343         throws MalformedURLException, IOException {
 344         Resolver r = queryResolver(resolver, "fpi2l", publicId, null);
 345         if (r != null) {
 346             return r.resolvePublic(publicId, null);
 347         } else {
 348             return null;
 349         }
 350     }
 351 
 352     /**
 353      * Query an external RFC2483 resolver.
 354      *
 355      * @param resolver The URL of the RFC2483 resolver.
 356      * @param command The command to send the resolver.
 357      * @param arg1 The first argument to the resolver.
 358      * @param arg2 The second argument to the resolver, usually null.
 359      *
 360      * @return The Resolver constructed.
 361      */
 362     protected Resolver queryResolver(String resolver,
 363                                      String command,
 364                                      String arg1,
 365                                      String arg2) {
 366         InputStream iStream = null;
 367         String RFC2483 = resolver + "?command=" + command
 368             + "&format=tr9401&uri=" + arg1
 369             + "&uri2=" + arg2;
 370         String line = null;
 371 
 372         try {
 373             URL url = new URL(RFC2483);
 374 
 375             URLConnection urlCon = url.openConnection();
 376 
 377             urlCon.setUseCaches(false);
 378 
 379             Resolver r = (Resolver) newCatalog();
 380 
 381             String cType = urlCon.getContentType();
 382 
 383             // I don't care about the character set or subtype
 384             if (cType.indexOf(";") > 0) {
 385                 cType = cType.substring(0, cType.indexOf(";"));
 386             }
 387 
 388             r.parseCatalog(cType, urlCon.getInputStream());
 389 
 390             return r;
 391         } catch (CatalogException cex) {
 392           if (cex.getExceptionType() == CatalogException.UNPARSEABLE) {
 393             catalogManager.debug.message(1, "Unparseable catalog: " + RFC2483);
 394           } else if (cex.getExceptionType()
 395                      == CatalogException.UNKNOWN_FORMAT) {
 396             catalogManager.debug.message(1, "Unknown catalog format: " + RFC2483);
 397           }
 398           return null;
 399         } catch (MalformedURLException mue) {
 400             catalogManager.debug.message(1, "Malformed resolver URL: " + RFC2483);
 401             return null;
 402         } catch (IOException ie) {
 403             catalogManager.debug.message(1, "I/O Exception opening resolver: " + RFC2483);
 404             return null;
 405         }
 406     }
 407 
 408     /**
 409      * Append two vectors, returning the result.
 410      *
 411      * @param vec The first vector
 412      * @param appvec The vector to be appended
 413      * @return The vector vec, with appvec's elements appended to it
 414      */
 415     private Vector appendVector(Vector vec, Vector appvec) {
 416         if (appvec != null) {
 417             for (int count = 0; count < appvec.size(); count++) {
 418                 vec.addElement(appvec.elementAt(count));
 419             }
 420         }
 421         return vec;
 422     }
 423 
 424     /**
 425      * Find the URNs for a given system identifier in all catalogs.
 426      *
 427      * @param systemId The system ID to locate.
 428      *
 429      * @return A vector of URNs that map to the systemId.
 430      */
 431     public Vector resolveAllSystemReverse(String systemId)
 432         throws MalformedURLException, IOException {
 433         Vector resolved = new Vector();
 434 
 435         // If there's a SYSTEM entry in this catalog, use it
 436         if (systemId != null) {
 437             Vector localResolved = resolveLocalSystemReverse(systemId);
 438             resolved = appendVector(resolved, localResolved);
 439         }
 440 
 441         // Otherwise, look in the subordinate catalogs
 442         Vector subResolved = resolveAllSubordinateCatalogs(SYSTEMREVERSE,
 443                                                            null,
 444                                                            null,
 445                                                            systemId);
 446 
 447         return appendVector(resolved, subResolved);
 448     }
 449 
 450     /**
 451      * Find the URN for a given system identifier.
 452      *
 453      * @param systemId The system ID to locate.
 454      *
 455      * @return A (single) URN that maps to the systemId.
 456      */
 457     public String resolveSystemReverse(String systemId)
 458         throws MalformedURLException, IOException {
 459         Vector resolved = resolveAllSystemReverse(systemId);
 460         if (resolved != null && resolved.size() > 0) {
 461             return (String) resolved.elementAt(0);
 462         } else {
 463             return null;
 464         }
 465     }
 466 
 467     /**
 468      * Return the applicable SYSTEM system identifiers.
 469      *
 470      * <p>If one or more SYSTEM entries exists in the Catalog
 471      * for the system ID specified, return the mapped values.</p>
 472      *
 473      * <p>The caller is responsible for doing any necessary
 474      * normalization of the system identifier before calling
 475      * this method. For example, a relative system identifier in
 476      * a document might be converted to an absolute system identifier
 477      * before attempting to resolve it.</p>
 478      *
 479      * <p>Note that this function will force all subordinate catalogs
 480      * to be loaded.</p>
 481      *
 482      * <p>On Windows-based operating systems, the comparison between
 483      * the system identifier provided and the SYSTEM entries in the
 484      * Catalog is case-insensitive.</p>
 485      *
 486      * @param systemId The system ID to locate in the catalog.
 487      *
 488      * @return The system identifier to use for the notation.
 489      *
 490      * @throws MalformedURLException The formal system identifier of a
 491      * subordinate catalog cannot be turned into a valid URL.
 492      * @throws IOException Error reading subordinate catalog file.
 493      */
 494     public Vector resolveAllSystem(String systemId)
 495         throws MalformedURLException, IOException {
 496         Vector resolutions = new Vector();
 497 
 498         // If there are SYSTEM entries in this catalog, start with them
 499         if (systemId != null) {
 500             Vector localResolutions = resolveAllLocalSystem(systemId);
 501             resolutions = appendVector(resolutions, localResolutions);
 502         }
 503 
 504         // Then look in the subordinate catalogs
 505         Vector subResolutions = resolveAllSubordinateCatalogs(SYSTEM,
 506                                                               null,
 507                                                               null,
 508                                                               systemId);
 509         resolutions = appendVector(resolutions, subResolutions);
 510 
 511         if (resolutions.size() > 0) {
 512             return resolutions;
 513         } else {
 514             return null;
 515         }
 516     }
 517 
 518     /**
 519      * Return all applicable SYSTEM system identifiers in this
 520      * catalog.
 521      *
 522      * <p>If one or more SYSTEM entries exists in the catalog file
 523      * for the system ID specified, return the mapped values.</p>
 524      *
 525      * @param systemId The system ID to locate in the catalog
 526      *
 527      * @return A vector of the mapped system identifiers or null
 528      */
 529     private Vector resolveAllLocalSystem(String systemId) {
 530         Vector map = new Vector();
 531         String osname = SecuritySupport.getSystemProperty("os.name");
 532         boolean windows = (osname.indexOf("Windows") >= 0);
 533         Enumeration en = catalogEntries.elements();
 534         while (en.hasMoreElements()) {
 535             CatalogEntry e = (CatalogEntry) en.nextElement();
 536             if (e.getEntryType() == SYSTEM
 537                 && (e.getEntryArg(0).equals(systemId)
 538                     || (windows
 539                         && e.getEntryArg(0).equalsIgnoreCase(systemId)))) {
 540                 map.addElement(e.getEntryArg(1));
 541             }
 542         }
 543         if (map.size() == 0) {
 544             return null;
 545         } else {
 546             return map;
 547         }
 548     }
 549 
 550     /**
 551      * Find the URNs for a given system identifier in the current catalog.
 552      *
 553      * @param systemId The system ID to locate.
 554      *
 555      * @return A vector of URNs that map to the systemId.
 556      */
 557     private Vector resolveLocalSystemReverse(String systemId) {
 558         Vector map = new Vector();
 559         String osname = SecuritySupport.getSystemProperty("os.name");
 560         boolean windows = (osname.indexOf("Windows") >= 0);
 561         Enumeration en = catalogEntries.elements();
 562         while (en.hasMoreElements()) {
 563             CatalogEntry e = (CatalogEntry) en.nextElement();
 564             if (e.getEntryType() == SYSTEM
 565                 && (e.getEntryArg(1).equals(systemId)
 566                     || (windows
 567                         && e.getEntryArg(1).equalsIgnoreCase(systemId)))) {
 568                 map.addElement(e.getEntryArg(0));
 569             }
 570         }
 571         if (map.size() == 0) {
 572             return null;
 573         } else {
 574             return map;
 575         }
 576     }
 577 
 578     /**
 579      * Search the subordinate catalogs, in order, looking for all
 580      * match.
 581      *
 582      * <p>This method searches the Catalog and returns all of the system
 583      * identifiers specified for the given entity type with the given
 584      * name, public, and system identifiers. In some contexts, these
 585      * may be null.</p>
 586      *
 587      * @param entityType The CatalogEntry type for which this query is
 588      * being conducted. This is necessary in order to do the approprate
 589      * query on a subordinate catalog.
 590      * @param entityName The name of the entity being searched for, if
 591      * appropriate.
 592      * @param publicId The public identifier of the entity in question
 593      * (as provided in the source document).
 594      * @param systemId The nominal system identifier for the entity
 595      * in question (as provided in the source document).
 596      *
 597      * @throws MalformedURLException The formal system identifier of a
 598      * delegated catalog cannot be turned into a valid URL.
 599      * @throws IOException Error reading delegated catalog file.
 600      *
 601      * @return The system identifier to use.
 602      * Note that the nominal system identifier is not returned if a
 603      * match is not found in the catalog, instead null is returned
 604      * to indicate that no match was found.
 605      */
 606     private synchronized Vector resolveAllSubordinateCatalogs(int entityType,
 607                                               String entityName,
 608                                               String publicId,
 609                                               String systemId)
 610         throws MalformedURLException, IOException {
 611 
 612         Vector resolutions = new Vector();
 613 
 614         for (int catPos = 0; catPos < catalogs.size(); catPos++) {
 615             Resolver c = null;
 616 
 617             try {
 618                 c = (Resolver) catalogs.elementAt(catPos);
 619             } catch (ClassCastException e) {
 620                 String catfile = (String) catalogs.elementAt(catPos);
 621                 c = (Resolver) newCatalog();
 622 
 623                 try {
 624                     c.parseCatalog(catfile);
 625                 } catch (MalformedURLException mue) {
 626                     catalogManager.debug.message(1, "Malformed Catalog URL", catfile);
 627                 } catch (FileNotFoundException fnfe) {
 628                     catalogManager.debug.message(1, "Failed to load catalog, file not found",
 629                           catfile);
 630                 } catch (IOException ioe) {
 631                     catalogManager.debug.message(1, "Failed to load catalog, I/O error", catfile);
 632                 }
 633 
 634                 catalogs.setElementAt(c, catPos);
 635             }
 636 
 637             String resolved = null;
 638 
 639             // Ok, now what are we supposed to call here?
 640             if (entityType == DOCTYPE) {
 641                 resolved = c.resolveDoctype(entityName,
 642                                             publicId,
 643                                             systemId);
 644                 if (resolved != null) {
 645                     // Only find one DOCTYPE resolution
 646                     resolutions.addElement(resolved);
 647                     return resolutions;
 648                 }
 649             } else if (entityType == DOCUMENT) {
 650                 resolved = c.resolveDocument();
 651                 if (resolved != null) {
 652                     // Only find one DOCUMENT resolution
 653                     resolutions.addElement(resolved);
 654                     return resolutions;
 655                 }
 656             } else if (entityType == ENTITY) {
 657                 resolved = c.resolveEntity(entityName,
 658                                            publicId,
 659                                            systemId);
 660                 if (resolved != null) {
 661                     // Only find one ENTITY resolution
 662                     resolutions.addElement(resolved);
 663                     return resolutions;
 664                 }
 665             } else if (entityType == NOTATION) {
 666                 resolved = c.resolveNotation(entityName,
 667                                              publicId,
 668                                              systemId);
 669                 if (resolved != null) {
 670                     // Only find one NOTATION resolution
 671                     resolutions.addElement(resolved);
 672                     return resolutions;
 673                 }
 674             } else if (entityType == PUBLIC) {
 675                 resolved = c.resolvePublic(publicId, systemId);
 676                 if (resolved != null) {
 677                     // Only find one PUBLIC resolution
 678                     resolutions.addElement(resolved);
 679                     return resolutions;
 680                 }
 681             } else if (entityType == SYSTEM) {
 682                 Vector localResolutions = c.resolveAllSystem(systemId);
 683                 resolutions = appendVector(resolutions, localResolutions);
 684                 break;
 685             } else if (entityType == SYSTEMREVERSE) {
 686                 Vector localResolutions = c.resolveAllSystemReverse(systemId);
 687                 resolutions = appendVector(resolutions, localResolutions);
 688             }
 689         }
 690 
 691         if (resolutions != null) {
 692             return resolutions;
 693         } else {
 694             return null;
 695         }
 696     }
 697 }