KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > webdav > GetMethod


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.webdav;
18
19 import java.io.IOException JavaDoc;
20 import java.io.Writer JavaDoc;
21 import java.text.ParseException JavaDoc;
22 import java.text.SimpleDateFormat JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29
30 import org.alfresco.i18n.I18NUtil;
31 import org.alfresco.repo.content.filestore.FileContentReader;
32 import org.alfresco.service.cmr.model.FileFolderService;
33 import org.alfresco.service.cmr.model.FileInfo;
34 import org.alfresco.service.cmr.model.FileNotFoundException;
35 import org.alfresco.service.cmr.repository.ContentReader;
36 import org.alfresco.service.cmr.repository.NodeRef;
37 import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
38 import org.alfresco.service.cmr.repository.datatype.TypeConverter;
39
40 /**
41  * Implements the WebDAV GET method
42  *
43  * @author gavinc
44  */

45 public class GetMethod extends WebDAVMethod
46 {
47     // Request parameters
48

49     private ArrayList JavaDoc ifMatchTags = null;
50     private ArrayList JavaDoc ifNoneMatchTags = null;
51     private Date JavaDoc m_ifModifiedSince = null;
52     private Date JavaDoc m_ifUnModifiedSince = null;
53
54     protected boolean m_returnContent = true;
55
56     /**
57      * Default constructor
58      */

59     public GetMethod()
60     {
61     }
62
63     /**
64      * Parse the request headers
65      *
66      * @exception WebDAVServerException
67      */

68     protected void parseRequestHeaders() throws WebDAVServerException
69     {
70         // If the range header is present output a warning, add support later
71

72         String JavaDoc strRange = m_request.getHeader(WebDAV.HEADER_RANGE);
73
74         if (strRange != null && strRange.length() > 0)
75         {
76             logger.warn("Range header (" + strRange + ") not supported");
77         }
78
79         // Capture all the If headers, process later
80

81         String JavaDoc strIfMatch = m_request.getHeader(WebDAV.HEADER_IF_MATCH);
82
83         if (strIfMatch != null && strIfMatch.length() > 0)
84         {
85             ifMatchTags = parseETags(strIfMatch);
86         }
87
88         String JavaDoc strIfNoneMatch = m_request.getHeader(WebDAV.HEADER_IF_NONE_MATCH);
89         if (strIfNoneMatch != null && strIfNoneMatch.length() > 0)
90         {
91             ifNoneMatchTags = parseETags(strIfNoneMatch);
92         }
93
94         // Parse the dates
95

96         SimpleDateFormat JavaDoc dateFormat = new SimpleDateFormat JavaDoc(WebDAV.HEADER_IF_DATE_FORMAT);
97         String JavaDoc strIfModifiedSince = m_request.getHeader(WebDAV.HEADER_IF_MODIFIED_SINCE);
98
99         if (strIfModifiedSince != null && strIfModifiedSince.length() > 0)
100         {
101             try
102             {
103                 m_ifModifiedSince = dateFormat.parse(strIfModifiedSince);
104             }
105             catch (ParseException JavaDoc e)
106             {
107                 logger.warn("Failed to parse If-Modified-Since date of " + strIfModifiedSince);
108             }
109         }
110
111         String JavaDoc strIfUnModifiedSince = m_request.getHeader(WebDAV.HEADER_IF_UNMODIFIED_SINCE);
112         if (strIfUnModifiedSince != null && strIfUnModifiedSince.length() > 0)
113         {
114             try
115             {
116                 m_ifUnModifiedSince = dateFormat.parse(strIfUnModifiedSince);
117             }
118             catch (ParseException JavaDoc e)
119             {
120                 logger.warn("Failed to parse If-Unmodified-Since date of " + strIfUnModifiedSince);
121             }
122         }
123     }
124
125     /**
126      * Parse the request body
127      *
128      * @exception WebDAVServerException
129      */

130     protected void parseRequestBody() throws WebDAVServerException
131     {
132         // Nothing to do in this method
133
}
134
135     /**
136      * Exceute the WebDAV request
137      *
138      * @exception WebDAVServerException
139      */

140     protected void executeImpl() throws WebDAVServerException, Exception JavaDoc
141     {
142         FileFolderService fileFolderService = getFileFolderService();
143         NodeRef rootNodeRef = getRootNodeRef();
144         String JavaDoc path = getPath();
145         String JavaDoc servletPath = getServletPath();
146
147         FileInfo nodeInfo = null;
148         try
149         {
150             nodeInfo = getDAVHelper().getNodeForPath(rootNodeRef, path, servletPath);
151         }
152         catch (FileNotFoundException e)
153         {
154             throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
155         }
156         
157         // Check if the node is a folder
158
if (nodeInfo.isFolder())
159         {
160             // is content required
161
if (!m_returnContent)
162             {
163                 // it is a folder and no content is required
164
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
165             }
166             // Generate a folder listing
167
generateDirectoryListing(nodeInfo);
168         }
169         else
170         {
171             NodeRef pathNodeRef = nodeInfo.getNodeRef();
172             // Return the node details, and content if requested, check that the node passes the pre-conditions
173

174             checkPreConditions(nodeInfo);
175
176             // Build the response header
177
m_response.setHeader(WebDAV.HEADER_ETAG, getDAVHelper().makeQuotedETag(pathNodeRef));
178
179             Date JavaDoc modifiedDate = nodeInfo.getModifiedDate();
180             if (modifiedDate != null)
181             {
182                 long modDate = DefaultTypeConverter.INSTANCE.longValue(modifiedDate);
183                 m_response.setHeader(WebDAV.HEADER_LAST_MODIFIED, WebDAV.formatHeaderDate(modDate));
184             }
185
186             ContentReader reader = fileFolderService.getReader(nodeInfo.getNodeRef());
187             // ensure that we generate something, even if the content is missing
188
reader = FileContentReader.getSafeContentReader(
189                     (ContentReader) reader,
190                     I18NUtil.getMessage(FileContentReader.MSG_MISSING_CONTENT),
191                     nodeInfo.getNodeRef(), reader);
192             // there is content associated with the node
193
m_response.setHeader(WebDAV.HEADER_CONTENT_LENGTH, "" + reader.getSize());
194             m_response.setHeader(WebDAV.HEADER_CONTENT_TYPE, reader.getMimetype());
195             
196             if (m_returnContent)
197             {
198                 // copy the content to the response output stream
199
reader.getContent(m_response.getOutputStream());
200             }
201         }
202     }
203
204     /**
205      * Checks the If header conditions
206      *
207      * @param nodeInfo the node to check
208      * @throws WebDAVServerException if a pre-condition is not met
209      */

210     private void checkPreConditions(FileInfo nodeInfo) throws WebDAVServerException
211     {
212         // Make an etag for the node
213

214         String JavaDoc strETag = getDAVHelper().makeQuotedETag(nodeInfo.getNodeRef());
215         TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
216
217         // Check the If-Match header, don't send any content back if none of the tags in
218
// the list match the etag, and the wildcard is not present
219

220         if (ifMatchTags != null)
221         {
222             if (ifMatchTags.contains(WebDAV.ASTERISK) == false && ifMatchTags.contains(strETag) == false)
223             {
224                 throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
225             }
226         }
227
228         // Check the If-None-Match header, don't send any content back if any of the tags
229
// in the list match the etag, or the wildcard is present
230

231         if (ifNoneMatchTags != null)
232         {
233             if (ifNoneMatchTags.contains(WebDAV.ASTERISK) || ifNoneMatchTags.contains(strETag))
234             {
235                 throw new WebDAVServerException(HttpServletResponse.SC_NOT_MODIFIED);
236             }
237         }
238
239         // Check the modified since list, if the If-None-Match header was not specified
240

241         if (m_ifModifiedSince != null && ifNoneMatchTags == null)
242         {
243             Date JavaDoc lastModifiedDate = nodeInfo.getModifiedDate();
244
245             long fileLastModified = lastModifiedDate != null ? typeConv.longValue(lastModifiedDate) : 0L;
246             long modifiedSince = m_ifModifiedSince.getTime();
247
248             if (fileLastModified != 0L && fileLastModified <= modifiedSince)
249             {
250                 throw new WebDAVServerException(HttpServletResponse.SC_NOT_MODIFIED);
251             }
252         }
253
254         // Check the un-modified since list
255

256         if (m_ifUnModifiedSince != null)
257         {
258             Date JavaDoc lastModifiedDate = nodeInfo.getModifiedDate();
259
260             long fileLastModified = lastModifiedDate != null ? typeConv.longValue(lastModifiedDate) : 0L;
261             long unModifiedSince = m_ifUnModifiedSince.getTime();
262
263             if (fileLastModified >= unModifiedSince)
264             {
265                 throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
266             }
267         }
268     }
269
270     /**
271      * Parses the given ETag header into a list of separate ETags
272      *
273      * @param strETagHeader The header to parse
274      * @return A list of ETags
275      */

276     private ArrayList JavaDoc parseETags(String JavaDoc strETagHeader)
277     {
278         ArrayList JavaDoc<String JavaDoc> list = new ArrayList JavaDoc<String JavaDoc>();
279
280         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(strETagHeader, WebDAV.HEADER_VALUE_SEPARATOR);
281         while (tokenizer.hasMoreTokens())
282         {
283             list.add(tokenizer.nextToken().trim());
284         }
285
286         return list;
287     }
288
289     /**
290      * Generates a HTML representation of the contents of the path represented by the given node
291      *
292      * @param fileInfo the file to use
293      */

294     private void generateDirectoryListing(FileInfo fileInfo)
295     {
296         FileFolderService fileFolderService = getFileFolderService();
297         Writer JavaDoc writer = null;
298
299         try
300         {
301             writer = m_response.getWriter();
302
303             // Get the list of child nodes for the parent node
304
List JavaDoc<FileInfo> childNodeInfos = fileFolderService.list(fileInfo.getNodeRef());
305
306             // Send back the start of the HTML
307
writer.write("<html><head><title>Alfresco Content Repository</title>");
308             writer.write("<style>");
309             writer.write("body { font-family: Arial, Helvetica; font-size: 12pt; background-color: white; }\n");
310             writer.write("table { font-family: Arial, Helvetica; font-size: 12pt; background-color: white; }\n");
311             writer.write(".listingTable { border: solid black 1px; }\n");
312             writer.write(".textCommand { font-family: verdana; font-size: 10pt; }\n");
313             writer.write(".textLocation { font-family: verdana; font-size: 11pt; font-weight: bold; color: #2a568f; }\n");
314             writer.write(".textData { font-family: verdana; font-size: 10pt; }\n");
315             writer.write(".tableHeading { font-family: verdana; font-size: 10pt; font-weight: bold; color: white; background-color: #2a568f; }\n");
316             writer.write(".rowOdd { background-color: #eeeeee; }\n");
317             writer.write(".rowEven { background-color: #dddddd; }\n");
318             writer.write("</style></head>\n");
319             writer.flush();
320
321             // Send back the table heading
322
writer.write("<body>\n");
323             writer.write("<table cellspacing='2' cellpadding='3' border='0' width='100%'>\n");
324             writer.write("<tr><td colspan='3' class='textLocation'>Directory listing for ");
325             writer.write(WebDAVHelper.encodeHTML(getPath()));
326             writer.write("</td></tr>\n");
327             writer.write("<tr><td height='10'></td></tr></table>");
328
329             writer.write("<table cellspacing='2' cellpadding='3' border='0' width='100%' class='listingTable'>\n");
330             writer.write("<tr><td class='tableHeading' width='*'>Name</td>");
331             writer.write("<td class='tableHeading' width='10%'>Size</td>");
332             writer.write("<td class='tableHeading' width='20%'>Modified</td>");
333             writer.write("</tr>");
334
335             // Get the URL for the root path
336
String JavaDoc rootURL = WebDAV.getURLForPath(m_request, getPath(), true);
337             if (rootURL.endsWith(WebDAVHelper.PathSeperator) == false)
338             {
339                 rootURL = rootURL + WebDAVHelper.PathSeperator;
340             }
341
342             // Start with a link to the parent folder so we can navigate back up, unless we are at the root level
343
if (fileInfo.getNodeRef().equals(getRootNodeRef()) == false)
344             {
345                 writer.write("<tr class='rowOdd'>");
346                 writer.write("<td class='textData'><a HREF=\"");
347
348                 // Strip the last folder from the path
349

350                 String JavaDoc[] paths = getDAVHelper().splitPath(rootURL.substring(0, rootURL.length() - 1));
351                 writer.write(paths[0]);
352
353                 writer.write("\">");
354                 writer.write("[Up a level]</a>");
355                 writer.write("</tr>\n");
356             }
357
358             // Send back what we have generated so far
359
writer.flush();
360             int rowId = 0;
361
362             for (FileInfo childNodeInfo : childNodeInfos)
363             {
364                 // Output the details for the current node
365
writer.write("<tr class='");
366                 if (rowId++ % 2 == 0)
367                 {
368                     writer.write("rowOdd");
369                 }
370                 else
371                 {
372                     writer.write("rowEven");
373                 }
374                 writer.write("'><td class='textData'><a HREF=\"");
375                 writer.write(rootURL);
376
377                 String JavaDoc fname = childNodeInfo.getName();
378
379                 writer.write(WebDAVHelper.encodeURL(fname));
380                 writer.write("\">");
381                 writer.write(WebDAVHelper.encodeHTML(fname));
382                 writer.write("</a>");
383
384                 writer.write("</td><td class='textData'>");
385                 if (fileInfo.isFolder())
386                 {
387                     writer.write(formatSize("0"));
388                 }
389                 else
390                 {
391                     ContentReader reader = fileFolderService.getReader(childNodeInfo.getNodeRef());
392                     long fsize = 0L;
393                     if ( reader != null)
394                     {
395                         fsize = reader.getSize();
396                     }
397                     writer.write(formatSize("" + fsize));
398                 }
399                 writer.write("</td><td class='textData'>");
400
401                 Date JavaDoc modifiedDate = childNodeInfo.getModifiedDate();
402                 if (modifiedDate != null)
403                 {
404                     writer.write(WebDAV.formatHeaderDate(DefaultTypeConverter.INSTANCE.longValue(modifiedDate)));
405                 }
406                 else
407                 {
408                     writer.write("");
409                 }
410                 writer.write("</td>");
411
412                 writer.write("</tr>\n");
413                 writer.flush();
414             }
415         }
416         catch (Throwable JavaDoc e)
417         {
418             logger.error(e);
419
420             if (writer != null)
421             {
422                 try
423                 {
424                     writer.write("<table><tr><td style='color:red'>");
425                     writer.write("An error occurred whilst generating the directory listing, ");
426                     writer.write("please contact the system administrator.</td></tr></table>");
427                     writer.flush();
428                 }
429                 catch (IOException JavaDoc ioe)
430                 {
431                 }
432             }
433         }
434     }
435
436     /**
437      * Formats the given size for display in a directory listing
438      *
439      * @param strSize The content size
440      * @return The formatted size
441      */

442     private String JavaDoc formatSize(String JavaDoc strSize)
443     {
444         String JavaDoc strFormattedSize = strSize;
445
446         int length = strSize.length();
447         if (length < 4)
448         {
449             strFormattedSize = strSize + " bytes";
450         }
451         else if (length >= 4 && length < 7)
452         {
453             String JavaDoc strLeft = strSize.substring(0, length - 3);
454             String JavaDoc strRight = strSize.substring(length - 3, length - 2);
455
456             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(strLeft);
457             if (!strRight.equals("0"))
458             {
459                 buffer.append(".");
460                 buffer.append(strRight);
461             }
462             buffer.append(" Kb");
463
464             strFormattedSize = buffer.toString();
465         }
466         else
467         {
468             String JavaDoc strLeft = strSize.substring(0, length - 6);
469             String JavaDoc strRight = strSize.substring(length - 6, length - 5);
470
471             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(strLeft);
472             if (!strRight.equals("0"))
473             {
474                 buffer.append(".");
475                 buffer.append(strRight);
476             }
477             buffer.append(" Mb");
478
479             strFormattedSize = buffer.toString();
480         }
481
482         return strFormattedSize;
483     }
484 }
485
Popular Tags