KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.Date JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23
24 import javax.servlet.http.HttpServletRequest JavaDoc;
25 import javax.servlet.http.HttpServletResponse JavaDoc;
26 import javax.xml.parsers.DocumentBuilder JavaDoc;
27 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
28 import javax.xml.parsers.ParserConfigurationException JavaDoc;
29
30 import org.alfresco.model.ContentModel;
31 import org.alfresco.repo.security.permissions.AccessDeniedException;
32 import org.alfresco.repo.transaction.TransactionUtil;
33 import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
34 import org.alfresco.service.ServiceRegistry;
35 import org.alfresco.service.cmr.lock.LockService;
36 import org.alfresco.service.cmr.model.FileFolderService;
37 import org.alfresco.service.cmr.repository.ContentService;
38 import org.alfresco.service.cmr.repository.MimetypeService;
39 import org.alfresco.service.cmr.repository.NodeRef;
40 import org.alfresco.service.cmr.repository.NodeService;
41 import org.alfresco.service.cmr.security.AuthenticationService;
42 import org.alfresco.service.transaction.TransactionService;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.dom4j.DocumentHelper;
46 import org.dom4j.io.OutputFormat;
47 import org.dom4j.io.XMLWriter;
48 import org.w3c.dom.Document JavaDoc;
49 import org.xml.sax.Attributes JavaDoc;
50 import org.xml.sax.InputSource JavaDoc;
51 import org.xml.sax.SAXException JavaDoc;
52
53 /**
54  * Abstract base class for all the WebDAV method handling classes
55  *
56  * @author gavinc
57  */

58 public abstract class WebDAVMethod
59 {
60     // Log output
61

62     protected static Log logger = LogFactory.getLog("org.alfresco.webdav.protocol");
63
64     // Output formatted XML in the response
65

66     private static final boolean XMLPrettyPrint = true;
67
68     // Servlet request/response
69

70     protected HttpServletRequest JavaDoc m_request;
71     protected HttpServletResponse JavaDoc m_response;
72
73     // WebDAV helper
74

75     protected WebDAVHelper m_davHelper;
76
77     // Root node
78

79     protected NodeRef m_rootNodeRef;
80
81     // Repository path
82

83     protected String JavaDoc m_strPath = null;
84
85     /**
86      * Default constructor
87      */

88     public WebDAVMethod()
89     {
90     }
91
92     /**
93      * Set the request/response details
94      *
95      * @param req HttpServletRequest
96      * @param resp HttpServletResponse
97      * @param registry ServiceRegistry
98      * @param rootNode NodeRef
99      */

100     public void setDetails(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc resp, WebDAVHelper davHelper, NodeRef rootNode)
101     {
102         m_request = req;
103         m_response = resp;
104         m_davHelper = davHelper;
105         m_rootNodeRef = rootNode;
106
107         m_strPath = WebDAV.getRepositoryPath(req);
108     }
109
110     /**
111      * Executes the method
112      */

113     public void execute() throws WebDAVServerException
114     {
115         // Parse the HTTP headers
116
parseRequestHeaders();
117
118         // Parse the HTTP body
119
parseRequestBody();
120         
121         TransactionWork<WebDAVServerException> executeWork = new TransactionWork<WebDAVServerException>()
122         {
123             public WebDAVServerException doWork() throws Exception JavaDoc
124             {
125                 executeImpl();
126                 return null;
127             }
128         };
129         try
130         {
131             // Execute the method
132
TransactionService transactionService = getTransactionService();
133             TransactionUtil.executeInUserTransaction(transactionService, executeWork);
134         }
135         catch (AccessDeniedException e)
136         {
137             // Return a forbidden status
138
throw new WebDAVServerException(HttpServletResponse.SC_UNAUTHORIZED, e);
139         }
140         catch (Throwable JavaDoc e)
141         {
142             Throwable JavaDoc cause = e.getCause();
143             if (cause instanceof WebDAVServerException)
144             {
145                 throw (WebDAVServerException) cause;
146             }
147             else
148             {
149                 // Convert error to a server error
150
throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
151             }
152         }
153     }
154
155     /**
156      * Access the content repository to satisfy the request and generates the appropriate WebDAV
157      * response.
158      *
159      * @throws WebDAVServerException a general server exception
160      * @throws Exception any unhandled exception
161      */

162     protected abstract void executeImpl() throws WebDAVServerException, Exception JavaDoc;
163
164     /**
165      * Parses the given request body represented as an XML document and sets any necessary context
166      * ready for execution.
167      */

168     protected abstract void parseRequestBody() throws WebDAVServerException;
169
170     /**
171      * Parses the HTTP headers of the request and sets any necessary context ready for execution.
172      */

173     protected abstract void parseRequestHeaders() throws WebDAVServerException;
174
175     /**
176      * Retrieves the request body as an XML document
177      *
178      * @return The body of the request as an XML document or null if there isn't a body
179      */

180     protected Document JavaDoc getRequestBodyAsDocument() throws WebDAVServerException
181     {
182         Document JavaDoc body = null;
183
184         if (m_request.getContentLength() > 0)
185         {
186             // TODO: Do we need to do anything for chunking support?
187

188             try
189             {
190                 DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
191                 factory.setNamespaceAware(true);
192
193                 DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
194                 body = builder.parse(new InputSource JavaDoc(m_request.getReader()));
195             }
196             catch (ParserConfigurationException JavaDoc e)
197             {
198                 throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST, e);
199             }
200             catch (SAXException JavaDoc e)
201             {
202                 throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST, e);
203             }
204             catch (IOException JavaDoc e)
205             {
206                 throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST, e);
207             }
208         }
209
210         return body;
211     }
212
213     /**
214      * Returns the lock token present in the If header
215      *
216      * @return The lock token present in the If header
217      */

218     protected String JavaDoc parseIfHeader() throws WebDAVServerException
219     {
220         String JavaDoc strLockToken = null;
221
222         String JavaDoc strIf = m_request.getHeader(WebDAV.HEADER_IF);
223
224         if (logger.isDebugEnabled())
225             logger.debug("Parsing If header: " + strIf);
226
227         if (strIf != null && strIf.length() > 0)
228         {
229             if (strIf.startsWith("(<"))
230             {
231                 // Parse the tokens (only get the first one though)
232

233                 int idx = strIf.indexOf(">");
234                 if (idx != -1)
235                 {
236                     try
237                     {
238                         strLockToken = strIf.substring(WebDAV.OPAQUE_LOCK_TOKEN.length() + 2, idx);
239                     }
240                     catch (IndexOutOfBoundsException JavaDoc e)
241                     {
242                         logger.warn("Failed to parse If header: " + strIf);
243                     }
244                 }
245                 else
246                 {
247                     throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
248                 }
249
250                 // Print a warning if there are other tokens detected
251

252                 if (strIf.length() > idx + 2)
253                 {
254                     logger.warn("The If header contained more than one lock token, only one is supported");
255                 }
256             }
257             else if (strIf.startsWith("<"))
258             {
259                 logger.warn("Tagged lists in the If header are not supported");
260             }
261             else if (strIf.startsWith("(["))
262             {
263                 logger.warn("ETags in the If header are not supported");
264             }
265         }
266
267         return strLockToken;
268     }
269
270     /**
271      * Return the WebDAV protocol helper
272      *
273      * @return WebDAVHelper
274      */

275     protected final WebDAVHelper getDAVHelper()
276     {
277         return m_davHelper;
278     }
279
280     /**
281      * Return the service registry
282      *
283      * @return ServiceRegistry
284      */

285     protected final ServiceRegistry getServiceRegistry()
286     {
287         return m_davHelper.getServiceRegistry();
288     }
289
290     /**
291      * Convenience method to return the transaction service
292      *
293      * @return TransactionService
294      */

295     protected final TransactionService getTransactionService()
296     {
297         return m_davHelper.getServiceRegistry().getTransactionService();
298     }
299
300     /**
301      * Convenience method to return the node service
302      *
303      * @return NodeService
304      */

305     protected final NodeService getNodeService()
306     {
307         return m_davHelper.getNodeService();
308     }
309     
310     /**
311      * @return Returns the general file/folder manipulation service
312      */

313     protected final FileFolderService getFileFolderService()
314     {
315         return m_davHelper.getFileFolderService();
316     }
317
318     /**
319      * Convenience method to return the content service
320      *
321      * @return ContentService
322      */

323     protected final ContentService getContentService()
324     {
325         return m_davHelper.getServiceRegistry().getContentService();
326     }
327
328     /**
329      * Convenience method to return the mimetype service
330      *
331      * @return MimetypeService
332      */

333     protected final MimetypeService getMimetypeService()
334     {
335         return m_davHelper.getMimetypeService();
336     }
337     
338     /**
339      * Convenience method to return the lock service
340      *
341      * @return LockService
342      */

343     protected final LockService getLockService()
344     {
345         return m_davHelper.getLockService();
346     }
347     
348     /**
349      * Convenience method to return the authentication service
350      *
351      * @return AuthenticationService
352      */

353     protected final AuthenticationService getAuthenticationService()
354     {
355         return m_davHelper.getAuthenticationService();
356     }
357     
358     /**
359      * @return Returns the path of the servlet
360      */

361     protected final String JavaDoc getServletPath()
362     {
363         return m_request.getServletPath();
364     }
365     
366     /**
367      * Return the root node
368      *
369      * @return NodeRef
370      */

371     protected final NodeRef getRootNodeRef()
372     {
373         return m_rootNodeRef;
374     }
375
376     /**
377      * Return the relative path
378      *
379      * @return String
380      */

381     protected final String JavaDoc getPath()
382     {
383         return m_strPath;
384     }
385
386     /**
387      * Create an XML writer for the response
388      *
389      * @return XMLWriter
390      * @exception IOException
391      */

392     protected final XMLWriter createXMLWriter() throws IOException JavaDoc
393     {
394         // Check if debug output or XML pretty printing is enabled
395

396         XMLWriter writer = null;
397         
398         if (XMLPrettyPrint == true || logger.isDebugEnabled())
399         {
400             writer = new XMLWriter(m_response.getWriter(), OutputFormat.createPrettyPrint());
401         }
402         else
403         {
404             writer = new XMLWriter(m_response.getWriter(), OutputFormat.createCompactFormat());
405         }
406         
407         // Return the writer
408

409         return writer;
410     }
411
412     /**
413      * Generates the lock discovery XML response
414      *
415      * @param xml XMLWriter
416      * @param lockNode NodeRef
417      */

418     protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode) throws Exception JavaDoc
419     {
420         Attributes JavaDoc nullAttr= getDAVHelper().getNullAttributes();
421         
422         if (lockNode != null)
423         {
424             
425             // Get the lock details
426

427             NodeService nodeService = getNodeService();
428             
429             String JavaDoc owner = (String JavaDoc) nodeService.getProperty(lockNode, ContentModel.PROP_LOCK_OWNER);
430             Date JavaDoc expiryDate = (Date JavaDoc) nodeService.getProperty(lockNode, ContentModel.PROP_EXPIRY_DATE);
431             
432             // Output the XML response
433

434             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_NS_LOCK_DISCOVERY, nullAttr);
435             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_NS_ACTIVE_LOCK, nullAttr);
436              
437             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr);
438             xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE));
439             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE);
440              
441             // NOTE: We only do exclusive lock tokens at the moment
442

443             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr);
444             xml.write(DocumentHelper.createElement(WebDAV.XML_NS_EXCLUSIVE));
445             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE);
446              
447             // NOTE: We only support one level of lock at the moment
448

449             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH, nullAttr);
450             xml.write(WebDAV.ZERO);
451             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH);
452              
453             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER, nullAttr);
454             xml.write(owner);
455             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER);
456              
457             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_NS_TIMEOUT, nullAttr);
458
459             // Output the expiry time
460

461             String JavaDoc strTimeout = WebDAV.INFINITE;
462             if (expiryDate != null)
463             {
464                   long timeoutRemaining = (expiryDate.getTime() - System.currentTimeMillis())/1000L;
465               
466                   strTimeout = WebDAV.SECOND + timeoutRemaining;
467             }
468             xml.write(strTimeout);
469            
470             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_NS_TIMEOUT);
471              
472             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_NS_LOCK_TOKEN, nullAttr);
473             xml.startElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF, nullAttr);
474            
475             xml.write(WebDAV.makeLockToken(lockNode, owner));
476             
477             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF);
478             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_NS_LOCK_TOKEN);
479            
480             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_NS_ACTIVE_LOCK);
481             xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_NS_LOCK_DISCOVERY);
482         }
483     }
484     
485     /**
486      * Generates a list of namespace declarations for the response
487      */

488     protected String JavaDoc generateNamespaceDeclarations(HashMap JavaDoc<String JavaDoc,String JavaDoc> nameSpaces)
489     {
490         StringBuilder JavaDoc ns = new StringBuilder JavaDoc();
491
492         ns.append(" ");
493         ns.append(WebDAV.XML_NS);
494         ns.append(":");
495         ns.append(WebDAV.DAV_NS);
496         ns.append("=\"");
497         ns.append(WebDAV.DEFAULT_NAMESPACE_URI);
498         ns.append("\"");
499
500         // Add additional namespaces
501

502         if ( nameSpaces != null)
503         {
504             Iterator JavaDoc<String JavaDoc> namespaceList = nameSpaces.keySet().iterator();
505     
506             while (namespaceList.hasNext())
507             {
508                 String JavaDoc strNamespaceUri = namespaceList.next();
509                 String JavaDoc strNamespaceName = nameSpaces.get(strNamespaceUri);
510                 
511                 ns.append(" ").append(WebDAV.XML_NS).append(":").append(strNamespaceName).append("=\"");
512                 ns.append(strNamespaceUri).append("\" ");
513             }
514         }
515         
516         return ns.toString();
517     }
518
519     
520 }
521
Popular Tags