001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.dav.methods;
021:
022: import java.io.FileNotFoundException;
023: import java.io.IOException;
024: import java.util.Collection;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import javax.servlet.ServletException;
029: import javax.servlet.http.HttpServletRequest;
030: import javax.servlet.http.HttpServletResponse;
031:
032: import org.apache.log4j.Logger;
033: import org.jdom.Document;
034: import org.jdom.Element;
035: import org.jdom.JDOMException;
036: import org.jdom.Namespace;
037: import org.jdom.input.SAXBuilder;
038: import org.jdom.output.Format;
039: import org.jdom.output.XMLOutputter;
040: import org.jdom.xpath.XPath;
041:
042: import com.ecyrd.jspwiki.dav.DavContext;
043: import com.ecyrd.jspwiki.dav.DavPath;
044: import com.ecyrd.jspwiki.dav.DavProvider;
045: import com.ecyrd.jspwiki.dav.WebdavServlet;
046: import com.ecyrd.jspwiki.dav.items.DavItem;
047: import com.ecyrd.jspwiki.providers.ProviderException;
048:
049: /**
050: * @author jalkanen
051: *
052: * @since
053: */
054: public class PropFindMethod extends DavMethod {
055: private static Logger log = Logger.getLogger(PropFindMethod.class);
056:
057: /**
058: *
059: */
060: public PropFindMethod(DavProvider provider) {
061: super (provider);
062: }
063:
064: public void sendMultiResponse(HttpServletResponse res,
065: Element response) throws IOException {
066: res.setContentType("application/xml; charset=\"UTF-8\"");
067: res.setStatus(WebdavServlet.SC_MULTISTATUS);
068:
069: Document doc = new Document();
070:
071: doc.setRootElement(response);
072:
073: XMLOutputter output = new XMLOutputter();
074:
075: // System.out.println("Returning");
076: output.setFormat(Format.getPrettyFormat());
077: // output.output( doc, System.out );
078: output.output(doc, res.getWriter());
079: }
080:
081: private Element getPropertyNames(DavContext dc) {
082: log.debug("Retrieving all property names for context " + dc);
083:
084: Namespace davns = Namespace.getNamespace("DAV:");
085: Element root = new Element("multistatus", davns);
086:
087: DavItem di = m_provider.getItem(dc.getPath());
088:
089: for (Iterator i = di.iterator(dc.getDepth()); i.hasNext();) {
090: di = (DavItem) i.next();
091:
092: Element response = new Element("response", davns);
093:
094: response.addContent(new Element("href", davns).setText(di
095: .getHref()));
096:
097: Element propstat = new Element("propstat", davns);
098:
099: //
100: // Wiki specifics.
101: //
102: Collection c = di.getPropertySet();
103:
104: Element prop = new Element("prop", davns);
105:
106: for (Iterator j = c.iterator(); j.hasNext();) {
107: Element el = (Element) j.next();
108: el.removeContent();
109: prop.addContent(el);
110: }
111:
112: propstat.addContent(prop);
113: propstat.addContent(new Element("status", davns)
114: .setText("HTTP/1.1 200 OK"));
115:
116: response.addContent(propstat);
117:
118: root.addContent(response);
119: }
120:
121: return root;
122: }
123:
124: private Element getProperties(DavContext dc, List askedprops)
125: throws IOException {
126: Namespace davns = Namespace.getNamespace("DAV:");
127:
128: Element root = new Element("multistatus", davns);
129:
130: DavItem di = m_provider.getItem(dc.getPath());
131:
132: if (di == null) {
133: throw new FileNotFoundException(dc.getPath().toString());
134: }
135:
136: for (Iterator i = di.iterator(dc.getDepth()); i.hasNext();) {
137: di = (DavItem) i.next();
138:
139: Element response = new Element("response", davns);
140:
141: response.addContent(new Element("href", davns).setText(di
142: .getHref()));
143:
144: Element props = new Element("prop", davns);
145: Element failedprops = new Element("prop", davns);
146:
147: //
148: // Get the matching property set
149: //
150: Collection c = di.getPropertySet();
151:
152: if (askedprops == null) {
153: for (Iterator j = c.iterator(); j.hasNext();) {
154: Element el = (Element) j.next();
155:
156: props.addContent(el);
157: }
158: } else {
159: for (Iterator x = askedprops.iterator(); x.hasNext();) {
160: Element askedElement = (Element) x.next();
161:
162: boolean found = false;
163:
164: for (Iterator j = c.iterator(); j.hasNext();) {
165: Element el = (Element) j.next();
166:
167: if (askedElement.getNamespaceURI().equals(
168: el.getNamespaceURI())
169: && askedElement.getName().equals(
170: el.getName())) {
171: //
172: // This protects in case there are multiple elements
173: // in the request.
174: //
175: if (props.indexOf(el) == -1) {
176: props.addContent(el);
177: }
178: found = true;
179: break;
180: }
181: }
182:
183: if (!found) {
184: Element el = (Element) askedElement.clone();
185: failedprops.addContent(el);
186: }
187: }
188:
189: }
190:
191: if (props.getContentSize() > 0) {
192: Element ps = new Element("propstat", davns);
193: ps.addContent(props);
194: ps.addContent(new Element("status", davns)
195: .setText("HTTP/1.1 200 OK"));
196: response.addContent(ps);
197: }
198:
199: if (failedprops.getContentSize() > 0) {
200: Element ps = new Element("propstat", davns);
201: ps.addContent(failedprops);
202: ps.addContent(new Element("status", davns)
203: .setText("HTTP/1.1 404 Not found"));
204: response.addContent(ps);
205: }
206:
207: root.addContent(response);
208: }
209:
210: return root;
211: }
212:
213: private Element getAllProps(DavContext dc)
214: throws ProviderException, IOException {
215: log.debug("Retrieving all properties for context "
216: + dc.getPath());
217:
218: return getProperties(dc, null);
219: }
220:
221: public void execute(HttpServletRequest req,
222: HttpServletResponse res, DavPath dp)
223: throws ServletException, IOException {
224: DavContext dc = new DavContext(req, dp);
225:
226: try {
227: Document doc = new SAXBuilder().build(req.getInputStream());
228:
229: XPath xpath = XPath.newInstance("/D:propfind/*");
230: xpath.addNamespace("D", "DAV:");
231:
232: Element firstnode = (Element) xpath.selectSingleNode(doc);
233:
234: Element davresponse = null;
235:
236: System.out.println("Request=" + dc.getPath() + " depth="
237: + dc.getDepth());
238:
239: if (firstnode == null
240: || firstnode.getName().equals("allprop")) {
241: davresponse = getAllProps(dc);
242: } else if (firstnode.getName().equals("propname")) {
243: davresponse = getPropertyNames(dc);
244: } else if (firstnode.getName().equals("prop")) {
245: XPath ndxp = XPath.newInstance("/D:propfind/D:prop/*");
246: ndxp.addNamespace("D", "DAV:");
247:
248: List nodes = ndxp.selectNodes(doc);
249:
250: davresponse = getProperties(dc, nodes);
251: }
252:
253: sendMultiResponse(res, davresponse);
254: } catch (JDOMException e) {
255: // This is probably someone trying to poke at us
256: log.info("Broken XML received", e);
257:
258: res.sendError(HttpServletResponse.SC_BAD_REQUEST,
259: "Parse error");
260: } catch (ProviderException e) {
261: log.error("Provider failed", e);
262:
263: res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
264: e.getMessage());
265: } catch (FileNotFoundException e) {
266: res.sendError(HttpServletResponse.SC_NOT_FOUND, e
267: .getMessage());
268: }
269: }
270:
271: }
|