All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jsftemplating.util.FileUtil Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://jsftemplating.dev.java.net/cddl1.html or
 * jsftemplating/cddl1.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at jsftemplating/cddl1.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.jsftemplating.util;

import com.sun.jsftemplating.layout.LayoutDefinitionException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;


/**
 *  

This class is for general purpose utility methods.

* * @author Ken Paulsen ([email protected]) */ public class FileUtil { /** *

This method calculates the system path to the given filename that * is relative to the docroot. It takes the * ServletContext or PortletContext (which * is why this method takes an Object for this parameter) * and the relative path to find. It then invokes the * getRealPath(String) method of the * ServletContext / PortletContext and * returns the result. This method uses reflection.

*/ public static String getRealPath(Object ctx, String relativePath) { String path = null; // The following should work w/ a ServletContext or PortletContext Method method = null; try { method = ctx.getClass().getMethod("getRealPath", REALPATH_ARGS); } catch (NoSuchMethodException ex) { throw new RuntimeException(ex); } try { path = (String) method.invoke(ctx, new Object [] {relativePath}); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { throw new RuntimeException(ex); } // Return Result return path; } /** *

This method checks for the relPath in the docroot of * the application. This should work in both Portlet and Servlet * environments. If FacesContext is null, null will be * returned.

*/ public static URL getResource(String relPath) { FacesContext facesContext = FacesContext.getCurrentInstance(); if (facesContext == null) { return null; } Object ctx = facesContext.getExternalContext().getContext(); URL url = null; // The following should work w/ a ServletContext or PortletContext Method method = null; try { method = ctx.getClass().getMethod( "getResource", GET_RES_ARGS); } catch (NoSuchMethodException ex) { throw new LayoutDefinitionException("Unable to find " + "'getResource' method in this environment!", ex); } try { url = (URL) method.invoke(ctx, new Object [] {"/" + relPath}); } catch (IllegalAccessException ex) { throw new LayoutDefinitionException(ex); } catch (InvocationTargetException ex) { throw new LayoutDefinitionException(ex); } return url; } /** *

This method searches for the given relative path filename. It * first looks relative the context root of the application, it then * looks in the classpath, including relative to the * META-INF folder. If found a URL to the * file will be returned.

* * @param path The Path. * * @param defSuff The suffix to use if the file specified in path is not * found, it is sometimes useful to translate the path * using a default suffix. */ public static URL searchForFile(String path, String defSuff) throws IOException { // Remove leading '/' characters if needed boolean absolutePath = false; String newPath = path; while (newPath.startsWith("/")) { newPath = newPath.substring(1); absolutePath = true; } // Check to see if we have already found this before (on this request) URL url = null; FacesContext ctx = FacesContext.getCurrentInstance(); Map filesFound = getFilesFoundMap(ctx); if (filesFound != null) { url = filesFound.get(newPath); if (url != null) { // We've already figured this out, abort before we start return url; } } // Next check relative newPath (i.e. determine the directory w/i the app // they are in and prepend it to the newPath) if (!absolutePath) { // Check for URL syntax... at this point it will look like a relative // path. // // NOTE: While this should not be exposed from the browser, it is // valid for server-side code to request page fragments via URLs. // If this is the case, "newPath" will be in the form: // ://... We'll simply detect by checking for "://". if (newPath.contains("://")) { // Looks like a URL... try { // Read the contents byte[] content = readFromURL(new URL(newPath)); // Use request scope in order to persist it appropriately... // Not retrievied, prevents GC from happenning early if (ctx != null) { ctx.getExternalContext().getRequestMap(). put("__gf." + newPath, content); } // Use special URL which will buffer the contents url = new URL(null, newPath, new CachedURLStreamHandler(content)); // Cache the URL... if (filesFound != null) { // Cache what we found -- each LDM calls this method, help them... filesFound.put(newPath, url); } // We need to end early b/c this is a special case... return url; } catch (MalformedURLException ex) { // This is probably bad, but we'll ignore it and see if // it can be found via a relative path. } catch (IOException ex) { // Rethrow it b/c this error probably should be shown. throw ex; } } String absPath = getAbsolutePath(ctx, newPath); url = searchForFile(absPath, defSuff); // We're done, don't search anymore even if not found return url; } // Check for file in docroot. url = getResource(newPath); if (url == null) { // Check the classpath for the file ClassLoader loader = Util.getClassLoader(path); url = loader.getResource(newPath); if (url == null) { // Check w/ a leading '/' url = loader.getResource("/" + newPath); if (url == null) { // Check in "META-INF/" url = loader.getResource("META-INF/" + newPath); if ((url == null) && (defSuff != null)) { // Check to see if the extension is not .jsf, if // not then try finding w/ the extension of .jsf // This allows developers to write .jsf files and // share them even if the FacesServlet is mapped // differently int idx = path.lastIndexOf('.'); if (idx != -1) { String ext = path.substring(idx); if (!ext.equalsIgnoreCase(defSuff)) { return searchForFile(path.substring(0, idx) + defSuff, null); } } else { return searchForFile(path + defSuff, null); } } } } } if ((url != null) && (filesFound != null)) { // Cache what we found -- each LDM calls this method, help them... filesFound.put(newPath, url); } // Return a url to the file (hopefully)... return url; } /** *

This method converts a path relative to the current viewId into an * absolute path from the context-root. It does this by prepending * the current viewId to it. It is expected that relPath does not * contain a leading '/'.

* * @param ctx The FacesContext. * @param relPath The relative path to convert. * * @return The absolute path (relative to the context-root). */ public static String getAbsolutePath(FacesContext ctx, String relPath) { // Sanity check String absPath = null; if (ctx != null) { // Make sure we have a ViewRoot UIViewRoot viewRoot = ctx.getViewRoot(); if (viewRoot != null) { // Get the viewId String viewId = viewRoot.getViewId(); if (viewId == null) { viewId = "/"; } else if (!viewId.startsWith("/")) { // Ensure our viewId starts with a '/' viewId = "/" + viewId; } int slash = viewId.lastIndexOf('/'); // This will give our our base directory... absPath = viewId.substring(0, ++slash); // Append on the relative path absPath += relPath; } } return (absPath == null) ? ("/" + relPath) : absPath; } /** *

This method looks for "/./" or "/../" elements in an absolute path * and removes them. If a "/./" is found, it simply removes it. If a * "/../" is found, it removes it and the preceeding path element. * This method also removes duplate '/' characters (i.e. "//" becomes * "/").

*/ public static String cleanUpPath(String absPath) { // First lets remove any "/./" elements int idx; while ((idx = absPath.indexOf("/./")) != -1) { absPath = absPath.substring(0, idx) + absPath.substring(idx + 2); } // Next remove any "/../" elements while ((idx = absPath.indexOf("/../")) != -1) { int prevElement = 0; if (idx > 0) { // Find previous element prevElement = absPath.lastIndexOf('/', idx - 1); if (prevElement == -1) { prevElement = 0; } } absPath = absPath.substring(0, prevElement) + absPath.substring(idx + 3); } // Remove "//" while ((idx = absPath.indexOf("//")) != -1) { absPath = absPath.substring(0, idx) + absPath.substring(idx + 1); } // Return the fixed-up path return absPath; } /** *

This method looks for resources in jar files without using the * ClassLoader. It accepts directories in which it should scan for * jar files.

* * @param facesContext The FacesContext. * @param resourcePath The resource name to search in all jar files. * @param searchPaths The array of paths to search for jar files. */ public static List getJarResources(FacesContext facesContext, String resourcePath, String... searchPaths) throws IOException { if (searchPaths == null) { // Use default jar search path... searchPaths = DEFAULT_SEARCH_PATH; } List entries = new ArrayList(); ExternalContext ec = facesContext.getExternalContext(); for (String searchPath : searchPaths) { Set paths = ec.getResourcePaths(searchPath); for (String path : paths) { if ("jar".equalsIgnoreCase(path.substring(path.length() - 3))) { // FIXME: Can this be a URL? JarFile jarFile = new JarFile(new File(ec.getResource(path).getFile())); JarEntry jarEntry = jarFile.getJarEntry(resourcePath); if (jarEntry != null) { entries.add(new Tuple(jarFile, jarEntry)); } } } } return entries; } /** *

This method read content from a URL and returns the * result as a byte[].

*/ public static byte[] readFromURL(URL url) throws IOException { byte buffer[] = new byte[10000]; byte result[] = new byte[0]; //try { int count = 0; int offset = 0; InputStream in = url.openStream(); // Attempt to read up to 10K bytes. count = in.read(buffer); while (count != -1) { // Make room for new content... //result = Arrays.copyOf(result, offset + count); Java 6 only... // When I can depend on Java 6... replace the following 3 lines // with the line above. byte oldResult[] = result; result = new byte[offset + count]; System.arraycopy(oldResult, 0, result, 0, offset); // Copy in new content... System.arraycopy(buffer, 0, result, offset, count); // Increment the offset offset += count; // Attempt to read up to 10K more bytes... count = in.read(buffer); } //} catch (IOException ex) { //throw new RuntimException("Error while trying to read from URL: " + url); //} return result; } /** *

This method provides access to a Map containing the URLs of files * that have been found already on this particular request. This is * done to speed up the task of locating the appropriate URL.

* *

The Map returned is keyed by the viewId (or String * representation of the URL) for the file in question. If the * given FacesContext is null, * null will be returned from this method.

*/ private static Map getFilesFoundMap(FacesContext ctx) { Map filesFound = null; // Only do this caching if we're in Faces... if (ctx != null) { filesFound = (Map) ctx.getExternalContext().getRequestMap().get(FILES_FOUND); if (filesFound == null) { // Not yet created, create it... filesFound = new HashMap(8); ctx.getExternalContext().getRequestMap().put(FILES_FOUND, filesFound); } } return filesFound; } private static final String FILES_FOUND = "_filesFoundThisRequest"; private static final Class [] REALPATH_ARGS = new Class[] {String.class}; private static final Class [] GET_RES_ARGS = new Class[] {String.class}; private static final String [] DEFAULT_SEARCH_PATH = new String[] {"/WEB-INF/lib/"}; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy