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