1   /**
2    * Copyright (c) 2000-2009 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   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portal.webdav.methods;
21  
22  import com.liferay.lock.model.Lock;
23  import com.liferay.portal.kernel.log.Log;
24  import com.liferay.portal.kernel.log.LogFactoryUtil;
25  import com.liferay.portal.kernel.util.ContentTypes;
26  import com.liferay.portal.kernel.util.FileUtil;
27  import com.liferay.portal.kernel.util.GetterUtil;
28  import com.liferay.portal.kernel.util.Time;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.webdav.Status;
31  import com.liferay.portal.webdav.WebDAVException;
32  import com.liferay.portal.webdav.WebDAVRequest;
33  import com.liferay.portal.webdav.WebDAVStorage;
34  import com.liferay.portal.webdav.WebDAVUtil;
35  import com.liferay.util.servlet.ServletResponseUtil;
36  import com.liferay.util.xml.XMLFormatter;
37  
38  import java.io.StringReader;
39  
40  import java.util.List;
41  
42  import javax.servlet.http.HttpServletRequest;
43  import javax.servlet.http.HttpServletResponse;
44  
45  import org.dom4j.Document;
46  import org.dom4j.Element;
47  import org.dom4j.io.SAXReader;
48  
49  /**
50   * <a href="LockMethodImpl.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Alexander Chow
53   *
54   */
55  public class LockMethodImpl implements Method {
56  
57      public int process(WebDAVRequest webDavRequest) throws WebDAVException {
58          try {
59              return doProcess(webDavRequest);
60          }
61          catch (Exception e) {
62              throw new WebDAVException(e);
63          }
64      }
65  
66      protected int doProcess(WebDAVRequest webDavRequest) throws Exception {
67          WebDAVStorage storage = webDavRequest.getWebDAVStorage();
68  
69          if (!storage.isSupportsClassTwo()) {
70              return HttpServletResponse.SC_METHOD_NOT_ALLOWED;
71          }
72  
73          HttpServletRequest request = webDavRequest.getHttpServletRequest();
74          HttpServletResponse response = webDavRequest.getHttpServletResponse();
75  
76          Lock lock = null;
77          Status status = null;
78  
79          String lockUuid = webDavRequest.getLockUuid();
80          long timeout = WebDAVUtil.getTimeout(request);
81  
82          if (Validator.isNull(lockUuid)) {
83  
84              // Create new lock
85  
86              String owner = null;
87              String xml = new String(
88                  FileUtil.getBytes(request.getInputStream()));
89  
90              if (Validator.isNotNull(xml)) {
91                  if (_log.isDebugEnabled()) {
92                      _log.debug(
93                          "Request XML\n" + XMLFormatter.toString(xml));
94                  }
95  
96                  SAXReader reader = new SAXReader();
97  
98                  Document doc = reader.read(new StringReader(xml));
99  
100                 Element root = doc.getRootElement();
101 
102                 boolean exclusive = false;
103 
104                 List<Element> lockscopeEls = root.element(
105                     "lockscope").elements();
106 
107                 for (Element scopeEl : lockscopeEls) {
108                     String name = GetterUtil.getString(scopeEl.getName());
109 
110                     if (name.equals("exclusive")) {
111                         exclusive = true;
112                     }
113                 }
114 
115                 if (!exclusive) {
116                     return HttpServletResponse.SC_BAD_REQUEST;
117                 }
118 
119                 Element ownerEl = root.element("owner");
120 
121                 owner = ownerEl.getTextTrim();
122 
123                 if (Validator.isNull(owner)) {
124                     List<Element> childEls = ownerEl.elements("href");
125 
126                     for (Element childEl : childEls) {
127                         owner =
128                             "<D:href>" + childEl.getTextTrim() + "</D:href>";
129                     }
130                 }
131             }
132             else {
133                 _log.error("Empty request XML");
134 
135                 return HttpServletResponse.SC_PRECONDITION_FAILED;
136             }
137 
138             status = storage.lockResource(webDavRequest, owner, timeout);
139 
140             lock = (Lock)status.getObject();
141         }
142         else {
143 
144             // Refresh existing lock
145 
146             lock = storage.refreshResourceLock(
147                 webDavRequest, lockUuid, timeout);
148 
149             status = new Status(HttpServletResponse.SC_OK);
150         }
151 
152         // Return lock details
153 
154         if (lock == null) {
155             return status.getCode();
156         }
157 
158         long depth = WebDAVUtil.getDepth(request);
159 
160         String xml = getResponseXML(lock, depth);
161 
162         if (_log.isDebugEnabled()) {
163             _log.debug("Response XML\n" + xml);
164         }
165 
166         String lockToken = "<" + WebDAVUtil.TOKEN_PREFIX + lock.getUuid() + ">";
167 
168         response.setContentType(ContentTypes.TEXT_XML_UTF8);
169         response.setHeader("Lock-Token", lockToken);
170         response.setStatus(status.getCode());
171 
172         if (_log.isInfoEnabled()) {
173             _log.info("Returning lock token " + lockToken);
174             _log.info("Status code " + status.getCode());
175         }
176 
177         try {
178             ServletResponseUtil.write(response, xml);
179         }
180         catch (Exception e) {
181             if (_log.isWarnEnabled()) {
182                 _log.warn(e);
183             }
184         }
185 
186         return -1;
187     }
188 
189     protected String getResponseXML(Lock lock, long depth) throws Exception {
190         StringBuilder sb = new StringBuilder();
191 
192         long timeoutSecs = lock.getExpirationTime() / Time.SECOND;
193 
194         sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
195         sb.append("<D:prop xmlns:D=\"DAV:\">");
196         sb.append("<D:lockdiscovery>");
197         sb.append("<D:activelock>");
198         sb.append("<D:locktype><D:write/></D:locktype>");
199         sb.append("<D:lockscope><D:exclusive/></D:lockscope>");
200 
201         if (depth < 0) {
202             sb.append("<D:depth>Infinity</D:depth>");
203         }
204 
205         sb.append("<D:owner>" + lock.getOwner() + "</D:owner>");
206         sb.append("<D:timeout>Second-" + timeoutSecs + "</D:timeout>");
207         sb.append(
208             "<D:locktoken><D:href>" + WebDAVUtil.TOKEN_PREFIX + lock.getUuid() +
209             "</D:href></D:locktoken>");
210         sb.append("</D:activelock>");
211         sb.append("</D:lockdiscovery>");
212         sb.append("</D:prop>");
213 
214         return XMLFormatter.toString(sb.toString());
215     }
216 
217     private static Log _log = LogFactoryUtil.getLog(LockMethodImpl.class);
218 
219 }