View Javadoc

1   /*
2    * Copyright (c) 2006-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.danube.webdav.util;
14  
15  import org.abstracthorizon.danube.http.HTTPConnection;
16  import org.abstracthorizon.danube.webdav.ResourceAdapter;
17  import org.abstracthorizon.danube.webdav.lock.LockingMechanism;
18  
19  import java.util.HashSet;
20  import java.util.Set;
21  
22  /**
23   * This object represents "If" header of WebDAV specification.
24   *
25   * @author Daniel Sendula
26   */
27  public class IF {
28  
29      /** Collected token of a main resource. May be <code>null</code> */
30      public String token;
31  
32      /** Collected token of a parent resource. May be <code>null</code> */
33      public String parentToken;
34  
35      /** Collection of resource that was cleared. May be <code>null</code> */
36      public Set<Object> clearedResources;
37  
38      /** <code>true<code> if header parsing wasn't successful */
39      public boolean error;
40  
41      /**
42       * Parses &quot;if&quot; header and checks if values correspond
43       * to given resource.
44       *
45       * It returns lock token of supplied main resource. If it failed
46       * <code>null</code> will be returned.
47       *
48       * @param httpConnection http connection
49       * @param adapter resource adapter
50       * @param mainResource main resource
51       * @param parentResource parent resource. May be null.
52       * @param header if header
53       * @return lock token of supplied main resource or <code>null</code>
54       */
55      public boolean parse(HTTPConnection httpConnection, ResourceAdapter adapter, Object mainResource, Object parentResource) {
56          String[] ifs = httpConnection.getRequestHeaders().getAsArray("If");
57          if ((ifs == null) || (ifs.length == 0)) {
58              return true;
59  //            if (adapter.getLockingMechanism().isLocked(mainResource)) {
60  //                error = true;
61  //                return false;
62  //            } else {
63  //                return true;
64  //            }
65          }
66          int len = 0;
67          for (String s : ifs) {
68              len = len + s.length() + 1;
69          }
70          char[] header = new char[len];
71          len = 0;
72          for (String s : ifs) {
73              s.getChars(0, s.length(), header, len);
74              len = len + s.length();
75              header[len] = ' ';
76              len = len + 1;
77          }
78          return parse(httpConnection, adapter, mainResource, parentResource, header);
79      }
80  
81      /**
82       * Parses &quot;if&quot; header and checks if values correspond
83       * to given resource.
84       *
85       * It returns lock token of supplied main resource. If it failed
86       * <code>null</code> will be returned.
87       *
88       * @param httpConnection http connection
89       * @param adapter resource adapter
90       * @param mainResource main resource
91       * @param parentResource parent resource. May be null.
92       * @param header if header
93       * @return lock token of supplied main resource or <code>null</code>
94       */
95      public boolean parse(HTTPConnection httpConnection, ResourceAdapter adapter, Object mainResource, Object parentResource, char[] buf) {
96          boolean orResult = false;
97          boolean andResult = true;
98          boolean parentCleared = (parentResource == null);
99  
100         char[] temp = new char[buf.length];
101         int tp = 0;
102         int p = 0;
103         int state = 0;
104         Object currentResource = null;
105         boolean not = false;
106 
107         while (p < buf.length) {
108             char c = buf[p];
109             if (state == 0) {
110                 if (c == ' ') {
111                     // ignore spaces
112                 } else if (c == '<') {
113                     if ((currentResource != null) && !orResult) {
114                         // it is not first resource and result is still false.
115                         error = true;
116                         return false;
117                     }
118                     tp = 0;
119                     state = 1;
120                 } else if (c == '(') {
121                     andResult = true;
122                     if (currentResource == null) {
123                         currentResource = mainResource;
124                     }
125                     not = false;
126                     state = 4;
127                 } else {
128                     p = buf.length;
129                 }
130             } else if (state == 1) {
131                 if (c == '>') {
132                     if (tp == 0) {
133                         error = true;
134                         return false;
135                     }
136                     String uriString = new String(temp, 0, tp);
137                     tp = 0;
138                     currentResource = URIUtils.uriToResource(httpConnection, adapter, uriString);
139                     if (currentResource == null) {
140                         error = true;
141                         return false;
142                     }
143                     state = 3;
144                 } else {
145                     temp[tp] = c;
146                     tp++;
147                 }
148             } else if (state == 3) {
149                 if (c == ' ') {
150                 } else if (c == '(') {
151                     andResult = true;
152                     not = false;
153                     state = 4;
154                 } else {
155                     error = true;
156                     return false;
157                 }
158             } else if (state == 4) {
159                 if (c == ' ') {
160                     // ignore
161                 } else if (c == 'N') {
162                     state = 5;
163                 } else if (c == '<') {
164                     not = false;
165                     state = 8;
166                     tp = 0;
167                 } else if (c == '[') {
168                     not = false;
169                     tp = 0;
170                     state = 9;
171                 } else if (c == ')') {
172                     orResult = orResult || andResult;
173                     state = 0;
174                 } else {
175                     error = true;
176                     return false;
177                 }
178             } else if (state == 5) {
179                 if (c == 'o') {
180                     state = 6;
181                 } else {
182                     return false;
183                 }
184             } else if (state == 6) {
185                 if (c == 't') {
186                     not = true;
187                     state = 7;
188                 } else {
189                     return false;
190                 }
191             } else if (state == 7) {
192                 if (c == ' ') {
193                     // ignore
194                 } else if (c == '<') {
195                     tp = 0;
196                     state = 8;
197                 } else if (c == '[') {
198                     tp = 0;
199                     state = 9;
200                 }
201             } else if (state == 8) {
202                 if (c == '>') {
203                     if (tp == 0) {
204                         return false;
205                     }
206                     String tokenString = new String(temp, 0, tp);
207                     tp = 0;
208 
209                     LockingMechanism lockingMechanism = adapter.getLockingMechanism();
210                     if (lockingMechanism.isAccessAllowed(currentResource, tokenString)) {
211                         if (not) {
212                             andResult = false;
213                         } else {
214                             if (currentResource == mainResource) {
215                                 token = tokenString;
216                             } else if (currentResource == parentResource) {
217                                 parentCleared = true;
218                                 parentToken = tokenString;
219                             } else if (currentResource.equals(mainResource)) {
220                                 token = tokenString;
221                             } else if ((parentResource != null) && parentResource.equals(currentResource)) {
222                                 parentCleared = true;
223                                 parentToken = tokenString;
224                             } else {
225                                 if (clearedResources == null) {
226                                     clearedResources = new HashSet<Object>();
227                                 }
228                                 clearedResources.add(currentResource);
229                             }
230                         }
231                     } else {
232                         if (!not) {
233                             andResult = false;
234                         }
235                     }
236 
237                     not = false;
238                     state = 4;
239                 } else {
240                     temp[tp] = c;
241                     tp++;
242                 }
243             } else if (state == 9) {
244                 if (c == ']') {
245                     if (tp == 0) {
246                         error = true;
247                         return false;
248                     }
249                     String etagToken = new String(temp, 0, tp);
250                     tp = 0;
251 
252                     String etag = adapter.getResourceETag(currentResource);
253                     if ((etag != null) && etag.equals(etagToken)) {
254                         if (not) {
255                             andResult = false;
256                         }
257                     } else {
258                         if (!not) {
259                             andResult = false;
260                         }
261                     }
262 
263                     not = false;
264                     state = 4;
265                 } else {
266                     temp[tp] = c;
267                     tp++;
268                 }
269             }
270 
271             p = p + 1;
272         }
273 
274         return ((state == 0) && orResult && parentCleared);
275     }
276 }