001: /**
002: * Licensed under the Common Development and Distribution License,
003: * you may not use this file except in compliance with the License.
004: * You may obtain a copy of the License at
005: *
006: * http://www.sun.com/cddl/
007: *
008: * Unless required by applicable law or agreed to in writing, software
009: * distributed under the License is distributed on an "AS IS" BASIS,
010: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * permissions and limitations under the License.
013: */package com.sun.facelets.util;
014:
015: import java.io.FileNotFoundException;
016: import java.io.IOException;
017: import java.io.InputStream;
018: import java.net.MalformedURLException;
019: import java.net.URL;
020: import java.net.URLConnection;
021: import java.net.URLStreamHandler;
022: import java.util.logging.Level;
023: import java.util.logging.Logger;
024:
025: import javax.faces.context.ExternalContext;
026: import javax.faces.context.FacesContext;
027: import javax.servlet.ServletContext;
028:
029: /**
030: * @author Roland Huss
031: *
032: */
033: public final class Resource {
034:
035: protected final static Logger log = Logger
036: .getLogger("facelets.factory");
037:
038: /**
039: * Get an URL of an internal resource. First,
040: * {@link javax.faces.context.ExternalContext#getResource(String)} is
041: * checked for an non-null URL return value. In the case of a null return
042: * value (as it is the case for Weblogic 8.1 for a packed war), a URL with a
043: * special URL handler is constructed, which can be used for
044: * <em>opening</em> a serlvet resource later. Internally, this special URL
045: * handler will call {@link ServletContext#getResourceAsStream(String)} when
046: * an inputstream is requested. This works even on Weblogic 8.1
047: *
048: * @param ctx
049: * the faces context from which to retrieve the resource
050: * @param path
051: * an URL path
052: *
053: * @return an url representing the URL and on which getInputStream() can be
054: * called to get the resource
055: * @throws MalformedURLException
056: */
057: public static URL getResourceUrl(FacesContext ctx, String path)
058: throws MalformedURLException {
059: final ExternalContext externalContext = ctx
060: .getExternalContext();
061: URL url = externalContext.getResource(path);
062: if (log.isLoggable(Level.FINE)) {
063: log.fine("Resource-Url from external context: " + url);
064: }
065: if (url == null) {
066: // This might happen on Servlet container which doesnot return
067: // anything
068: // for getResource() (like weblogic 8.1 for packaged wars) we
069: // are trying
070: // to use an own URL protocol in order to use
071: // ServletContext.getResourceAsStream()
072: // when opening the url
073: if (resourceExist(externalContext, path)) {
074: url = getUrlForResourceAsStream(externalContext, path);
075: }
076: }
077: return url;
078: }
079:
080: // This method could be used above to provide a 'fail fast' if a
081: // resource
082: // doesnt exist. Otherwise, the URL will fail on the first access.
083: private static boolean resourceExist(
084: ExternalContext externalContext, String path) {
085: if ("/".equals(path)) {
086: // The root context exists always
087: return true;
088: }
089: Object ctx = externalContext.getContext();
090: if (ctx instanceof ServletContext) {
091: ServletContext servletContext = (ServletContext) ctx;
092: InputStream stream = servletContext
093: .getResourceAsStream(path);
094: if (stream != null) {
095: try {
096: stream.close();
097: } catch (IOException e) {
098: // Ignore here, since we donnot wanted to read from this
099: // resource anyway
100: }
101: return true;
102: }
103: }
104: return false;
105: }
106:
107: // Construct URL with special URLStreamHandler for proxying
108: // ServletContext.getResourceAsStream()
109: private static URL getUrlForResourceAsStream(
110: final ExternalContext externalContext, String path)
111: throws MalformedURLException {
112: URLStreamHandler handler = new URLStreamHandler() {
113: protected URLConnection openConnection(URL u)
114: throws IOException {
115: final String file = u.getFile();
116: return new URLConnection(u) {
117: public void connect() throws IOException {
118: }
119:
120: public InputStream getInputStream()
121: throws IOException {
122: if (log.isLoggable(Level.FINE)) {
123: log.fine("Opening internal url to " + file);
124: }
125: Object ctx = externalContext.getContext();
126: // Or maybe fetch the external context afresh ?
127: // Object ctx =
128: // FacesContext.getCurrentInstance().getExternalContext().getContext();
129:
130: if (ctx instanceof ServletContext) {
131: ServletContext servletContext = (ServletContext) ctx;
132: InputStream stream = servletContext
133: .getResourceAsStream(file);
134: if (stream == null) {
135: throw new FileNotFoundException(
136: "Cannot open resource " + file);
137: }
138: return stream;
139: } else {
140: throw new IOException(
141: "Cannot open resource for an context of "
142: + (ctx != null ? ctx
143: .getClass() : null));
144: }
145: }
146: };
147: }
148: };
149: return new URL("internal", null, 0, path, handler);
150: }
151: }
|