View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets.util;
20  
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.net.URLConnection;
27  import java.net.URLStreamHandler;
28  import java.util.logging.Level;
29  import java.util.logging.Logger;
30  
31  import javax.faces.context.ExternalContext;
32  import javax.faces.context.FacesContext;
33  import javax.servlet.ServletContext;
34  
35  /**
36   * @author Roland Huss
37   * 
38   */
39  public final class Resource
40  {
41  
42      //protected final static Logger log = Logger.getLogger("facelets.factory");
43      protected final static Logger log = Logger.getLogger(Resource.class.getName());
44  
45      /**
46       * Get an URL of an internal resource. First, {@link javax.faces.context.ExternalContext#getResource(String)} is
47       * checked for an non-null URL return value. In the case of a null return value (as it is the case for Weblogic 8.1
48       * for a packed war), a URL with a special URL handler is constructed, which can be used for <em>opening</em> a
49       * serlvet resource later. Internally, this special URL handler will call
50       * {@link ServletContext#getResourceAsStream(String)} when an inputstream is requested. This works even on Weblogic
51       * 8.1
52       * 
53       * @param ctx
54       *            the faces context from which to retrieve the resource
55       * @param path
56       *            an URL path
57       * 
58       * @return an url representing the URL and on which getInputStream() can be called to get the resource
59       * @throws MalformedURLException
60       */
61      public static URL getResourceUrl(FacesContext ctx, String path) throws MalformedURLException
62      {
63          final ExternalContext externalContext = ctx.getExternalContext();
64          URL url = externalContext.getResource(path);
65          if (log.isLoggable(Level.FINE))
66          {
67              log.fine("Resource-Url from external context: " + url);
68          }
69          if (url == null)
70          {
71              // This might happen on Servlet container which doesnot return
72              // anything
73              // for getResource() (like weblogic 8.1 for packaged wars) we
74              // are trying
75              // to use an own URL protocol in order to use
76              // ServletContext.getResourceAsStream()
77              // when opening the url
78              if (resourceExist(externalContext, path))
79              {
80                  url = getUrlForResourceAsStream(externalContext, path);
81              }
82          }
83          return url;
84      }
85  
86      // This method could be used above to provide a 'fail fast' if a
87      // resource
88      // doesnt exist. Otherwise, the URL will fail on the first access.
89      private static boolean resourceExist(ExternalContext externalContext, String path)
90      {
91          if ("/".equals(path))
92          {
93              // The root context exists always
94              return true;
95          }
96          Object ctx = externalContext.getContext();
97          if (ctx instanceof ServletContext)
98          {
99              ServletContext servletContext = (ServletContext) ctx;
100             InputStream stream = servletContext.getResourceAsStream(path);
101             if (stream != null)
102             {
103                 try
104                 {
105                     stream.close();
106                 }
107                 catch (IOException e)
108                 {
109                     // Ignore here, since we donnot wanted to read from this
110                     // resource anyway
111                 }
112                 return true;
113             }
114         }
115         return false;
116     }
117 
118     // Construct URL with special URLStreamHandler for proxying
119     // ServletContext.getResourceAsStream()
120     private static URL getUrlForResourceAsStream(final ExternalContext externalContext, String path)
121             throws MalformedURLException
122     {
123         URLStreamHandler handler = new URLStreamHandler()
124         {
125             protected URLConnection openConnection(URL u) throws IOException
126             {
127                 final String file = u.getFile();
128                 return new URLConnection(u)
129                 {
130                     public void connect() throws IOException
131                     {
132                     }
133 
134                     public InputStream getInputStream() throws IOException
135                     {
136                         if (log.isLoggable(Level.FINE))
137                         {
138                             log.fine("Opening internal url to " + file);
139                         }
140                         Object ctx = externalContext.getContext();
141                         // Or maybe fetch the external context afresh ?
142                         // Object ctx =
143                         // FacesContext.getCurrentInstance().getExternalContext().getContext();
144 
145                         if (ctx instanceof ServletContext)
146                         {
147                             ServletContext servletContext = (ServletContext) ctx;
148                             InputStream stream = servletContext.getResourceAsStream(file);
149                             if (stream == null)
150                             {
151                                 throw new FileNotFoundException("Cannot open resource " + file);
152                             }
153                             return stream;
154                         }
155                         else
156                         {
157                             throw new IOException("Cannot open resource for an context of "
158                                     + (ctx != null ? ctx.getClass() : null));
159                         }
160                     }
161                 };
162             }
163         };
164         return new URL("internal", null, 0, path, handler);
165     }
166 }