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