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  import java.net.URI;
25  
26  import org.apache.commons.httpclient.methods.GetMethod;
27  import org.joda.time.DateTime;
28  import org.joda.time.chrono.ISOChronology;
29  import org.opensaml.xml.util.DatatypeHelper;
30  
31  /**
32   * A resource representing a file read from an HTTP(S) location. Every time the file is successfully read from the URL
33   * location it is written to a backing file. If the file can not be read from the URL it is read from this backing file,
34   * if available.
35   * 
36   * Note, large files should not be accessed in this manner as the entire file is read into memory before being written
37   * to disk and then returned.
38   */
39  public class FileBackedHttpResource extends HttpResource {
40  
41      /** Backing resource file. */
42      private File resourceFile;
43  
44      /**
45       * Constructor.
46       * 
47       * @param resource HTTP(S) URL of the resource
48       * @param backingFile filesystem location to store the resource
49       */
50      public FileBackedHttpResource(String resource, String backingFile) {
51          super(resource);
52  
53          if (DatatypeHelper.isEmpty(backingFile)) {
54              throw new IllegalArgumentException("Backing file path may not be null or empty");
55          }
56  
57          resourceFile = new File(backingFile);
58      }
59  
60      /**
61       * Constructor.
62       * 
63       * @param resource HTTP(S) URL of the resource
64       * @param backingFile file: URI location to store the resource
65       * 
66       * @since 1.2
67       */
68      public FileBackedHttpResource(String resource, URI backingFile) {
69          super(resource);
70  
71          if (backingFile == null) {
72              throw new IllegalArgumentException("Backing file path may not be null or empty");
73          }
74  
75          resourceFile = new File(backingFile);
76      }
77  
78      /**
79       * Constructor.
80       * 
81       * @param resource HTTP(S) URL of the resource
82       * @param backingFile filesystem location to store the resource
83       * @param resourceFilter filter to apply to this resource
84       * 
85       * @deprecated use {@link #setResourceFilter(ResourceFilter)} instead
86       */
87      public FileBackedHttpResource(String resource, String backingFile, ResourceFilter resourceFilter) {
88          super(resource, resourceFilter);
89  
90          if (DatatypeHelper.isEmpty(backingFile)) {
91              throw new IllegalArgumentException("Backing file path may not be null or empty");
92          }
93  
94          resourceFile = new File(backingFile);
95      }
96  
97      /**
98       * Constructor.
99       * 
100      * @param resource HTTP(S) URL of the resource
101      * @param backingFile filesystem location to store the resource
102      * @param resourceFilter filter to apply to this resource
103      * 
104      * @since 1.2
105      * @deprecated use {@link #setResourceFilter(ResourceFilter)} instead
106      */
107     public FileBackedHttpResource(String resource, URI backingFile, ResourceFilter resourceFilter) {
108         super(resource, resourceFilter);
109 
110         if (backingFile == null) {
111             throw new IllegalArgumentException("Backing file path may not be null or empty");
112         }
113 
114         resourceFile = new File(backingFile);
115     }
116 
117     /** {@inheritDoc} */
118     public boolean exists() throws ResourceException {
119         if (!super.exists()) {
120             return resourceFile.exists();
121         }
122 
123         return true;
124     }
125 
126     /** {@inheritDoc} */
127     public InputStream getInputStream() throws ResourceException {
128         InputStream ins = null;
129         try {
130             GetMethod getMethod = super.getResource();
131             byte[] response = getMethod.getResponseBody();
132             saveToResourceFile(response);
133             ins = getMethod.getResponseBodyAsStream();
134         } catch (Exception e) {
135             try {
136                 ins = new FileInputStream(resourceFile);
137             } catch (IOException ioe) {
138                 throw new ResourceException("Unable to read resource URL or backing file "
139                         + resourceFile.getAbsolutePath(), ioe);
140             }
141         }
142 
143         return applyFilter(ins);
144     }
145 
146     /** {@inheritDoc} */
147     public DateTime getLastModifiedTime() throws ResourceException {
148         try {
149             return super.getLastModifiedTime();
150         } catch (ResourceException e) {
151             long lastModifiedTime = resourceFile.lastModified();
152             if (lastModifiedTime == 0) {
153                 throw new ResourceException("URL resource is not reachable and backing file is not readable");
154             }
155 
156             return new DateTime(lastModifiedTime, ISOChronology.getInstanceUTC());
157         }
158     }
159 
160     /** {@inheritDoc} */
161     public String getLocation() {
162         return super.getLocation();
163     }
164 
165     /**
166      * Saves a resource to the backing file.
167      * 
168      * @param resource the string representation of the resource
169      * 
170      * @throws ResourceException thrown if the resource backing file can not be written to
171      */
172     protected void saveToResourceFile(byte[] resource) throws ResourceException {
173         try {
174             FileOutputStream out = new FileOutputStream(resourceFile);
175             out.write(resource);
176         } catch (IOException e) {
177             throw new ResourceException("Unable to write resource to backing file " + resourceFile.getAbsolutePath(), e);
178         }
179     }
180 }