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