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