1 //
2 // ========================================================================
3 // Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.websocket.server.pathmap;
20
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 public class RegexPathSpec extends PathSpec
25 {
26 protected Pattern pattern;
27
28 protected RegexPathSpec()
29 {
30 super();
31 }
32
33 public RegexPathSpec(String regex)
34 {
35 super.pathSpec = regex;
36 boolean inGrouping = false;
37 this.pathDepth = 0;
38 this.specLength = pathSpec.length();
39 // build up a simple signature we can use to identify the grouping
40 StringBuilder signature = new StringBuilder();
41 for (char c : pathSpec.toCharArray())
42 {
43 switch (c)
44 {
45 case '[':
46 inGrouping = true;
47 break;
48 case ']':
49 inGrouping = false;
50 signature.append('g'); // glob
51 break;
52 case '*':
53 signature.append('g'); // glob
54 break;
55 case '/':
56 if (!inGrouping)
57 {
58 this.pathDepth++;
59 }
60 break;
61 default:
62 if (!inGrouping)
63 {
64 if (Character.isLetterOrDigit(c))
65 {
66 signature.append('l'); // literal (exact)
67 }
68 }
69 break;
70 }
71 }
72 this.pattern = Pattern.compile(pathSpec);
73
74 // Figure out the grouping based on the signature
75 String sig = signature.toString();
76
77 if (Pattern.matches("^l*$",sig))
78 {
79 this.group = PathSpecGroup.EXACT;
80 }
81 else if (Pattern.matches("^l*g+",sig))
82 {
83 this.group = PathSpecGroup.PREFIX_GLOB;
84 }
85 else if (Pattern.matches("^g+l+$",sig))
86 {
87 this.group = PathSpecGroup.SUFFIX_GLOB;
88 }
89 else
90 {
91 this.group = PathSpecGroup.MIDDLE_GLOB;
92 }
93 }
94
95 public Matcher getMatcher(String path)
96 {
97 return this.pattern.matcher(path);
98 }
99
100 @Override
101 public String getPathInfo(String path)
102 {
103 // Path Info only valid for PREFIX_GLOB types
104 if (group == PathSpecGroup.PREFIX_GLOB)
105 {
106 Matcher matcher = getMatcher(path);
107 if (matcher.matches())
108 {
109 if (matcher.groupCount() >= 1)
110 {
111 String pathInfo = matcher.group(1);
112 if ("".equals(pathInfo))
113 {
114 return "/";
115 }
116 else
117 {
118 return pathInfo;
119 }
120 }
121 }
122 }
123 return null;
124 }
125
126 @Override
127 public String getPathMatch(String path)
128 {
129 Matcher matcher = getMatcher(path);
130 if (matcher.matches())
131 {
132 if (matcher.groupCount() >= 1)
133 {
134 int idx = matcher.start(1);
135 if (idx > 0)
136 {
137 if (path.charAt(idx - 1) == '/')
138 {
139 idx--;
140 }
141 return path.substring(0,idx);
142 }
143 }
144 return path;
145 }
146 return null;
147 }
148
149 public Pattern getPattern()
150 {
151 return this.pattern;
152 }
153
154 @Override
155 public String getRelativePath(String base, String path)
156 {
157 // TODO Auto-generated method stub
158 return null;
159 }
160
161 @Override
162 public boolean matches(final String path)
163 {
164 int idx = path.indexOf('?');
165 if (idx >= 0)
166 {
167 // match only non-query part
168 return getMatcher(path.substring(0,idx)).matches();
169 }
170 else
171 {
172 // match entire path
173 return getMatcher(path).matches();
174 }
175 }
176 }