jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java
changeset 43121 e73af7b6ce47
parent 40582 1dddef49982c
child 43358 9e2d943b5b66
equal deleted inserted replaced
43040:ab2c8b03c328 43121:e73af7b6ce47
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 package javax.xml.catalog;
    25 package javax.xml.catalog;
    26 
    26 
    27 import java.io.File;
    27 import java.io.File;
       
    28 import java.io.IOException;
    28 import java.net.MalformedURLException;
    29 import java.net.MalformedURLException;
    29 import java.net.URI;
    30 import java.net.URI;
    30 import java.net.URISyntaxException;
       
    31 import java.net.URL;
       
    32 import java.nio.file.Path;
       
    33 import java.nio.file.Paths;
       
    34 import java.util.Iterator;
    31 import java.util.Iterator;
       
    32 import java.util.jar.JarEntry;
       
    33 import java.util.jar.JarFile;
       
    34 import static javax.xml.catalog.CatalogFeatures.DEFER_FALSE;
       
    35 import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
       
    36 import javax.xml.catalog.CatalogFeatures.Feature;
       
    37 import static javax.xml.catalog.CatalogFeatures.PREFER_PUBLIC;
       
    38 import static javax.xml.catalog.CatalogFeatures.PREFER_SYSTEM;
       
    39 import static javax.xml.catalog.CatalogFeatures.RESOLVE_CONTINUE;
       
    40 import static javax.xml.catalog.CatalogFeatures.RESOLVE_IGNORE;
       
    41 import static javax.xml.catalog.CatalogFeatures.RESOLVE_STRICT;
    35 import jdk.xml.internal.SecuritySupport;
    42 import jdk.xml.internal.SecuritySupport;
    36 
    43 
    37 /**
    44 /**
    38  *
    45  *
    39  * @since 9
    46  * @since 9
    40  */
    47  */
    41 class Util {
    48 class Util {
       
    49 
    42     final static String URN = "urn:publicid:";
    50     final static String URN = "urn:publicid:";
    43     final static String PUBLICID_PREFIX = "-//";
    51     final static String PUBLICID_PREFIX = "-//";
    44     final static String PUBLICID_PREFIX_ALT = "+//";
    52     final static String PUBLICID_PREFIX_ALT = "+//";
       
    53     final static String SCHEME_FILE = "file";
       
    54     final static String SCHEME_JAR = "jar";
       
    55     final static String SCHEME_JARFILE = "jar:file:";
    45 
    56 
    46     /**
    57     /**
    47      * Finds an entry in the catalog that matches with the publicId or systemId.
    58      * Finds an entry in the catalog that matches with the publicId or systemId.
    48      *
    59      *
    49      * The resolution follows the following rules determined by the prefer setting:
    60      * The resolution follows the following rules determined by the prefer
    50      *
    61      * setting:
    51      * prefer "system": attempts to resolve with a system entry;
    62      *
    52      *                  attempts to resolve with a public entry when only
    63      * prefer "system": attempts to resolve with a system entry; attempts to
    53      *                  publicId is specified.
    64      * resolve with a public entry when only publicId is specified.
    54      *
    65      *
    55      * prefer "public": attempts to resolve with a system entry;
    66      * prefer "public": attempts to resolve with a system entry; attempts to
    56      *                  attempts to resolve with a public entry if no matching
    67      * resolve with a public entry if no matching system entry is found.
    57      *                  system entry is found.
       
    58      *
    68      *
    59      * If no match is found, continue searching uri entries
    69      * If no match is found, continue searching uri entries
    60      *
    70      *
    61      * @param catalog the catalog
    71      * @param catalog the catalog
    62      * @param publicId the publicId
    72      * @param publicId the publicId
    68 
    78 
    69         //search the current catalog
    79         //search the current catalog
    70         catalog.reset();
    80         catalog.reset();
    71         if (systemId != null) {
    81         if (systemId != null) {
    72             /*
    82             /*
    73                If a system identifier is specified, it is used no matter how
    83              If a system identifier is specified, it is used no matter how
    74             prefer is set.
    84              prefer is set.
    75             */
    85              */
    76             resolvedSystemId = catalog.matchSystem(systemId);
    86             resolvedSystemId = catalog.matchSystem(systemId);
    77         }
    87         }
    78 
    88 
    79         if (resolvedSystemId == null && publicId != null) {
    89         if (resolvedSystemId == null && publicId != null) {
    80             resolvedSystemId = catalog.matchPublic(publicId);
    90             resolvedSystemId = catalog.matchPublic(publicId);
    89 
    99 
    90         //search alternative catalogs
   100         //search alternative catalogs
    91         if (resolvedSystemId == null) {
   101         if (resolvedSystemId == null) {
    92             Iterator<Catalog> iter = catalog.catalogs().iterator();
   102             Iterator<Catalog> iter = catalog.catalogs().iterator();
    93             while (iter.hasNext()) {
   103             while (iter.hasNext()) {
    94                 resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
   104                 resolvedSystemId = resolve((CatalogImpl) iter.next(), publicId, systemId);
    95                 if (resolvedSystemId != null) {
   105                 if (resolvedSystemId != null) {
    96                     break;
   106                     break;
    97                 }
   107                 }
    98 
   108 
    99             }
   109             }
   100         }
   110         }
   101 
   111 
   102         return resolvedSystemId;
   112         return resolvedSystemId;
   103     }
   113     }
   104 
   114 
   105     /**
   115     static void validateUrisSyntax(URI... uris) {
   106      * Resolves the specified file path to an absolute systemId. If it is
   116         for (URI uri : uris) {
   107      * relative, it shall be resolved using the base or user.dir property if
   117             validateUriSyntax(uri);
   108      * base is not specified.
   118         }
   109      *
   119     }
   110      * @param file The specified file path
   120 
   111      * @param baseURI the base URI
   121     static void validateUrisSyntax(String... uris) {
   112      * @return The URI
   122         for (String uri : uris) {
   113      * @throws CatalogException if the specified file path can not be converted
   123             validateUriSyntax(URI.create(uri));
   114      * to a system id
   124         }
   115      */
   125     }
   116     static URI verifyAndGetURI(String file, URL baseURI)
   126 
   117             throws MalformedURLException, URISyntaxException, IllegalArgumentException {
   127     /**
   118         URL filepath;
   128      * Validate that the URI must be absolute and a valid URL.
   119         URI temp;
   129      *
   120         if (file != null && file.length() > 0) {
   130      * Note that this method does not verify the existence of the resource. The
   121             File f = new File(file);
   131      * Catalog standard requires that such resources be ignored.
   122 
   132      *
   123             if (baseURI != null && !f.isAbsolute()) {
   133      * @param uri
   124                 filepath = new URL(baseURI, fixSlashes(file));
   134      * @throws IllegalArgumentException if the uri is not absolute and a valid
   125                 temp = filepath.toURI();
   135      * URL
   126             } else {
   136      */
   127                 temp = resolveURI(file);
   137     static void validateUriSyntax(URI uri) {
   128             }
   138         CatalogMessages.reportNPEOnNull("URI input", uri);
   129             //Paths.get may throw IllegalArgumentException
   139 
   130             Path path = Paths.get(temp);
   140         if (!uri.isAbsolute()) {
   131             if (path.toFile().isFile()) {
   141             CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTABSOLUTE,
   132                 return temp;
   142                     new Object[]{uri}, null);
   133             }
   143         }
   134         }
   144 
   135         return null;
       
   136     }
       
   137 
       
   138     /**
       
   139      * Resolves the specified uri. If the uri is relative, makes it absolute by
       
   140      * the user.dir directory.
       
   141      *
       
   142      * @param uri The specified URI.
       
   143      * @return The resolved URI
       
   144      */
       
   145     static URI resolveURI(String uri) throws MalformedURLException {
       
   146         if (uri == null) {
       
   147             uri = "";
       
   148         }
       
   149 
       
   150         URI temp = null;
       
   151         try {
   145         try {
   152             URL url = new URL(uri);
   146             // check if the scheme was valid
   153             temp = url.toURI();
   147             uri.toURL();
   154         } catch (MalformedURLException | URISyntaxException mue) {
   148         } catch (MalformedURLException ex) {
   155             File file = new File(uri);
   149             CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
   156             temp = file.toURI();
   150                     new Object[]{uri}, null);
   157         }
   151         }
   158 
   152 
   159         return temp;
   153         // verify the resource exists where possible
   160     }
   154         if (isFileUri(uri)) {
   161 
   155             if (!isFileUriExist(uri, false)) {
   162     /**
   156                 CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
   163      * Replace backslashes with forward slashes. (URLs always use forward
   157                         new Object[]{uri}, null);
   164      * slashes.)
   158             }
   165      *
   159         }
   166      * @param sysid The input system identifier.
   160     }
   167      * @return The same system identifier with backslashes turned into forward
   161 
   168      * slashes.
   162     /**
   169      */
   163      * Checks whether the URI is a file URI, including JAR file.
   170     static String fixSlashes(String sysid) {
   164      *
   171         return sysid.replace('\\', '/');
   165      * @param uri the specified URI.
       
   166      * @return true if it is a file or JAR file URI, false otherwise
       
   167      */
       
   168     static boolean isFileUri(URI uri) {
       
   169         if (SCHEME_FILE.equals(uri.getScheme())
       
   170                 || SCHEME_JAR.equals(uri.getScheme())) {
       
   171             return true;
       
   172         }
       
   173         return false;
       
   174     }
       
   175 
       
   176     /**
       
   177      * Verifies whether the file resource exists.
       
   178      *
       
   179      * @param uri the URI to locate the resource
       
   180      * @param openJarFile a flag to indicate whether a JAR file should be
       
   181      * opened. This operation may be expensive.
       
   182      * @return true if the resource exists, false otherwise.
       
   183      */
       
   184     static boolean isFileUriExist(URI uri, boolean openJarFile) {
       
   185         if (uri != null && uri.isAbsolute()) {
       
   186             if (null != uri.getScheme()) {
       
   187                 switch (uri.getScheme()) {
       
   188                     case SCHEME_FILE:
       
   189                         String path = uri.getPath();
       
   190                         File f1 = new File(path);
       
   191                         if (f1.isFile()) {
       
   192                             return true;
       
   193                         }
       
   194                         break;
       
   195                     case SCHEME_JAR:
       
   196                         String tempUri = uri.toString();
       
   197                         int pos = tempUri.indexOf("!");
       
   198                         if (pos < 0) {
       
   199                             return false;
       
   200                         }
       
   201                         if (openJarFile) {
       
   202                             String jarFile = tempUri.substring(SCHEME_JARFILE.length(), pos);
       
   203                             String entryName = tempUri.substring(pos + 2);
       
   204                             try {
       
   205                                 JarFile jf = new JarFile(jarFile);
       
   206                                 JarEntry je = jf.getJarEntry(entryName);
       
   207                                 if (je != null) {
       
   208                                     return true;
       
   209                                 }
       
   210                             } catch (IOException ex) {
       
   211                                 return false;
       
   212                             }
       
   213                         } else {
       
   214                             return true;
       
   215                         }
       
   216                         break;
       
   217                 }
       
   218             }
       
   219         }
       
   220         return false;
   172     }
   221     }
   173 
   222 
   174     /**
   223     /**
   175      * Find catalog file paths by reading the system property, and then
   224      * Find catalog file paths by reading the system property, and then
   176      * jaxp.properties if the system property is not specified.
   225      * jaxp.properties if the system property is not specified.
   185         }
   234         }
   186         return null;
   235         return null;
   187     }
   236     }
   188 
   237 
   189     /**
   238     /**
   190      * Checks whether the specified string is null or empty, returns the original
   239      * Checks whether the specified string is null or empty, returns the
   191      * string with leading and trailing spaces removed if not.
   240      * original string with leading and trailing spaces removed if not.
       
   241      *
   192      * @param test the string to be tested
   242      * @param test the string to be tested
   193      * @return the original string with leading and trailing spaces removed,
   243      * @return the original string with leading and trailing spaces removed, or
   194      * or null if it is null or empty
   244      * null if it is null or empty
   195      *
   245      *
   196      */
   246      */
   197     static String getNotNullOrEmpty(String test) {
   247     static String getNotNullOrEmpty(String test) {
   198         if (test == null) {
   248         if (test == null) {
   199             return test;
   249             return test;
   204             } else {
   254             } else {
   205                 return temp;
   255                 return temp;
   206             }
   256             }
   207         }
   257         }
   208     }
   258     }
       
   259 
       
   260     /**
       
   261      * Validates the input for features.
       
   262      *
       
   263      * @param f the feature
       
   264      * @param value the value
       
   265      * @throws IllegalArgumentException if the value is invalid for the feature
       
   266      */
       
   267     static void validateFeatureInput(Feature f, String value) {
       
   268         CatalogMessages.reportNPEOnNull(f.name(), value);
       
   269         if (value.length() == 0) {
       
   270             CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
       
   271                     new Object[]{value, f.name()}, null);
       
   272         }
       
   273 
       
   274         if (f == Feature.PREFER) {
       
   275             if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
       
   276                 CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
       
   277                         new Object[]{value, Feature.PREFER.name()}, null);
       
   278             }
       
   279         } else if (f == Feature.DEFER) {
       
   280             if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
       
   281                 CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
       
   282                         new Object[]{value, Feature.DEFER.name()}, null);
       
   283             }
       
   284         } else if (f == Feature.RESOLVE) {
       
   285             if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
       
   286                     && !value.equals(RESOLVE_IGNORE)) {
       
   287                 CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
       
   288                         new Object[]{value, Feature.RESOLVE.name()}, null);
       
   289             }
       
   290         } else if (f == Feature.FILES) {
       
   291             Util.validateUrisSyntax(value.split(";"));
       
   292         }
       
   293     }
   209 }
   294 }