1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.webdav.methods;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.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.Lock;
30  import com.liferay.portal.model.WebDAVProps;
31  import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
32  import com.liferay.portal.webdav.InvalidRequestException;
33  import com.liferay.portal.webdav.LockException;
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.xml.XMLFormatter;
40  
41  import java.util.HashSet;
42  import java.util.Iterator;
43  import java.util.List;
44  import java.util.Set;
45  
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpServletResponse;
48  
49  /**
50   * <a href="ProppatchMethodImpl.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Alexander Chow
53   */
54  public class ProppatchMethodImpl extends BasePropMethodImpl {
55  
56      public int process(WebDAVRequest webDavRequest) throws WebDAVException {
57          try {
58              Set<Tuple> props = processInstructions(webDavRequest);
59  
60              return writeResponseXML(webDavRequest, props);
61          }
62          catch (InvalidRequestException ire) {
63              if (_log.isInfoEnabled()) {
64                  _log.info(ire.getMessage(), ire);
65              }
66  
67              return HttpServletResponse.SC_BAD_REQUEST;
68          }
69          catch (LockException le) {
70              return WebDAVUtil.SC_LOCKED;
71          }
72          catch (Exception e) {
73              throw new WebDAVException(e);
74          }
75      }
76  
77      protected WebDAVProps getStoredProperties(WebDAVRequest webDavRequest)
78          throws PortalException, SystemException {
79  
80          WebDAVStorage storage = webDavRequest.getWebDAVStorage();
81  
82          Resource resource = storage.getResource(webDavRequest);
83  
84          WebDAVProps webDavProps = null;
85  
86          if (resource.getPrimaryKey() <= 0) {
87              if (_log.isWarnEnabled()) {
88                  _log.warn("There is no primary key set for resource");
89              }
90  
91              throw new InvalidRequestException();
92          }
93          else if (resource.isLocked()) {
94              Lock lock = resource.getLock();
95  
96              if ((lock == null) ||
97                  !lock.getUuid().equals(webDavRequest.getLockUuid())) {
98  
99                  throw new LockException();
100             }
101         }
102 
103         webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
104             webDavRequest.getCompanyId(), resource.getClassName(),
105             resource.getPrimaryKey());
106 
107         return webDavProps;
108     }
109 
110     protected Set<Tuple> processInstructions(WebDAVRequest webDavRequest)
111         throws InvalidRequestException, LockException {
112 
113         try {
114             Set<Tuple> newProps = new HashSet<Tuple>();
115 
116             HttpServletRequest request = webDavRequest.getHttpServletRequest();
117 
118             WebDAVProps webDavProps = getStoredProperties(webDavRequest);
119 
120             String xml = new String(
121                 FileUtil.getBytes(request.getInputStream()));
122 
123             if (Validator.isNull(xml)) {
124                 return newProps;
125             }
126 
127             if (_log.isInfoEnabled()) {
128                 _log.info(
129                     "Request XML: \n" +
130                         XMLFormatter.toString(xml, StringPool.FOUR_SPACES));
131             }
132 
133             Document document = SAXReaderUtil.read(xml);
134 
135             Element rootElement = document.getRootElement();
136 
137             Iterator<Element> itr = rootElement.elements().iterator();
138 
139             while (itr.hasNext()) {
140                 Element instructionElement = itr.next();
141 
142                 List<Element> propElements = instructionElement.elements();
143 
144                 if (propElements.size() != 1) {
145                     throw new InvalidRequestException(
146                         "There should only be one <prop /> per set or remove " +
147                             "instruction.");
148                 }
149 
150                 Element propElement = propElements.get(0);
151 
152                 if (!propElement.getName().equals("prop") ||
153                     !propElement.getNamespaceURI().equals(
154                         WebDAVUtil.DAV_URI.getURI())) {
155 
156                     throw new InvalidRequestException(
157                         "Invalid <prop /> element " + propElement);
158                 }
159 
160                 List<Element> customPropElements = propElement.elements();
161 
162                 for (Element customPropElement : customPropElements) {
163                     String name = customPropElement.getName();
164                     String prefix = customPropElement.getNamespacePrefix();
165                     String uri = customPropElement.getNamespaceURI();
166                     String text = customPropElement.getText();
167 
168                     Namespace namespace = null;
169 
170                     if (uri.equals(WebDAVUtil.DAV_URI.getURI())) {
171                         namespace = WebDAVUtil.DAV_URI;
172                     }
173                     else if (Validator.isNull(prefix)) {
174                         namespace = SAXReaderUtil.createNamespace(uri);
175                     }
176                     else {
177                         namespace = SAXReaderUtil.createNamespace(prefix, uri);
178                     }
179 
180                     if (instructionElement.getName().equals("set")) {
181                         if (Validator.isNull(text)) {
182                             webDavProps.addProp(name, prefix, uri);
183                         }
184                         else {
185                             webDavProps.addProp(name, prefix, uri, text);
186                         }
187 
188                         newProps.add(
189                             new Tuple(customPropElement.getName(), namespace));
190                     }
191                     else if (instructionElement.getName().equals("remove")) {
192                         webDavProps.removeProp(name, prefix, uri);
193                     }
194                     else {
195                         throw new InvalidRequestException(
196                             "Instead of set/remove instruction, received " +
197                                 instructionElement);
198                     }
199                 }
200             }
201 
202             WebDAVPropsLocalServiceUtil.storeWebDAVProps(webDavProps);
203 
204             return newProps;
205         }
206         catch (LockException le) {
207             throw le;
208         }
209         catch (Exception e) {
210             throw new InvalidRequestException(e);
211         }
212     }
213 
214     private static Log _log = LogFactoryUtil.getLog(ProppatchMethodImpl.class);
215 
216 }