1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2002,2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.utils;
  22 
  23 import java.io.File;
  24 import java.io.FileInputStream;
  25 import java.io.FileNotFoundException;
  26 import java.io.IOException;
  27 import java.io.InputStream;
  28 import java.net.URL;
  29 import java.security.AccessController;
  30 import java.security.PrivilegedAction;
  31 import java.security.PrivilegedActionException;
  32 import java.security.PrivilegedExceptionAction;
  33 import java.util.Locale;
  34 import java.util.MissingResourceException;
  35 import java.util.Properties;
  36 import java.util.PropertyResourceBundle;
  37 import java.util.ResourceBundle;
  38 
  39 /**
  40  * This class is duplicated for each subpackage so keep it in sync.
  41  * It is package private and therefore is not exposed as part of any API.
  42  *
  43  * @xerces.internal
  44  */
  45 public final class SecuritySupport {
  46 
  47     private static final SecuritySupport securitySupport = new SecuritySupport();
  48 
  49     /**
  50      * Return an instance of this class.
  51      */
  52     public static SecuritySupport getInstance() {
  53         return securitySupport;
  54     }
  55 
  56     static ClassLoader getContextClassLoader() {
  57         return (ClassLoader)
  58         AccessController.doPrivileged(new PrivilegedAction() {
  59             public Object run() {
  60                 ClassLoader cl = null;
  61                 try {
  62                     cl = Thread.currentThread().getContextClassLoader();
  63                 } catch (SecurityException ex) { }
  64                 return cl;
  65             }
  66         });
  67     }
  68 
  69     static ClassLoader getSystemClassLoader() {
  70         return (ClassLoader)
  71         AccessController.doPrivileged(new PrivilegedAction() {
  72             public Object run() {
  73                 ClassLoader cl = null;
  74                 try {
  75                     cl = ClassLoader.getSystemClassLoader();
  76                 } catch (SecurityException ex) {}
  77                 return cl;
  78             }
  79         });
  80     }
  81 
  82     static ClassLoader getParentClassLoader(final ClassLoader cl) {
  83         return (ClassLoader)
  84         AccessController.doPrivileged(new PrivilegedAction() {
  85             public Object run() {
  86                 ClassLoader parent = null;
  87                 try {
  88                     parent = cl.getParent();
  89                 } catch (SecurityException ex) {}
  90 
  91                 // eliminate loops in case of the boot
  92                 // ClassLoader returning itself as a parent
  93                 return (parent == cl) ? null : parent;
  94             }
  95         });
  96     }
  97 
  98     public static String getSystemProperty(final String propName) {
  99         return (String)
 100         AccessController.doPrivileged(new PrivilegedAction() {
 101             public Object run() {
 102                 return System.getProperty(propName);
 103             }
 104         });
 105     }
 106 
 107     static FileInputStream getFileInputStream(final File file)
 108     throws FileNotFoundException
 109     {
 110         try {
 111             return (FileInputStream)
 112             AccessController.doPrivileged(new PrivilegedExceptionAction() {
 113                 public Object run() throws FileNotFoundException {
 114                     return new FileInputStream(file);
 115                 }
 116             });
 117         } catch (PrivilegedActionException e) {
 118             throw (FileNotFoundException)e.getException();
 119         }
 120     }
 121     /**
 122      * Return resource using the same classloader for the ObjectFactory by default
 123      * or bootclassloader when Security Manager is in place
 124      */
 125     public static InputStream getResourceAsStream(final String name) {
 126         if (System.getSecurityManager()!=null) {
 127             return getResourceAsStream(null, name);
 128         } else {
 129             return getResourceAsStream(ObjectFactory.findClassLoader(), name);
 130         }
 131     }
 132 
 133     public static InputStream getResourceAsStream(final ClassLoader cl,
 134             final String name)
 135     {
 136         return (InputStream)
 137         AccessController.doPrivileged(new PrivilegedAction() {
 138             public Object run() {
 139                 InputStream ris;
 140                 if (cl == null) {
 141                     ris = Object.class.getResourceAsStream("/"+name);
 142                 } else {
 143                     ris = cl.getResourceAsStream(name);
 144                 }
 145                 return ris;
 146             }
 147         });
 148     }
 149 
 150     /**
 151      * Gets a resource bundle using the specified base name, the default locale, and the caller's class loader.
 152      * @param bundle the base name of the resource bundle, a fully qualified class name
 153      * @return a resource bundle for the given base name and the default locale
 154      */
 155     public static ResourceBundle getResourceBundle(String bundle) {
 156         return getResourceBundle(bundle, Locale.getDefault());
 157     }
 158 
 159     /**
 160      * Gets a resource bundle using the specified base name and locale, and the caller's class loader.
 161      * @param bundle the base name of the resource bundle, a fully qualified class name
 162      * @param locale the locale for which a resource bundle is desired
 163      * @return a resource bundle for the given base name and locale
 164      */
 165     public static ResourceBundle getResourceBundle(final String bundle, final Locale locale) {
 166         return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
 167             public ResourceBundle run() {
 168                 try {
 169                     return PropertyResourceBundle.getBundle(bundle, locale);
 170                 } catch (MissingResourceException e) {
 171                     try {
 172                         return PropertyResourceBundle.getBundle(bundle, new Locale("en", "US"));
 173                     } catch (MissingResourceException e2) {
 174                         throw new MissingResourceException(
 175                                 "Could not load any resource bundle by " + bundle, bundle, "");
 176                     }
 177                 }
 178             }
 179         });
 180     }
 181 
 182     static boolean getFileExists(final File f) {
 183         return ((Boolean)
 184                 AccessController.doPrivileged(new PrivilegedAction() {
 185                     public Object run() {
 186                         return f.exists() ? Boolean.TRUE : Boolean.FALSE;
 187                     }
 188                 })).booleanValue();
 189     }
 190 
 191     static long getLastModified(final File f) {
 192         return ((Long)
 193                 AccessController.doPrivileged(new PrivilegedAction() {
 194                     public Object run() {
 195                         return new Long(f.lastModified());
 196                     }
 197                 })).longValue();
 198     }
 199 
 200     /**
 201      * Strip off path from an URI
 202      *
 203      * @param uri an URI with full path
 204      * @return the file name only
 205      */
 206     public static String sanitizePath(String uri) {
 207         if (uri == null) {
 208             return "";
 209         }
 210         int i = uri.lastIndexOf("/");
 211         if (i > 0) {
 212             return uri.substring(i+1, uri.length());
 213         }
 214         return "";
 215     }
 216 
 217     /**
 218      * Check the protocol used in the systemId against allowed protocols
 219      *
 220      * @param systemId the Id of the URI
 221      * @param allowedProtocols a list of allowed protocols separated by comma
 222      * @param accessAny keyword to indicate allowing any protocol
 223      * @return the name of the protocol if rejected, null otherwise
 224      */
 225     public static String checkAccess(String systemId, String allowedProtocols, String accessAny) throws IOException {
 226         if (systemId == null || (allowedProtocols != null && 
 227                 allowedProtocols.equalsIgnoreCase(accessAny))) {
 228             return null;
 229         }
 230 
 231         String protocol;
 232         if (systemId.indexOf(":")==-1) {
 233             protocol = "file";
 234         } else {
 235             URL url = new URL(systemId);
 236             protocol = url.getProtocol();
 237             if (protocol.equalsIgnoreCase("jar")) {
 238                 String path = url.getPath();
 239                 protocol = path.substring(0, path.indexOf(":"));
 240             }
 241         }
 242 
 243         if (isProtocolAllowed(protocol, allowedProtocols)) {
 244             //access allowed
 245             return null;
 246         } else {
 247             return protocol;
 248         }
 249     }
 250 
 251     /**
 252      * Check if the protocol is in the allowed list of protocols. The check
 253      * is case-insensitive while ignoring whitespaces.
 254      *
 255      * @param protocol a protocol
 256      * @param allowedProtocols a list of allowed protocols
 257      * @return true if the protocol is in the list
 258      */
 259     private static boolean isProtocolAllowed(String protocol, String allowedProtocols) {
 260          if (allowedProtocols == null) {
 261              return false;
 262          }
 263          String temp[] = allowedProtocols.split(",");
 264          for (String t : temp) {
 265              t = t.trim();
 266              if (t.equalsIgnoreCase(protocol)) {
 267                  return true;
 268              }
 269          }
 270          return false;
 271      }
 272 
 273     /**
 274      * Read JAXP system property in this order: system property,
 275      * $java.home/lib/jaxp.properties if the system property is not specified
 276      *
 277      * @param propertyId the Id of the property
 278      * @return the value of the property
 279      */
 280     public static String getJAXPSystemProperty(String sysPropertyId) {
 281         String accessExternal = getSystemProperty(sysPropertyId);
 282         if (accessExternal == null) {
 283             accessExternal = readJAXPProperty(sysPropertyId);
 284         }
 285         return accessExternal;
 286     }
 287 
 288      /**
 289      * Read from $java.home/lib/jaxp.properties for the specified property
 290      * The program
 291      *
 292      * @param propertyId the Id of the property
 293      * @return the value of the property
 294      */
 295     static String readJAXPProperty(String propertyId) {
 296         String value = null;
 297         InputStream is = null;
 298         try {
 299             if (firstTime) {
 300                 synchronized (cacheProps) {
 301                     if (firstTime) {
 302                         String configFile = getSystemProperty("java.home") + File.separator +
 303                             "lib" + File.separator + "jaxp.properties";
 304                         File f = new File(configFile);
 305                         if (getFileExists(f)) {
 306                             is = getFileInputStream(f);
 307                             cacheProps.load(is);
 308                         }
 309                         firstTime = false;
 310                     }
 311                 }
 312             }
 313             value = cacheProps.getProperty(propertyId);
 314 
 315         }
 316         catch (Exception ex) {}
 317         finally {
 318             if (is != null) {
 319                 try {
 320                     is.close();
 321                 } catch (IOException ex) {}
 322             }
 323         }
 324 
 325         return value;
 326     }
 327 
 328    /**
 329      * Cache for properties in java.home/lib/jaxp.properties
 330      */
 331     static final Properties cacheProps = new Properties();
 332 
 333     /**
 334      * Flag indicating if the program has tried reading java.home/lib/jaxp.properties
 335      */
 336     static volatile boolean firstTime = true;
 337 
 338     private SecuritySupport () {}
 339 }