/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.utils; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apereo.portal.ResourceMissingException; import org.apereo.portal.properties.PropertiesManager; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * This utility provides methods for accessing resources. The methods generally use the classpath to * find the resource if the requested URL isn't already specified as a fully-qualified URL string. * * <p>The methods of this class sort of replace the old UtiltiesBean.fixURI() method. * * @since 2.0 * @deprecated use CachingResourceLoader */ @Deprecated public class ResourceLoader { private static final Log log = LogFactory.getLog(ResourceLoader.class); private static DocumentBuilderFactory validatingDocumentBuilderFactory; private static DocumentBuilderFactory nonValidatingDocumentBuilderFactory; private static Map<Tuple<Class<?>, String>, URL> resourceUrlCache; private static Map<Tuple<Class<?>, String>, ResourceMissingException> resourceUrlNotFoundCache; static { validatingDocumentBuilderFactory = DocumentBuilderFactory.newInstance(); nonValidatingDocumentBuilderFactory = DocumentBuilderFactory.newInstance(); validatingDocumentBuilderFactory.setValidating(true); nonValidatingDocumentBuilderFactory.setValidating(false); validatingDocumentBuilderFactory.setNamespaceAware(true); nonValidatingDocumentBuilderFactory.setNamespaceAware(true); try { String handler = PropertiesManager.getProperty( "org.apereo.portal.utils.ResourceLoader.HttpsHandler"); if ((System.getProperty("java.protocol.handler.pkgs") != null) && !(System.getProperty("java.protocol.handler.pkgs").equals(""))) { handler = handler + "|" + System.getProperty("java.protocol.handler.pkgs"); } System.setProperty("java.protocol.handler.pkgs", handler); } catch (Exception e) { log.error("Unable to set HTTPS Protocol handler", e); } } /** @return the resourceUrlCache */ public Map<Tuple<Class<?>, String>, URL> getResourceUrlCache() { return resourceUrlCache; } /** @param resourceUrlCache the resourceUrlCache to set */ public void setResourceUrlCache(Map<Tuple<Class<?>, String>, URL> resourceUrlCache) { ResourceLoader.resourceUrlCache = resourceUrlCache; } /** @return the resourceUrlNotFoundCache */ public Map<Tuple<Class<?>, String>, ResourceMissingException> getResourceUrlNotFoundCache() { return resourceUrlNotFoundCache; } /** @param resourceUrlNotFoundCache the resourceUrlNotFoundCache to set */ public void setResourceUrlNotFoundCache( Map<Tuple<Class<?>, String>, ResourceMissingException> resourceUrlNotFoundCache) { ResourceLoader.resourceUrlNotFoundCache = resourceUrlNotFoundCache; } /** * Finds a resource with a given name. This is a convenience method for accessing a resource * from a channel or from the uPortal framework. If a well-formed URL is passed in, this method * will use that URL unchanged to find the resource. If the URL is not well-formed, this method * will look for the desired resource relative to the classpath. If the resource name starts * with "/", it is unchanged. Otherwise, the package name of the requesting class is prepended * to the resource name. * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource to load * @return a URL identifying the requested resource * @throws ResourceMissingException */ public static URL getResourceAsURL(Class<?> requestingClass, String resource) throws ResourceMissingException { final Tuple<Class<?>, String> cacheKey = new Tuple<Class<?>, String>(requestingClass, resource); //Look for a cached URL final Map<Tuple<Class<?>, String>, URL> resourceUrlCache = ResourceLoader.resourceUrlCache; URL resourceURL = resourceUrlCache != null ? resourceUrlCache.get(cacheKey) : null; if (resourceURL != null) { return resourceURL; } //Look for a failed lookup final Map<Tuple<Class<?>, String>, ResourceMissingException> resourceUrlNotFoundCache = ResourceLoader.resourceUrlNotFoundCache; ResourceMissingException exception = resourceUrlNotFoundCache != null ? resourceUrlNotFoundCache.get(cacheKey) : null; if (exception != null) { throw new ResourceMissingException(exception); } try { resourceURL = new URL(resource); } catch (MalformedURLException murle) { // URL is invalid, now try to load from classpath resourceURL = requestingClass.getResource(resource); if (resourceURL == null) { String resourceRelativeToClasspath = null; if (resource.startsWith("/")) resourceRelativeToClasspath = resource; else resourceRelativeToClasspath = '/' + requestingClass.getPackage().getName().replace('.', '/') + '/' + resource; exception = new ResourceMissingException( resource, resourceRelativeToClasspath, "Resource not found in classpath: " + resourceRelativeToClasspath); if (resourceUrlNotFoundCache != null) { resourceUrlNotFoundCache.put(cacheKey, exception); } throw new ResourceMissingException(exception); } } if (resourceUrlCache != null) { resourceUrlCache.put(cacheKey, resourceURL); } return resourceURL; } /** * Returns the requested resource as a URL string. * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource to load * @return the requested resource as a URL string * @throws ResourceMissingException */ public static String getResourceAsURLString(Class<?> requestingClass, String resource) throws ResourceMissingException { return getResourceAsURL(requestingClass, resource).toString(); } public static long getResourceLastModified(Class<?> requestingClass, String resource) { final URL contentUrl = getResourceAsURL(requestingClass, resource); final String contentFileName = contentUrl.getFile(); //Use JAR modified time if the resource is in a .jar file denoted by ! delimeter final int delimIndex = contentFileName.indexOf('!'); final File contentFile; if (delimIndex > 0) { contentFile = new File(contentFileName.substring(0, delimIndex)); } else { contentFile = new File(contentFileName); } return contentFile.lastModified(); } /** * Returns the requested resource as a stream. * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource to load * @return the requested resource as a stream * @throws ResourceMissingException * @throws java.io.IOException */ public static InputStream getResourceAsStream(Class<?> requestingClass, String resource) throws ResourceMissingException, IOException { return getResourceAsURL(requestingClass, resource).openStream(); } /** * Returns the requested resource as a SAX input source. * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource to load * @return the requested resource as a SAX input source * @throws ResourceMissingException * @throws java.io.IOException */ public static InputSource getResourceAsSAXInputSource(Class<?> requestingClass, String resource) throws ResourceMissingException, IOException { URL url = getResourceAsURL(requestingClass, resource); InputSource source = new InputSource(url.openStream()); source.setPublicId(url.toExternalForm()); return source; } /** * Get the contents of a URL as an XML Document * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource whose contents to * load * @param validate boolean. True if the document builder factory should validate, false * otherwise. * @return the actual contents of the resource as an XML Document * @throws ResourceMissingException * @throws java.io.IOException * @throws javax.xml.parsers.ParserConfigurationException * @throws org.xml.sax.SAXException */ public static Document getResourceAsDocument( Class<?> requestingClass, String resource, boolean validate) throws ResourceMissingException, IOException, ParserConfigurationException, SAXException { Document document = null; InputStream inputStream = null; try { DocumentBuilderFactory factoryToUse = null; if (validate) { factoryToUse = ResourceLoader.validatingDocumentBuilderFactory; } else { factoryToUse = ResourceLoader.nonValidatingDocumentBuilderFactory; } inputStream = getResourceAsStream(requestingClass, resource); DocumentBuilder db = factoryToUse.newDocumentBuilder(); db.setEntityResolver(new DTDResolver()); db.setErrorHandler( new SAXErrorHandler("ResourceLoader.getResourceAsDocument(" + resource + ")")); document = db.parse(inputStream); } finally { if (inputStream != null) inputStream.close(); } return document; } /** * Get the contents of a URL as an XML Document, first trying to read the Document with * validation turned on, and falling back to reading it with validation turned off. * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource whose contents to * load * @return the actual contents of the resource as an XML Document * @throws ResourceMissingException * @throws java.io.IOException * @throws javax.xml.parsers.ParserConfigurationException * @throws org.xml.sax.SAXException */ public static Document getResourceAsDocument(Class<?> requestingClass, String resource) throws ResourceMissingException, IOException, ParserConfigurationException, SAXException { // Default is non-validating... return getResourceAsDocument(requestingClass, resource, false); } /** * Get the contents of a URL as a java.util.Properties object * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource whose contents to * load * @return the actual contents of the resource as a Properties object * @throws ResourceMissingException * @throws java.io.IOException */ public static Properties getResourceAsProperties(Class<?> requestingClass, String resource) throws ResourceMissingException, IOException { InputStream inputStream = null; Properties props = null; try { inputStream = getResourceAsStream(requestingClass, resource); props = new Properties(); props.load(inputStream); } finally { if (inputStream != null) inputStream.close(); } return props; } /** * Get the contents of a URL as a String * * @param requestingClass the java.lang.Class object of the class that is attempting to load the * resource * @param resource a String describing the full or partial URL of the resource whose contents to * load * @return the actual contents of the resource as a String * @throws ResourceMissingException * @throws java.io.IOException */ public static String getResourceAsString(Class<?> requestingClass, String resource) throws ResourceMissingException, IOException { String line = null; BufferedReader in = null; StringBuffer sbText = null; try { in = new BufferedReader( new InputStreamReader(getResourceAsStream(requestingClass, resource))); sbText = new StringBuffer(1024); while ((line = in.readLine()) != null) sbText.append(line).append("\n"); } finally { if (in != null) in.close(); } return sbText.toString(); } }