1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.webdav.methods;
16  
17  import com.liferay.portal.NoSuchLockException;
18  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.util.ContentTypes;
22  import com.liferay.portal.kernel.util.FileUtil;
23  import com.liferay.portal.kernel.util.GetterUtil;
24  import com.liferay.portal.kernel.util.StringBundler;
25  import com.liferay.portal.kernel.util.Time;
26  import com.liferay.portal.kernel.util.Validator;
27  import com.liferay.portal.model.Lock;
28  import com.liferay.portal.webdav.Status;
29  import com.liferay.portal.webdav.WebDAVException;
30  import com.liferay.portal.webdav.WebDAVRequest;
31  import com.liferay.portal.webdav.WebDAVStorage;
32  import com.liferay.portal.webdav.WebDAVUtil;
33  import com.liferay.util.servlet.ServletResponseUtil;
34  import com.liferay.util.xml.XMLFormatter;
35  
36  import java.util.List;
37  
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpServletResponse;
40  
41  import org.dom4j.Document;
42  import org.dom4j.Element;
43  import org.dom4j.io.SAXReader;
44  
45  /**
46   * <a href="LockMethodImpl.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Alexander Chow
49   */
50  public class LockMethodImpl implements Method {
51  
52      public int process(WebDAVRequest webDavRequest) throws WebDAVException {
53          try {
54              return doProcess(webDavRequest);
55          }
56          catch (Exception e) {
57              throw new WebDAVException(e);
58          }
59      }
60  
61      protected int doProcess(WebDAVRequest webDavRequest) throws Exception {
62          WebDAVStorage storage = webDavRequest.getWebDAVStorage();
63  
64          if (!storage.isSupportsClassTwo()) {
65              return HttpServletResponse.SC_METHOD_NOT_ALLOWED;
66          }
67  
68          HttpServletRequest request = webDavRequest.getHttpServletRequest();
69          HttpServletResponse response = webDavRequest.getHttpServletResponse();
70  
71          Lock lock = null;
72          Status status = null;
73  
74          String lockUuid = webDavRequest.getLockUuid();
75          long timeout = WebDAVUtil.getTimeout(request);
76  
77          if (Validator.isNull(lockUuid)) {
78  
79              // Create new lock
80  
81              String owner = null;
82              String xml = new String(
83                  FileUtil.getBytes(request.getInputStream()));
84  
85              if (Validator.isNotNull(xml)) {
86                  if (_log.isDebugEnabled()) {
87                      _log.debug(
88                          "Request XML\n" + XMLFormatter.toString(xml));
89                  }
90  
91                  SAXReader reader = new SAXReader();
92  
93                  Document doc = reader.read(new UnsyncStringReader(xml));
94  
95                  Element root = doc.getRootElement();
96  
97                  boolean exclusive = false;
98  
99                  List<Element> lockscopeEls = root.element(
100                     "lockscope").elements();
101 
102                 for (Element scopeEl : lockscopeEls) {
103                     String name = GetterUtil.getString(scopeEl.getName());
104 
105                     if (name.equals("exclusive")) {
106                         exclusive = true;
107                     }
108                 }
109 
110                 if (!exclusive) {
111                     return HttpServletResponse.SC_BAD_REQUEST;
112                 }
113 
114                 Element ownerEl = root.element("owner");
115 
116                 owner = ownerEl.getTextTrim();
117 
118                 if (Validator.isNull(owner)) {
119                     List<Element> childEls = ownerEl.elements("href");
120 
121                     for (Element childEl : childEls) {
122                         owner =
123                             "<D:href>" + childEl.getTextTrim() + "</D:href>";
124                     }
125                 }
126             }
127             else {
128                 _log.error("Empty request XML");
129 
130                 return HttpServletResponse.SC_PRECONDITION_FAILED;
131             }
132 
133             status = storage.lockResource(webDavRequest, owner, timeout);
134 
135             lock = (Lock)status.getObject();
136         }
137         else {
138             try {
139                 // Refresh existing lock
140 
141                 lock = storage.refreshResourceLock(
142                     webDavRequest, lockUuid, timeout);
143 
144                 status = new Status(HttpServletResponse.SC_OK);
145             }
146             catch (WebDAVException wde) {
147                 if (wde.getCause() instanceof NoSuchLockException) {
148                     return HttpServletResponse.SC_PRECONDITION_FAILED;
149                 }
150                 else {
151                     throw wde;
152                 }
153             }
154         }
155 
156         // Return lock details
157 
158         if (lock == null) {
159             return status.getCode();
160         }
161 
162         long depth = WebDAVUtil.getDepth(request);
163 
164         String xml = getResponseXML(lock, depth);
165 
166         if (_log.isDebugEnabled()) {
167             _log.debug("Response XML\n" + xml);
168         }
169 
170         String lockToken = "<" + WebDAVUtil.TOKEN_PREFIX + lock.getUuid() + ">";
171 
172         response.setContentType(ContentTypes.TEXT_XML_UTF8);
173         response.setHeader("Lock-Token", lockToken);
174         response.setStatus(status.getCode());
175 
176         if (_log.isDebugEnabled()) {
177             _log.debug("Returning lock token " + lockToken);
178         }
179 
180         try {
181             ServletResponseUtil.write(response, xml);
182         }
183         catch (Exception e) {
184             if (_log.isWarnEnabled()) {
185                 _log.warn(e);
186             }
187         }
188 
189         return status.getCode();
190     }
191 
192     protected String getResponseXML(Lock lock, long depth) throws Exception {
193         StringBundler sb = new StringBundler(20);
194 
195         long timeoutSecs = lock.getExpirationTime() / Time.SECOND;
196 
197         sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
198         sb.append("<D:prop xmlns:D=\"DAV:\">");
199         sb.append("<D:lockdiscovery>");
200         sb.append("<D:activelock>");
201         sb.append("<D:locktype><D:write/></D:locktype>");
202         sb.append("<D:lockscope><D:exclusive/></D:lockscope>");
203 
204         if (depth < 0) {
205             sb.append("<D:depth>Infinity</D:depth>");
206         }
207 
208         sb.append("<D:owner>");
209         sb.append(lock.getOwner());
210         sb.append("</D:owner>");
211         sb.append("<D:timeout>Second-");
212         sb.append(timeoutSecs);
213         sb.append("</D:timeout>");
214         sb.append("<D:locktoken><D:href>");
215         sb.append(WebDAVUtil.TOKEN_PREFIX);
216         sb.append(lock.getUuid());
217         sb.append("</D:href></D:locktoken>");
218         sb.append("</D:activelock>");
219         sb.append("</D:lockdiscovery>");
220         sb.append("</D:prop>");
221 
222         return XMLFormatter.toString(sb.toString());
223     }
224 
225     private static Log _log = LogFactoryUtil.getLog(LockMethodImpl.class);
226 
227 }