View Javadoc

1   /*
2    * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.opensaml.util.resource;
18  
19  import java.io.File;
20  import java.io.FileInputStream;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  
25  import org.apache.commons.httpclient.methods.GetMethod;
26  import org.joda.time.DateTime;
27  import org.opensaml.xml.util.DatatypeHelper;
28  
29  /**
30   * A resource representing a file read from an HTTP(S) location.  Every time the file is successfully read 
31   * from the URL location it is written to a backing file.  If the file can not be read from the URL it is 
32   * read from this backing file, if available.
33   * 
34   * Note, large files should not be accessed in this manner as the entire file is read into memory before 
35   * being written to disk and then returned.
36   */
37  public class FileBackedHttpResource extends HttpResource {
38  
39      /** Filesystem location to store the resource. */
40      private String resourceFilePath;
41  
42      /** Backing resource file. */
43      private File resourceFile;
44  
45      /**
46       * Constructor.
47       * 
48       * @param resource HTTP(S) URL of the resource
49       * @param backingFile filesystem location to store the resource
50       */
51      public FileBackedHttpResource(String resource, String backingFile) {
52          super(resource);
53  
54          resourceFilePath = DatatypeHelper.safeTrimOrNullString(backingFile);
55          if (resourceFilePath == null) {
56              throw new IllegalArgumentException("Backing file path may not be null or empty");
57          }
58  
59          resourceFile = new File(resourceFilePath);
60      }
61  
62      /** {@inheritDoc} */
63      public boolean exists() throws ResourceException {
64          if (!super.exists()) {
65              return resourceFile.exists();
66          }
67  
68          return true;
69      }
70  
71      /** {@inheritDoc} */
72      public InputStream getInputStream() throws ResourceException {
73          try {
74              GetMethod getMethod = super.getResource();
75              byte[] response = getMethod.getResponseBody();
76              saveToResourceFile(response);
77              return getMethod.getResponseBodyAsStream();
78          } catch (Exception e) {
79              try {
80                  return new FileInputStream(resourceFile);
81              } catch (IOException ioe) {
82                  throw new ResourceException("Unable to read resource URL or backing file " + resourceFilePath, ioe);
83              }
84          }
85      }
86  
87      /** {@inheritDoc} */
88      public DateTime getLastModifiedTime() throws ResourceException {
89          try {
90              return super.getLastModifiedTime();
91          } catch (ResourceException e) {
92              long lastModifiedTime = resourceFile.lastModified();
93              if (lastModifiedTime == 0) {
94                  throw new ResourceException("URL resource is not reachable and backing file is not readable");
95              }
96  
97              return new DateTime(lastModifiedTime);
98          }
99      }
100 
101     /** {@inheritDoc} */
102     public String getLocation() {
103         return super.getLocation();
104     }
105 
106     /**
107      * Saves a resource to the backing file.
108      * 
109      * @param resource the string representation of the resource
110      * 
111      * @throws ResourceException thrown if the resource backing file can not be written to
112      */
113     protected void saveToResourceFile(byte[] resource) throws ResourceException {
114         try {
115             FileOutputStream out = new FileOutputStream(resourceFile);
116             out.write(resource);
117         } catch (IOException e) {
118             throw new ResourceException("Unable to write resource to backing file " + resourceFilePath, e);
119         }
120     }
121 }