1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.xml.catalog;
  26 
  27 import java.io.StringReader;
  28 import java.util.Iterator;
  29 import org.xml.sax.InputSource;
  30 
  31 /**
  32  * A SAX EntityResolver/JAXP URIResolver that uses catalogs.
  33  *
  34  * <p>
  35  * This class implements both a SAX EntityResolver and a JAXP URIResolver.
  36  *
  37  *
  38  * @since 9
  39  */
  40 final class CatalogResolverImpl implements CatalogResolver {
  41     Catalog catalog;
  42 
  43     /**
  44      * Construct an instance of the CatalogResolver from a Catalog.
  45      *
  46      * @param catalog A Catalog.
  47      */
  48     public CatalogResolverImpl(Catalog catalog) {
  49         this.catalog = catalog;
  50     }
  51 
  52     @Override
  53     public InputSource resolveEntity(String publicId, String systemId) {
  54         //Normalize publicId and systemId
  55         systemId = Normalizer.normalizeURI(systemId);
  56         publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(publicId));
  57 
  58         //check whether systemId is an urn
  59         if (systemId != null && systemId.startsWith("urn:publicid:")) {
  60             systemId = Normalizer.decodeURN(systemId);
  61             if (publicId != null && !publicId.equals(systemId)) {
  62                 systemId = null;
  63             } else {
  64                 publicId = systemId;
  65                 systemId = null;
  66             }
  67         }
  68 
  69         CatalogImpl c = (CatalogImpl)catalog;
  70         String resolvedSystemId = resolve(c, publicId, systemId);
  71 
  72         if (resolvedSystemId != null) {
  73             return new InputSource(resolvedSystemId);
  74         }
  75 
  76         GroupEntry.ResolveType resolveType = ((CatalogImpl) catalog).getResolve();
  77         switch (resolveType) {
  78             case IGNORE:
  79                 return new InputSource(new StringReader(""));
  80             case STRICT:
  81                 CatalogMessages.reportError(CatalogMessages.ERR_NO_MATCH,
  82                         new Object[]{publicId, systemId});
  83         }
  84 
  85         //no action, allow the parser to continue
  86         return null;
  87     }
  88 
  89     /**
  90      * Resolves the publicId or systemId to one specified in the catalog.
  91      * @param catalog the catalog
  92      * @param publicId the publicId
  93      * @param systemId the systemId
  94      * @return the resolved systemId if a match is found, null otherwise
  95      */
  96     String resolve(CatalogImpl catalog, String publicId, String systemId) {
  97         String resolvedSystemId = null;
  98 
  99         //search the current catalog
 100         catalog.reset();
 101         if (systemId != null) {
 102             resolvedSystemId = catalog.matchSystem(systemId);
 103         }
 104         if (resolvedSystemId == null) {
 105             resolvedSystemId = catalog.matchPublic(publicId);
 106         }
 107 
 108         //mark the catalog as having been searched before trying alternatives
 109         catalog.markAsSearched();
 110 
 111         //search alternative catalogs
 112         if (resolvedSystemId == null) {
 113             Iterator<Catalog> iter = catalog.catalogs().iterator();
 114             while (iter.hasNext()) {
 115                 resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
 116                 if (resolvedSystemId != null) {
 117                     break;
 118                 }
 119 
 120             }
 121         }
 122 
 123         return resolvedSystemId;
 124     }
 125 }