1919import java .util .Collections ;
2020
2121import org .springframework .http .server .PathContainer ;
22+ import org .springframework .lang .Nullable ;
2223import org .springframework .messaging .Message ;
2324import org .springframework .messaging .simp .SimpMessageHeaderAccessor ;
2425import org .springframework .messaging .simp .SimpMessageType ;
26+ import org .springframework .security .messaging .access .intercept .MessageAuthorizationContext ;
2527import org .springframework .util .Assert ;
2628import org .springframework .web .util .pattern .PathPattern ;
2729import org .springframework .web .util .pattern .PathPatternParser ;
@@ -40,16 +42,16 @@ public final class PathPatternMessageMatcher implements MessageMatcher<Object> {
4042
4143 private final PathPattern pattern ;
4244
43- private final PathPatternParser parser ;
45+ private final PathContainer . Options options ;
4446
4547 /**
4648 * The {@link MessageMatcher} that determines if the type matches. If the type was
4749 * null, this matcher will match every Message.
4850 */
4951 private MessageMatcher <Object > messageTypeMatcher = ANY_MESSAGE ;
5052
51- private PathPatternMessageMatcher (PathPattern pattern , PathPatternParser parser ) {
52- this .parser = parser ;
53+ private PathPatternMessageMatcher (PathPattern pattern , PathContainer . Options options ) {
54+ this .options = options ;
5355 this .pattern = pattern ;
5456 }
5557
@@ -78,17 +80,7 @@ void setMessageTypeMatcher(MessageMatcher<Object> messageTypeMatcher) {
7880 */
7981 @ Override
8082 public boolean matches (Message <?> message ) {
81- if (!this .messageTypeMatcher .matches (message )) {
82- return false ;
83- }
84-
85- String destination = getDestination (message );
86- if (destination == null ) {
87- return false ;
88- }
89-
90- PathContainer destinationPathContainer = PathContainer .parsePath (destination , this .parser .getPathOptions ());
91- return this .pattern .matches (destinationPathContainer );
83+ return matcher (message ).isMatch ();
9284 }
9385
9486 /**
@@ -109,7 +101,7 @@ public MatchResult matcher(Message<?> message) {
109101 return MatchResult .notMatch ();
110102 }
111103
112- PathContainer destinationPathContainer = PathContainer .parsePath (destination , this .parser . getPathOptions () );
104+ PathContainer destinationPathContainer = PathContainer .parsePath (destination , this .options );
113105 PathPattern .PathMatchInfo pathMatchInfo = this .pattern .matchAndExtract (destinationPathContainer );
114106
115107 return (pathMatchInfo != null ) ? MatchResult .match (pathMatchInfo .getUriVariables ()) : MatchResult .notMatch ();
@@ -119,33 +111,92 @@ private static String getDestination(Message<?> message) {
119111 return SimpMessageHeaderAccessor .getDestination (message .getHeaders ());
120112 }
121113
114+ /**
115+ * A builder for specifying various elements of a message for the purpose of creating
116+ * a {@link PathPatternMessageMatcher}.
117+ */
122118 public static class Builder {
123119
124120 private final PathPatternParser parser ;
125121
126- private MessageMatcher <Object > messageTypeMatcher = ANY_MESSAGE ;
127-
128122 Builder (PathPatternParser parser ) {
129123 this .parser = parser ;
130124 }
131125
126+ /**
127+ * Match messages having this destination pattern.
128+ *
129+ * <p>
130+ * Path patterns always start with a slash and may contain placeholders. They can
131+ * also be followed by {@code /**} to signify all URIs under a given path.
132+ *
133+ * <p>
134+ * The following are valid patterns and their meaning
135+ * <ul>
136+ * <li>{@code /path} - match exactly and only `/path`</li>
137+ * <li>{@code /path/**} - match `/path` and any of its descendents</li>
138+ * <li>{@code /path/{value}/**} - match `/path/subdirectory` and any of its
139+ * descendents, capturing the value of the subdirectory in
140+ * {@link MessageAuthorizationContext#getVariables()}</li>
141+ * </ul>
142+ *
143+ * <p>
144+ * A more comprehensive list can be found at {@link PathPattern}.
145+ *
146+ * <p>
147+ * A dot-based message pattern is also supported when configuring a
148+ * {@link PathPatternParser} using
149+ * {@link PathPatternMessageMatcher#withPathPatternParser}
150+ * @param pattern the destination pattern to match
151+ * @return the {@link PathPatternMessageMatcher.Builder} for more configuration
152+ */
132153 public PathPatternMessageMatcher matcher (String pattern ) {
133- Assert .notNull (pattern , "Pattern must not be null" );
154+ return matcher (null , pattern );
155+ }
156+
157+ /**
158+ * Match messages having this type and destination pattern.
159+ *
160+ * <p>
161+ * When the message {@code type} is null, then the matcher does not consider the
162+ * message type
163+ *
164+ * <p>
165+ * Path patterns always start with a slash and may contain placeholders. They can
166+ * also be followed by {@code /**} to signify all URIs under a given path.
167+ *
168+ * <p>
169+ * The following are valid patterns and their meaning
170+ * <ul>
171+ * <li>{@code /path} - match exactly and only `/path`</li>
172+ * <li>{@code /path/**} - match `/path` and any of its descendents</li>
173+ * <li>{@code /path/{value}/**} - match `/path/subdirectory` and any of its
174+ * descendents, capturing the value of the subdirectory in
175+ * {@link MessageAuthorizationContext#getVariables()}</li>
176+ * </ul>
177+ *
178+ * <p>
179+ * A more comprehensive list can be found at {@link PathPattern}.
180+ *
181+ * <p>
182+ * A dot-based message pattern is also supported when configuring a
183+ * {@link PathPatternParser} using
184+ * {@link PathPatternMessageMatcher#withPathPatternParser}
185+ * @param type the message type to match
186+ * @param pattern the destination pattern to match
187+ * @return the {@link PathPatternMessageMatcher.Builder} for more configuration
188+ */
189+ public PathPatternMessageMatcher matcher (@ Nullable SimpMessageType type , String pattern ) {
190+ Assert .notNull (pattern , "pattern must not be null" );
134191 PathPattern pathPattern = this .parser .parse (pattern );
135- PathPatternMessageMatcher matcher = new PathPatternMessageMatcher (pathPattern , this .parser );
136- if (this .messageTypeMatcher != ANY_MESSAGE ) {
137- matcher .setMessageTypeMatcher (this .messageTypeMatcher );
192+ PathPatternMessageMatcher matcher = new PathPatternMessageMatcher (pathPattern ,
193+ this .parser .getPathOptions ());
194+ if (type != null ) {
195+ matcher .setMessageTypeMatcher (new SimpMessageTypeMatcher (type ));
138196 }
139197 return matcher ;
140198 }
141199
142- public PathPatternMessageMatcher matcher (String pattern , SimpMessageType type ) {
143- Assert .notNull (type , "Type must not be null" );
144- this .messageTypeMatcher = new SimpMessageTypeMatcher (type );
145-
146- return matcher (pattern );
147- }
148-
149200 }
150201
151202}
0 commit comments