1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions 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.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.util.ContentTypes;
28  import com.liferay.portal.kernel.util.FileUtil;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.Tuple;
31  import com.liferay.portal.kernel.util.Validator;
32  import com.liferay.portal.kernel.xml.Document;
33  import com.liferay.portal.kernel.xml.Element;
34  import com.liferay.portal.kernel.xml.Namespace;
35  import com.liferay.portal.kernel.xml.SAXReaderUtil;
36  import com.liferay.portal.model.WebDAVProps;
37  import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
38  import com.liferay.portal.webdav.InvalidRequestException;
39  import com.liferay.portal.webdav.LockException;
40  import com.liferay.portal.webdav.Resource;
41  import com.liferay.portal.webdav.WebDAVException;
42  import com.liferay.portal.webdav.WebDAVRequest;
43  import com.liferay.portal.webdav.WebDAVStorage;
44  import com.liferay.portal.webdav.WebDAVUtil;
45  import com.liferay.util.servlet.ServletResponseUtil;
46  import com.liferay.util.xml.XMLFormatter;
47  
48  import java.util.HashSet;
49  import java.util.Iterator;
50  import java.util.List;
51  import java.util.Set;
52  
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.HttpServletResponse;
55  
56  import org.apache.commons.logging.Log;
57  import org.apache.commons.logging.LogFactory;
58  
59  /**
60   * <a href="ProppatchMethodImpl.java.html"><b><i>View Source</i></b></a>
61   *
62   * @author Alexander Chow
63   *
64   */
65  public class ProppatchMethodImpl extends BasePropMethodImpl {
66  
67      public int process(WebDAVRequest webDavRequest) throws WebDAVException {
68          try {
69              HttpServletResponse response =
70                  webDavRequest.getHttpServletResponse();
71  
72              Set<Tuple> props = processInstructions(webDavRequest);
73  
74              String xml = getResponseXML(webDavRequest, props);
75  
76              // Must set the status prior to writing the XML
77  
78              response.setContentType(ContentTypes.TEXT_XML_UTF8);
79              response.setStatus(WebDAVUtil.SC_MULTI_STATUS);
80  
81              try {
82                  ServletResponseUtil.write(response, xml);
83              }
84              catch (Exception e) {
85                  if (_log.isWarnEnabled()) {
86                      _log.warn(e);
87                  }
88              }
89  
90              return -1;
91          }
92          catch (InvalidRequestException ire) {
93              if (_log.isInfoEnabled()) {
94                  _log.info(ire.getMessage(), ire);
95              }
96  
97              return HttpServletResponse.SC_BAD_REQUEST;
98          }
99          catch (LockException le) {
100             return WebDAVUtil.SC_LOCKED;
101         }
102         catch (Exception e) {
103             throw new WebDAVException(e);
104         }
105     }
106 
107     protected WebDAVProps getStoredProperties(WebDAVRequest webDavRequest)
108         throws PortalException, SystemException {
109 
110         WebDAVStorage storage = webDavRequest.getWebDAVStorage();
111 
112         Resource resource = storage.getResource(webDavRequest);
113 
114         WebDAVProps webDavProps = null;
115 
116         if (resource.getPrimaryKey() <= 0) {
117             if (_log.isWarnEnabled()) {
118                 _log.warn("There is no primary key set for resource");
119             }
120 
121             throw new InvalidRequestException();
122         }
123         else if (resource.isLocked()) {
124             throw new LockException();
125         }
126 
127         webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
128             webDavRequest.getCompanyId(), resource.getClassName(),
129             resource.getPrimaryKey());
130 
131         return webDavProps;
132     }
133 
134     protected Set<Tuple> processInstructions(WebDAVRequest webDavRequest)
135         throws InvalidRequestException, LockException {
136 
137         try {
138             Set<Tuple> newProps = new HashSet<Tuple>();
139 
140             HttpServletRequest request = webDavRequest.getHttpServletRequest();
141 
142             WebDAVProps webDavProps = getStoredProperties(webDavRequest);
143 
144             String xml = new String(
145                 FileUtil.getBytes(request.getInputStream()));
146 
147             if (Validator.isNull(xml)) {
148                 return newProps;
149             }
150 
151             if (_log.isDebugEnabled()) {
152                 _log.debug(
153                     "Request XML: \n" +
154                         XMLFormatter.toString(xml, StringPool.FOUR_SPACES));
155             }
156 
157             Document doc = SAXReaderUtil.read(xml);
158 
159             Element root = doc.getRootElement();
160 
161             Iterator<Element> itr = root.elements().iterator();
162 
163             while (itr.hasNext()) {
164                 Element instruction = itr.next();
165 
166                 List<Element> list = instruction.elements();
167 
168                 if (list.size() != 1) {
169                     throw new InvalidRequestException(
170                         "There should only be one <prop /> per set or remove " +
171                             "instruction.");
172                 }
173 
174                 Element prop = list.get(0);
175 
176                 if (!prop.getName().equals("prop") ||
177                     !prop.getNamespaceURI().equals(
178                         WebDAVUtil.DAV_URI.getURI())) {
179 
180                     throw new InvalidRequestException(
181                         "Invalid <prop /> element " + prop);
182                 }
183 
184                 list = prop.elements();
185 
186                 if (list.size() != 1) {
187                     throw new InvalidRequestException(
188                         "<prop /> should only have one subelement.");
189                 }
190 
191                 Element customProp = list.get(0);
192 
193                 String name = customProp.getName();
194                 String prefix = customProp.getNamespacePrefix();
195                 String uri = customProp.getNamespaceURI();
196                 String text = customProp.getText();
197 
198                 Namespace namespace = null;
199 
200                 if (uri.equals(WebDAVUtil.DAV_URI.getURI())) {
201                     namespace = WebDAVUtil.DAV_URI;
202                 }
203                 else if (Validator.isNull(prefix)) {
204                     namespace = SAXReaderUtil.createNamespace(uri);
205                 }
206                 else {
207                     namespace = SAXReaderUtil.createNamespace(prefix, uri);
208                 }
209 
210                 if (instruction.getName().equals("set")) {
211                     if (Validator.isNull(text)) {
212                         webDavProps.addProp(name, prefix, uri);
213                     }
214                     else {
215                         webDavProps.addProp(name, prefix, uri, text);
216                     }
217 
218                     newProps.add(new Tuple(customProp.getName(), namespace));
219                 }
220                 else if (instruction.getName().equals("remove")) {
221                     webDavProps.removeProp(name, prefix, uri);
222                 }
223                 else {
224                     throw new InvalidRequestException(
225                         "Instead of set/remove instruction, received " +
226                             instruction);
227                 }
228             }
229 
230             WebDAVPropsLocalServiceUtil.storeWebDAVProps(webDavProps);
231 
232             return newProps;
233         }
234         catch (LockException le) {
235             throw le;
236         }
237         catch (Exception e) {
238             throw new InvalidRequestException(e);
239         }
240     }
241 
242     private static Log _log = LogFactory.getLog(ProppatchMethodImpl.class);
243 
244 }