View Javadoc

1   package com.atlassian.plugin.servlet;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.plugin.elements.ResourceLocation;
5   import com.atlassian.plugin.servlet.util.LastModifiedHandler;
6   
7   import javax.servlet.http.HttpServletRequest;
8   import javax.servlet.http.HttpServletResponse;
9   import java.io.IOException;
10  import java.io.InputStream;
11  import java.io.OutputStream;
12  import java.util.Date;
13  
14  import org.apache.commons.logging.Log;
15  import org.apache.commons.logging.LogFactory;
16  import org.apache.commons.io.IOUtils;
17  import org.apache.commons.lang.StringUtils;
18  
19  abstract class AbstractDownloadableResource implements DownloadableResource
20  {
21      private static final Log log = LogFactory.getLog(AbstractDownloadableResource.class);
22  
23      protected Plugin plugin;
24      protected String extraPath;
25      protected ResourceLocation resourceLocation;
26  
27      public AbstractDownloadableResource(Plugin plugin, ResourceLocation resourceLocation, String extraPath)
28      {
29          if (extraPath != null && !"".equals(extraPath.trim()) && !resourceLocation.getLocation().endsWith("/"))
30          {
31              extraPath = "/" + extraPath;
32          }
33  
34          this.plugin = plugin;
35          this.extraPath = extraPath;
36          this.resourceLocation = resourceLocation;
37      }
38  
39      public void serveResource(HttpServletRequest request, HttpServletResponse response) throws DownloadException
40      {
41          log.debug("Serving: " + this);
42  
43          InputStream resourceStream = getResourceAsStream();
44          if (resourceStream == null)
45          {
46              log.warn("Resource not found: " + this);
47              return;
48          }
49  
50          if(StringUtils.isNotBlank(getContentType()))
51          {
52              response.setContentType(getContentType());
53          }
54  
55          OutputStream out;
56          try
57          {
58              out = response.getOutputStream();
59          }
60          catch (IOException e)
61          {
62              throw new DownloadException(e);
63          }
64  
65          streamResource(resourceStream, out);
66          log.debug("Serving file done.");
67      }
68  
69      public void streamResource(OutputStream out)
70      {
71          InputStream resourceStream = getResourceAsStream();
72          if (resourceStream == null)
73          {
74              log.warn("Resource not found: " + this);
75              return;
76          }
77  
78          streamResource(resourceStream, out);
79      }
80  
81      /**
82       * Copy from the supplied OutputStream to the supplied InputStream. Note that the InputStream will be closed on
83       * completion.
84       * 
85       * @param in the stream to read from
86       * @param out the stream to write to
87       */
88      private void streamResource(InputStream in, OutputStream out)
89      {
90          try
91          {
92              IOUtils.copy(in, out);
93          }
94          catch (IOException e)
95          {
96              log.error("Error serving the requested file", e);
97          }
98          finally
99          {
100             IOUtils.closeQuietly(in);
101             try
102             {
103                 out.flush();
104             }
105             catch (IOException e)
106             {
107                 log.warn("Error flushing output stream", e);
108             }
109         }        
110     }
111 
112     /**
113      * Checks any "If-Modified-Since" header from the request against the plugin's loading time, since plugins can't
114      * be modified after they've been loaded this is a good way to determine if a plugin resource has been modified
115      * or not.
116      *
117      * If this method returns true, don't do any more processing on the request -- the response code has already been
118      * set to "304 Not Modified" for you, and you don't need to serve the file.
119      */
120     public boolean isResourceModified(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
121     {
122         Date resourceLastModifiedDate = (plugin.getDateLoaded() == null) ? new Date() : plugin.getDateLoaded();
123         LastModifiedHandler lastModifiedHandler = new LastModifiedHandler(resourceLastModifiedDate);
124         return lastModifiedHandler.checkRequest(httpServletRequest, httpServletResponse);
125     }
126 
127     public String getContentType()
128     {
129         return resourceLocation.getContentType();
130     }
131 
132     /**
133      * Returns an {@link InputStream} to stream the resource from.
134      */
135     protected abstract InputStream getResourceAsStream();
136 
137     protected String getLocation()
138     {
139         return resourceLocation.getLocation() + extraPath;
140     }
141 
142     public String toString()
143     {
144         return "Resource: " + getLocation() + " (" + getContentType() + ")";
145     }
146 }