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       * @deprecated use {@link #setResourceFilter(ResourceFilter)} instead
85       */
86      public FileBackedHttpResource(String resource, String backingFile, ResourceFilter resourceFilter) {
87          super(resource, resourceFilter);
88  
89          if (DatatypeHelper.isEmpty(backingFile)) {
90              throw new IllegalArgumentException("Backing file path may not be null or empty");
91          }
92  
93          resourceFile = new File(backingFile);
94      }
95  
96      /**
97       * Constructor.
98       * 
99       * @param resource HTTP(S) URL of the resource
100      * @param backingFile filesystem location to store the resource
101      * @param resourceFilter filter to apply to this resource
102      * 
103      * @since 1.2
104      * @deprecated use {@link #setResourceFilter(ResourceFilter)} instead
105      */
106     public FileBackedHttpResource(String resource, URI backingFile, ResourceFilter resourceFilter) {
107         super(resource, resourceFilter);
108 
109         if (backingFile == null) {
110             throw new IllegalArgumentException("Backing file path may not be null or empty");
111         }
112 
113         resourceFile = new File(backingFile);
114     }
115 
116     /** {@inheritDoc} */
117     public boolean exists() throws ResourceException {
118         if (!super.exists()) {
119             return resourceFile.exists();
120         }
121 
122         return true;
123     }
124 
125     /** {@inheritDoc} */
126     public InputStream getInputStream() throws ResourceException {
127         InputStream ins = null;
128         try {
129             GetMethod getMethod = super.getResource();
130             byte[] response = getMethod.getResponseBody();
131             saveToResourceFile(response);
132             ins = getMethod.getResponseBodyAsStream();
133         } catch (Exception e) {
134             try {
135                 ins = new FileInputStream(resourceFile);
136             } catch (IOException ioe) {
137                 throw new ResourceException("Unable to read resource URL or backing file "
138                         + resourceFile.getAbsolutePath(), ioe);
139             }
140         }
141 
142         return applyFilter(ins);
143     }
144 
145     /** {@inheritDoc} */
146     public DateTime getLastModifiedTime() throws ResourceException {
147         try {
148             return super.getLastModifiedTime();
149         } catch (ResourceException e) {
150             long lastModifiedTime = resourceFile.lastModified();
151             if (lastModifiedTime == 0) {
152                 throw new ResourceException("URL resource is not reachable and backing file is not readable");
153             }
154 
155             return new DateTime(lastModifiedTime);
156         }
157     }
158 
159     /** {@inheritDoc} */
160     public String getLocation() {
161         return super.getLocation();
162     }
163 
164     /**
165      * Saves a resource to the backing file.
166      * 
167      * @param resource the string representation of the resource
168      * 
169      * @throws ResourceException thrown if the resource backing file can not be written to
170      */
171     protected void saveToResourceFile(byte[] resource) throws ResourceException {
172         try {
173             FileOutputStream out = new FileOutputStream(resourceFile);
174             out.write(resource);
175         } catch (IOException e) {
176             throw new ResourceException("Unable to write resource to backing file " + resourceFile.getAbsolutePath(), e);
177         }
178     }
179 }