1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.webdav.methods;
16  
17  import com.liferay.portal.kernel.exception.PortalException;
18  import com.liferay.portal.kernel.exception.SystemException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.util.FileUtil;
22  import com.liferay.portal.kernel.util.StringPool;
23  import com.liferay.portal.kernel.util.Tuple;
24  import com.liferay.portal.kernel.util.Validator;
25  import com.liferay.portal.kernel.xml.Document;
26  import com.liferay.portal.kernel.xml.Element;
27  import com.liferay.portal.kernel.xml.Namespace;
28  import com.liferay.portal.kernel.xml.SAXReaderUtil;
29  import com.liferay.portal.model.WebDAVProps;
30  import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
31  import com.liferay.portal.webdav.InvalidRequestException;
32  import com.liferay.portal.webdav.LockException;
33  import com.liferay.portal.webdav.Resource;
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.xml.XMLFormatter;
39  
40  import java.util.HashSet;
41  import java.util.Iterator;
42  import java.util.List;
43  import java.util.Set;
44  
45  import javax.servlet.http.HttpServletRequest;
46  import javax.servlet.http.HttpServletResponse;
47  
48  /**
49   * <a href="ProppatchMethodImpl.java.html"><b><i>View Source</i></b></a>
50   *
51   * @author Alexander Chow
52   */
53  public class ProppatchMethodImpl extends BasePropMethodImpl {
54  
55      public int process(WebDAVRequest webDavRequest) throws WebDAVException {
56          try {
57              Set<Tuple> props = processInstructions(webDavRequest);
58  
59              return writeResponseXML(webDavRequest, props);
60          }
61          catch (InvalidRequestException ire) {
62              if (_log.isInfoEnabled()) {
63                  _log.info(ire.getMessage(), ire);
64              }
65  
66              return HttpServletResponse.SC_BAD_REQUEST;
67          }
68          catch (LockException le) {
69              return WebDAVUtil.SC_LOCKED;
70          }
71          catch (Exception e) {
72              throw new WebDAVException(e);
73          }
74      }
75  
76      protected WebDAVProps getStoredProperties(WebDAVRequest webDavRequest)
77          throws PortalException, SystemException {
78  
79          WebDAVStorage storage = webDavRequest.getWebDAVStorage();
80  
81          Resource resource = storage.getResource(webDavRequest);
82  
83          WebDAVProps webDavProps = null;
84  
85          if (resource.getPrimaryKey() <= 0) {
86              if (_log.isWarnEnabled()) {
87                  _log.warn("There is no primary key set for resource");
88              }
89  
90              throw new InvalidRequestException();
91          }
92          else if (resource.isLocked()) {
93              throw new LockException();
94          }
95  
96          webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
97              webDavRequest.getCompanyId(), resource.getClassName(),
98              resource.getPrimaryKey());
99  
100         return webDavProps;
101     }
102 
103     protected Set<Tuple> processInstructions(WebDAVRequest webDavRequest)
104         throws InvalidRequestException, LockException {
105 
106         try {
107             Set<Tuple> newProps = new HashSet<Tuple>();
108 
109             HttpServletRequest request = webDavRequest.getHttpServletRequest();
110 
111             WebDAVProps webDavProps = getStoredProperties(webDavRequest);
112 
113             String xml = new String(
114                 FileUtil.getBytes(request.getInputStream()));
115 
116             if (Validator.isNull(xml)) {
117                 return newProps;
118             }
119 
120             if (_log.isInfoEnabled()) {
121                 _log.info(
122                     "Request XML: \n" +
123                         XMLFormatter.toString(xml, StringPool.FOUR_SPACES));
124             }
125 
126             Document doc = SAXReaderUtil.read(xml);
127 
128             Element root = doc.getRootElement();
129 
130             Iterator<Element> itr = root.elements().iterator();
131 
132             while (itr.hasNext()) {
133                 Element instruction = itr.next();
134 
135                 List<Element> list = instruction.elements();
136 
137                 if (list.size() != 1) {
138                     throw new InvalidRequestException(
139                         "There should only be one <prop /> per set or remove " +
140                             "instruction.");
141                 }
142 
143                 Element prop = list.get(0);
144 
145                 if (!prop.getName().equals("prop") ||
146                     !prop.getNamespaceURI().equals(
147                         WebDAVUtil.DAV_URI.getURI())) {
148 
149                     throw new InvalidRequestException(
150                         "Invalid <prop /> element " + prop);
151                 }
152 
153                 list = prop.elements();
154 
155                 if (list.size() != 1) {
156                     throw new InvalidRequestException(
157                         "<prop /> should only have one subelement.");
158                 }
159 
160                 Element customProp = list.get(0);
161 
162                 String name = customProp.getName();
163                 String prefix = customProp.getNamespacePrefix();
164                 String uri = customProp.getNamespaceURI();
165                 String text = customProp.getText();
166 
167                 Namespace namespace = null;
168 
169                 if (uri.equals(WebDAVUtil.DAV_URI.getURI())) {
170                     namespace = WebDAVUtil.DAV_URI;
171                 }
172                 else if (Validator.isNull(prefix)) {
173                     namespace = SAXReaderUtil.createNamespace(uri);
174                 }
175                 else {
176                     namespace = SAXReaderUtil.createNamespace(prefix, uri);
177                 }
178 
179                 if (instruction.getName().equals("set")) {
180                     if (Validator.isNull(text)) {
181                         webDavProps.addProp(name, prefix, uri);
182                     }
183                     else {
184                         webDavProps.addProp(name, prefix, uri, text);
185                     }
186 
187                     newProps.add(new Tuple(customProp.getName(), namespace));
188                 }
189                 else if (instruction.getName().equals("remove")) {
190                     webDavProps.removeProp(name, prefix, uri);
191                 }
192                 else {
193                     throw new InvalidRequestException(
194                         "Instead of set/remove instruction, received " +
195                             instruction);
196                 }
197             }
198 
199             WebDAVPropsLocalServiceUtil.storeWebDAVProps(webDavProps);
200 
201             return newProps;
202         }
203         catch (LockException le) {
204             throw le;
205         }
206         catch (Exception e) {
207             throw new InvalidRequestException(e);
208         }
209     }
210 
211     private static Log _log = LogFactoryUtil.getLog(ProppatchMethodImpl.class);
212 
213 }