1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.springframework.extensions.webscripts;
20
21 import java.util.Comparator;
22 import java.util.Map;
23 import java.util.TreeMap;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28
29
30
31
32
33
34 public class JaxRSUriIndex implements UriIndex
35 {
36
37 private static final Log logger = LogFactory.getLog(JaxRSUriIndex.class);
38
39
40 private Map<IndexEntry, IndexEntry> index = new TreeMap<IndexEntry, IndexEntry>(COMPARATOR);
41
42
43
44
45
46 public void clear()
47 {
48 index.clear();
49 }
50
51
52
53
54 public int getSize()
55 {
56 return index.size();
57 }
58
59
60
61
62 public Match findWebScript(String method, String uri)
63 {
64 IndexEntry pathMatch = null;
65 Map<String, String> varsMatch = null;
66 Match scriptMatch = null;
67 String match = uri;
68 String matchNoExt = uri;
69 int extIdx = uri.indexOf('.');
70 if (extIdx != -1)
71 {
72
73 if (uri.lastIndexOf('/') < extIdx)
74 {
75 matchNoExt = uri.substring(0, extIdx);
76 }
77 }
78 method = method.toUpperCase();
79
80
81 for (IndexEntry entry : index.keySet())
82 {
83 String test = entry.getIncludeExtension() ? match : matchNoExt;
84 Map<String, String> vars = entry.getTemplate().match(test);
85 if (vars != null)
86 {
87 pathMatch = entry;
88 varsMatch = vars;
89 if (entry.getMethod().equals(method))
90 {
91 scriptMatch = new Match(entry.getTemplate().getTemplate(), vars, entry.getStaticTemplate(), entry.getScript());
92 break;
93 }
94 }
95 }
96
97
98 if (scriptMatch == null && pathMatch != null)
99 {
100 scriptMatch = new Match(pathMatch.getTemplate().getTemplate(), varsMatch, pathMatch.getStaticTemplate());
101 }
102
103 return scriptMatch;
104 }
105
106
107
108
109 public void registerUri(WebScript script, String uri)
110 {
111 Description desc = script.getDescription();
112 boolean extension = true;
113
114
115 int queryArgIdx = uri.indexOf('?');
116 if (queryArgIdx != -1)
117 {
118 uri = uri.substring(0, queryArgIdx);
119 }
120
121
122 if (desc.getFormatStyle() != Description.FormatStyle.argument)
123 {
124 int extIdx = uri.lastIndexOf(".");
125 if (extIdx != -1)
126 {
127 uri = uri.substring(0, extIdx);
128 }
129 extension = false;
130 }
131
132
133 IndexEntry entry = new IndexEntry(desc.getMethod(), new UriTemplate(uri), extension, script);
134 if (index.containsKey(entry))
135 {
136 IndexEntry existingEntry = index.get(entry);
137 WebScript existingService = existingEntry.getScript();
138 if (!existingService.getDescription().getId().equals(desc.getId()))
139 {
140 String msg = "Web Script document " + desc.getDescPath() + " is attempting to define the url '" + entry + "' already defined by " + existingService.getDescription().getDescPath();
141 throw new WebScriptException(msg);
142 }
143 }
144 else
145 {
146 index.put(entry, entry);
147 if (logger.isTraceEnabled())
148 logger.trace("Indexed URI '" + uri + "' as '" + entry.getTemplate() + "'");
149 }
150 }
151
152
153
154
155 static final Comparator<IndexEntry> COMPARATOR = new Comparator<IndexEntry>()
156 {
157 public int compare(IndexEntry o1, IndexEntry o2)
158 {
159 if (o1 == null && o2 == null)
160 {
161 return 0;
162 }
163 if (o1 == null)
164 {
165 return 1;
166 }
167 if (o2 == null)
168 {
169 return -1;
170 }
171
172
173 int i = o2.getTemplate().getStaticCharCount() - o1.getTemplate().getStaticCharCount();
174 if (i != 0)
175 {
176 return i;
177 }
178
179
180 i = o2.getTemplate().getVariableNames().length - o1.getTemplate().getVariableNames().length;
181 if (i != 0)
182 {
183 return i;
184 }
185
186
187 i = o2.getTemplate().getRegex().pattern().compareTo(o1.getTemplate().getRegex().pattern());
188 if (i != 0)
189 {
190 return i;
191 }
192
193
194 return o2.method.compareTo(o1.method);
195 }
196 };
197
198
199
200
201
202
203 static class IndexEntry
204 {
205 private String method;
206 private UriTemplate template;
207 private WebScript script;
208 private boolean includeExtension;
209 private String staticTemplate;
210 private final String key;
211
212
213
214
215
216
217
218
219
220 IndexEntry(String method, UriTemplate template, boolean includeExtension, WebScript script)
221 {
222 this.method = method.toUpperCase();
223 this.template = template;
224 this.includeExtension = includeExtension;
225 this.script = script;
226 this.key = template.getRegex() + ":" + this.method;
227 int firstTokenIdx = template.getTemplate().indexOf('{');
228 this.staticTemplate = (firstTokenIdx == -1) ? template.getTemplate() : template.getTemplate().substring(0, firstTokenIdx);
229 }
230
231
232
233
234 public String getMethod()
235 {
236 return method;
237 }
238
239
240
241
242 public UriTemplate getTemplate()
243 {
244 return template;
245 }
246
247
248
249
250 public String getStaticTemplate()
251 {
252 return staticTemplate;
253 }
254
255
256
257
258 public boolean getIncludeExtension()
259 {
260 return includeExtension;
261 }
262
263
264
265
266 public WebScript getScript()
267 {
268 return script;
269 }
270
271 @Override
272 public final String toString()
273 {
274 return key;
275 }
276
277 @Override
278 public boolean equals(Object obj)
279 {
280 if (!(obj instanceof IndexEntry))
281 {
282 return false;
283 }
284 return key.equals(((IndexEntry)obj).key);
285 }
286
287 @Override
288 public int hashCode()
289 {
290 return key.hashCode();
291 }
292 }
293 }