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