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.opensaml.xml.util.DatatypeHelper;
29  
30  /**
31   * A resource representing a file read from an HTTP(S) location. Every time the file is successfully read from the URL
32   * 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,
33   * if available.
34   * 
35   * Note, large files should not be accessed in this manner as the entire file is read into memory before being written
36   * to disk and then returned.
37   */
38  public class FileBackedHttpResource extends HttpResource {
39  
40      /** Backing resource file. */
41      private File resourceFile;
42  
43      /**
44       * Constructor.
45       * 
46       * @param resource HTTP(S) URL of the resource
47       * @param backingFile filesystem location to store the resource
48       */
49      public FileBackedHttpResource(String resource, String backingFile) {
50          super(resource);
51  
52          if (DatatypeHelper.isEmpty(backingFile)) {
53              throw new IllegalArgumentException("Backing file path may not be null or empty");
54          }
55  
56          resourceFile = new File(backingFile);
57      }
58  
59      /**
60       * Constructor.
61       * 
62       * @param resource HTTP(S) URL of the resource
63       * @param backingFile file: URI location to store the resource
64       * 
65       * @since 1.2
66       */
67      public FileBackedHttpResource(String resource, URI backingFile) {
68          super(resource);
69  
70          if (backingFile == null) {
71              throw new IllegalArgumentException("Backing file path may not be null or empty");
72          }
73  
74          resourceFile = new File(backingFile);
75      }
76  
77      /**
78       * Constructor.
79       * 
80       * @param resource HTTP(S) URL of the resource
81       * @param backingFile filesystem location to store the resource
82       * @param resourceFilter filter to apply to this resource
83       */
84      public FileBackedHttpResource(String resource, String backingFile, ResourceFilter resourceFilter) {
85          super(resource, resourceFilter);
86  
87          if (DatatypeHelper.isEmpty(backingFile)) {
88              throw new IllegalArgumentException("Backing file path may not be null or empty");
89          }
90  
91          resourceFile = new File(backingFile);
92      }
93  
94      /**
95       * Constructor.
96       * 
97       * @param resource HTTP(S) URL of the resource
98       * @param backingFile filesystem location to store the resource
99       * @param resourceFilter filter to apply to this resource
100      * 
101      * @since 1.2
102      */
103     public FileBackedHttpResource(String resource, URI backingFile, ResourceFilter resourceFilter) {
104         super(resource, resourceFilter);
105 
106         if (backingFile == null) {
107             throw new IllegalArgumentException("Backing file path may not be null or empty");
108         }
109 
110         resourceFile = new File(backingFile);
111     }
112 
113     /** {@inheritDoc} */
114     public boolean exists() throws ResourceException {
115         if (!super.exists()) {
116             return resourceFile.exists();
117         }
118 
119         return true;
120     }
121 
122     /** {@inheritDoc} */
123     public InputStream getInputStream() throws ResourceException {
124         InputStream ins = null;
125         try {
126             GetMethod getMethod = super.getResource();
127             byte[] response = getMethod.getResponseBody();
128             saveToResourceFile(response);
129             ins = getMethod.getResponseBodyAsStream();
130         } catch (Exception e) {
131             try {
132                 ins = new FileInputStream(resourceFile);
133             } catch (IOException ioe) {
134                 throw new ResourceException("Unable to read resource URL or backing file "
135                         + resourceFile.getAbsolutePath(), ioe);
136             }
137         }
138 
139         if (getResourceFilter() != null) {
140             return getResourceFilter().applyFilter(ins);
141         } else {
142             return ins;
143         }
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);
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 }