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.io.unsync.UnsyncStringReader;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.util.ContentTypes;
29  import com.liferay.portal.kernel.util.FileUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.Time;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.model.Lock;
34  import com.liferay.portal.webdav.Status;
35  import com.liferay.portal.webdav.WebDAVException;
36  import com.liferay.portal.webdav.WebDAVRequest;
37  import com.liferay.portal.webdav.WebDAVStorage;
38  import com.liferay.portal.webdav.WebDAVUtil;
39  import com.liferay.util.servlet.ServletResponseUtil;
40  import com.liferay.util.xml.XMLFormatter;
41  
42  import java.util.List;
43  
44  import javax.servlet.http.HttpServletRequest;
45  import javax.servlet.http.HttpServletResponse;
46  
47  import org.dom4j.Document;
48  import org.dom4j.Element;
49  import org.dom4j.io.SAXReader;
50  
51  /**
52   * <a href="LockMethodImpl.java.html"><b><i>View Source</i></b></a>
53   *
54   * @author Alexander Chow
55   */
56  public class LockMethodImpl implements Method {
57  
58      public int process(WebDAVRequest webDavRequest) throws WebDAVException {
59          try {
60              return doProcess(webDavRequest);
61          }
62          catch (Exception e) {
63              throw new WebDAVException(e);
64          }
65      }
66  
67      protected int doProcess(WebDAVRequest webDavRequest) throws Exception {
68          WebDAVStorage storage = webDavRequest.getWebDAVStorage();
69  
70          if (!storage.isSupportsClassTwo()) {
71              return HttpServletResponse.SC_METHOD_NOT_ALLOWED;
72          }
73  
74          HttpServletRequest request = webDavRequest.getHttpServletRequest();
75          HttpServletResponse response = webDavRequest.getHttpServletResponse();
76  
77          Lock lock = null;
78          Status status = null;
79  
80          String lockUuid = webDavRequest.getLockUuid();
81          long timeout = WebDAVUtil.getTimeout(request);
82  
83          if (Validator.isNull(lockUuid)) {
84  
85              // Create new lock
86  
87              String owner = null;
88              String xml = new String(
89                  FileUtil.getBytes(request.getInputStream()));
90  
91              if (Validator.isNotNull(xml)) {
92                  if (_log.isDebugEnabled()) {
93                      _log.debug(
94                          "Request XML\n" + XMLFormatter.toString(xml));
95                  }
96  
97                  SAXReader reader = new SAXReader();
98  
99                  Document doc = reader.read(new UnsyncStringReader(xml));
100 
101                 Element root = doc.getRootElement();
102 
103                 boolean exclusive = false;
104 
105                 List<Element> lockscopeEls = root.element(
106                     "lockscope").elements();
107 
108                 for (Element scopeEl : lockscopeEls) {
109                     String name = GetterUtil.getString(scopeEl.getName());
110 
111                     if (name.equals("exclusive")) {
112                         exclusive = true;
113                     }
114                 }
115 
116                 if (!exclusive) {
117                     return HttpServletResponse.SC_BAD_REQUEST;
118                 }
119 
120                 Element ownerEl = root.element("owner");
121 
122                 owner = ownerEl.getTextTrim();
123 
124                 if (Validator.isNull(owner)) {
125                     List<Element> childEls = ownerEl.elements("href");
126 
127                     for (Element childEl : childEls) {
128                         owner =
129                             "<D:href>" + childEl.getTextTrim() + "</D:href>";
130                     }
131                 }
132             }
133             else {
134                 _log.error("Empty request XML");
135 
136                 return HttpServletResponse.SC_PRECONDITION_FAILED;
137             }
138 
139             status = storage.lockResource(webDavRequest, owner, timeout);
140 
141             lock = (Lock)status.getObject();
142         }
143         else {
144 
145             // Refresh existing lock
146 
147             lock = storage.refreshResourceLock(
148                 webDavRequest, lockUuid, timeout);
149 
150             status = new Status(HttpServletResponse.SC_OK);
151         }
152 
153         // Return lock details
154 
155         if (lock == null) {
156             return status.getCode();
157         }
158 
159         long depth = WebDAVUtil.getDepth(request);
160 
161         String xml = getResponseXML(lock, depth);
162 
163         if (_log.isDebugEnabled()) {
164             _log.debug("Response XML\n" + xml);
165         }
166 
167         String lockToken = "<" + WebDAVUtil.TOKEN_PREFIX + lock.getUuid() + ">";
168 
169         response.setContentType(ContentTypes.TEXT_XML_UTF8);
170         response.setHeader("Lock-Token", lockToken);
171         response.setStatus(status.getCode());
172 
173         if (_log.isDebugEnabled()) {
174             _log.debug("Returning lock token " + lockToken);
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 status.getCode();
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 }