1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package nl.hippo.client.webdav.caching;
17
18 import java.io.IOException;
19 import java.io.StringReader;
20 import java.util.ArrayList;
21 import java.util.Iterator;
22 import java.util.List;
23
24 import nl.hippo.client.api.ClientException;
25 import nl.hippo.client.api.content.Property;
26 import nl.hippo.client.api.event.EventValidity;
27 import nl.hippo.client.api.event.EventValidityImpl;
28 import nl.hippo.client.webdav.WebdavRequest;
29
30 import org.apache.commons.lang.StringUtils;
31 import org.xmlpull.v1.XmlPullParser;
32 import org.xmlpull.v1.XmlPullParserException;
33 import org.xmlpull.v1.XmlPullParserFactory;
34
35 class EventValidityCalculator {
36
37 private static final String SCOPE_ELEMENT_NAME = "scope";
38 private static final String HREF_ELEMENT_NAME = "href";
39
40 private static EventValidityCalculator calculator;
41
42 private static XmlPullParserFactory factory;
43 static {
44 try {
45 factory = XmlPullParserFactory.newInstance();
46 factory.setNamespaceAware(true);
47 } catch (XmlPullParserException e) {
48 throw new ExceptionInInitializerError("Error while creating xpp pull parser" + e.getMessage());
49 }
50 }
51
52 static EventValidity[] calculate(WebdavRequest request) throws ClientException {
53 if (request == null) {
54 throw new IllegalArgumentException("request may not be null");
55 }
56 if (request.getPath() == null) {
57 return new EventValidity[0];
58 }
59 if (request.getRequestBody() == null) {
60 return new EventValidityImpl[] { new EventValidityImpl(request.getPath().getFullPath()) };
61 }
62 try {
63
64 return new EventValidityCalculator(factory.newPullParser()).execute(request);
65 } catch (XmlPullParserException e) {
66
67 return new EventValidity[0];
68 }
69 }
70
71 private XmlPullParser xpp;
72
73 private EventValidityCalculator(XmlPullParser xpp) {
74 this.xpp = xpp;
75 }
76
77 private EventValidity[] execute(WebdavRequest request) throws ClientException {
78 List validities = new ArrayList();
79 try {
80 xpp.setInput(new StringReader(request.getRequestBody()));
81
82 while (nextElement(SCOPE_ELEMENT_NAME, Property.DAV_NAMESPACE)) {
83 if (nextElement(HREF_ELEMENT_NAME, Property.DAV_NAMESPACE)) {
84 xpp.next();
85 String scope = StringUtils.strip(getText());
86 if (scope != null) {
87 scope = StringUtils.stripEnd(scope, "/");
88 if (scope.startsWith("/")) {
89 validities.add(scope);
90 } else {
91 String validityPath = getValidityPath(request, scope);
92 validities.add(validityPath);
93 }
94 }
95 }
96 xpp.nextToken();
97 }
98
99 if (validities.size() == 0) {
100 validities.add(request.getPath().getFullPath());
101 }
102 return toArray(validities);
103
104 } catch (XmlPullParserException e) {
105 throw new ClientException("Error parsing document " + currentPositionString(), e);
106 } catch (IOException e) {
107 throw new ClientException("Error accessing document", e);
108 }
109 }
110
111 private String getValidityPath(WebdavRequest request, String scope) {
112 String result = request.getPath().getFullPath();
113 if (StringUtils.isNotEmpty(scope)) {
114 result += "/" + scope;
115 }
116 return result;
117 }
118
119 private boolean nextElement(String name, String namespace) throws XmlPullParserException, IOException {
120 int type = xpp.getEventType();
121 while (type != XmlPullParser.END_DOCUMENT) {
122 type = xpp.next();
123 if (type == XmlPullParser.START_TAG) {
124 if (verifyName(name) && verifyNamespace(namespace)) {
125 return true;
126 }
127 }
128 }
129 return false;
130 }
131
132 private String getText() throws XmlPullParserException, IOException {
133 int type = xpp.getEventType();
134 while (type != XmlPullParser.TEXT) {
135 if (type == XmlPullParser.START_TAG || type == XmlPullParser.END_DOCUMENT) {
136 return null;
137 }
138 type = xpp.next();
139 }
140 if (type == XmlPullParser.TEXT) {
141 return xpp.getText();
142 } else {
143 return null;
144 }
145 }
146
147 private boolean verifyName(String name) {
148 return xpp.getName().equals(name);
149 }
150
151 private boolean verifyNamespace(String ns) {
152 if (ns == null || "".equals(ns)) {
153 return xpp.getNamespace().length() == 0;
154 } else {
155 return ns.equals(xpp.getNamespace());
156 }
157 }
158
159 private EventValidity[] toArray(List list) throws ClientException {
160 int i = 0;
161 EventValidity[] result = new EventValidity[list.size()];
162 Iterator it = list.iterator();
163 while (it.hasNext()) {
164 result[i++] = new EventValidityImpl((String) it.next());
165 }
166 return result;
167 }
168
169 private String currentPositionString() {
170 StringBuffer buf = new StringBuffer();
171 buf.append("(line ").append(xpp.getLineNumber()).append(", col ").append(xpp.getColumnNumber()).append("): ");
172 if (xpp.getNamespace() == null || "".equals(xpp.getNamespace())) {
173 buf.append("\"").append(xpp.getName()).append("\"");
174 } else {
175 buf.append("\"{").append(xpp.getNamespace()).append("}").append(xpp.getName()).append("\"");
176 }
177 return buf.toString();
178 }
179 }