001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.webdav.methods;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.FileUtil;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.kernel.webdav.Resource;
025    import com.liferay.portal.kernel.webdav.WebDAVException;
026    import com.liferay.portal.kernel.webdav.WebDAVRequest;
027    import com.liferay.portal.kernel.webdav.WebDAVStorage;
028    import com.liferay.portal.kernel.webdav.WebDAVUtil;
029    import com.liferay.portal.kernel.xml.Document;
030    import com.liferay.portal.kernel.xml.Element;
031    import com.liferay.portal.kernel.xml.Namespace;
032    import com.liferay.portal.kernel.xml.QName;
033    import com.liferay.portal.kernel.xml.SAXReaderUtil;
034    import com.liferay.portal.model.Lock;
035    import com.liferay.portal.model.WebDAVProps;
036    import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
037    import com.liferay.portal.webdav.InvalidRequestException;
038    import com.liferay.portal.webdav.LockException;
039    import com.liferay.util.xml.XMLFormatter;
040    
041    import java.util.HashSet;
042    import java.util.Iterator;
043    import java.util.List;
044    import java.util.Set;
045    
046    import javax.servlet.http.HttpServletRequest;
047    import javax.servlet.http.HttpServletResponse;
048    
049    /**
050     * @author Alexander Chow
051     */
052    public class ProppatchMethodImpl extends BasePropMethodImpl {
053    
054            @Override
055            public int process(WebDAVRequest webDavRequest) throws WebDAVException {
056                    try {
057                            Set<QName> props = processInstructions(webDavRequest);
058    
059                            return writeResponseXML(webDavRequest, props);
060                    }
061                    catch (InvalidRequestException ire) {
062                            if (_log.isInfoEnabled()) {
063                                    _log.info(ire.getMessage(), ire);
064                            }
065    
066                            return HttpServletResponse.SC_BAD_REQUEST;
067                    }
068                    catch (LockException le) {
069                            return WebDAVUtil.SC_LOCKED;
070                    }
071                    catch (Exception e) {
072                            throw new WebDAVException(e);
073                    }
074            }
075    
076            protected WebDAVProps getStoredProperties(WebDAVRequest webDavRequest)
077                    throws PortalException, SystemException {
078    
079                    WebDAVStorage storage = webDavRequest.getWebDAVStorage();
080    
081                    Resource resource = storage.getResource(webDavRequest);
082    
083                    WebDAVProps webDavProps = null;
084    
085                    if (resource.getPrimaryKey() <= 0) {
086                            if (_log.isWarnEnabled()) {
087                                    _log.warn("There is no primary key set for resource");
088                            }
089    
090                            throw new InvalidRequestException();
091                    }
092                    else if (resource.isLocked()) {
093                            Lock lock = resource.getLock();
094    
095                            if ((lock == null) ||
096                                    !lock.getUuid().equals(webDavRequest.getLockUuid())) {
097    
098                                    throw new LockException();
099                            }
100                    }
101    
102                    webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
103                            webDavRequest.getCompanyId(), resource.getClassName(),
104                            resource.getPrimaryKey());
105    
106                    return webDavProps;
107            }
108    
109            protected Set<QName> processInstructions(WebDAVRequest webDavRequest)
110                    throws InvalidRequestException, LockException {
111    
112                    try {
113                            Set<QName> newProps = new HashSet<QName>();
114    
115                            HttpServletRequest request = webDavRequest.getHttpServletRequest();
116    
117                            WebDAVProps webDavProps = getStoredProperties(webDavRequest);
118    
119                            String xml = new String(
120                                    FileUtil.getBytes(request.getInputStream()));
121    
122                            if (Validator.isNull(xml)) {
123                                    return newProps;
124                            }
125    
126                            if (_log.isInfoEnabled()) {
127                                    _log.info(
128                                            "Request XML: \n" +
129                                                    XMLFormatter.toString(xml, StringPool.FOUR_SPACES));
130                            }
131    
132                            Document document = SAXReaderUtil.read(xml);
133    
134                            Element rootElement = document.getRootElement();
135    
136                            Iterator<Element> itr = rootElement.elements().iterator();
137    
138                            while (itr.hasNext()) {
139                                    Element instructionElement = itr.next();
140    
141                                    List<Element> propElements = instructionElement.elements();
142    
143                                    if (propElements.size() != 1) {
144                                            throw new InvalidRequestException(
145                                                    "There should only be one <prop /> per set or remove " +
146                                                            "instruction.");
147                                    }
148    
149                                    Element propElement = propElements.get(0);
150    
151                                    if (!propElement.getName().equals("prop") ||
152                                            !propElement.getNamespaceURI().equals(
153                                                    WebDAVUtil.DAV_URI.getURI())) {
154    
155                                            throw new InvalidRequestException(
156                                                    "Invalid <prop /> element " + propElement);
157                                    }
158    
159                                    List<Element> customPropElements = propElement.elements();
160    
161                                    for (Element customPropElement : customPropElements) {
162                                            String name = customPropElement.getName();
163                                            String prefix = customPropElement.getNamespacePrefix();
164                                            String uri = customPropElement.getNamespaceURI();
165                                            String text = customPropElement.getText();
166    
167                                            Namespace namespace = WebDAVUtil.createNamespace(
168                                                    prefix, uri);
169    
170                                            if (instructionElement.getName().equals("set")) {
171                                                    if (Validator.isNull(text)) {
172                                                            webDavProps.addProp(name, prefix, uri);
173                                                    }
174                                                    else {
175                                                            webDavProps.addProp(name, prefix, uri, text);
176                                                    }
177    
178                                                    newProps.add(
179                                                            SAXReaderUtil.createQName(
180                                                                    customPropElement.getName(), namespace));
181                                            }
182                                            else if (instructionElement.getName().equals("remove")) {
183                                                    webDavProps.removeProp(name, prefix, uri);
184                                            }
185                                            else {
186                                                    throw new InvalidRequestException(
187                                                            "Instead of set/remove instruction, received " +
188                                                                    instructionElement);
189                                            }
190                                    }
191                            }
192    
193                            WebDAVPropsLocalServiceUtil.storeWebDAVProps(webDavProps);
194    
195                            return newProps;
196                    }
197                    catch (LockException le) {
198                            throw le;
199                    }
200                    catch (Exception e) {
201                            throw new InvalidRequestException(e);
202                    }
203            }
204    
205            private static Log _log = LogFactoryUtil.getLog(ProppatchMethodImpl.class);
206    
207    }