Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit f79190e

Browse files
committed
[declarative-linking] - Support query parameters
- New Annotation @LinkQueryParam(name="...", value="...) Adds query parameters to Link. - New @InjectLink attributes : boolean copyRequestQueryParams - Specifies that request query params must be include in Link. String[] excludeFromRequestQueryParams - If request query params are copied to inject Link, then exclude query parameters from this list. It's compatible with 2.25.x ...
1 parent 8da4caf commit f79190e

File tree

6 files changed

+242
-5
lines changed

6 files changed

+242
-5
lines changed

Diff for: incubator/declarative-linking/src/main/java/org/glassfish/jersey/linking/ELLinkBuilder.java

+30
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@
4444
import java.util.HashMap;
4545
import java.util.List;
4646
import java.util.Map;
47+
import java.util.Map.Entry;
48+
import java.util.Set;
4749

50+
import javax.ws.rs.core.MultivaluedMap;
4851
import javax.ws.rs.core.UriBuilder;
4952
import javax.ws.rs.core.UriInfo;
5053

@@ -109,6 +112,33 @@ static URI buildURI(InjectLinkDescriptor link,
109112
UriTemplateParser parser = new UriTemplateParser(template);
110113
List<String> parameterNames = parser.getNames();
111114
Map<String, Object> valueMap = getParameterValues(parameterNames, link, context, uriInfo);
115+
116+
// adds query parameters.
117+
MultivaluedMap<String, String> query = link.getQueryParams();
118+
for (Entry<String, List<String>> entry : query.entrySet()) {
119+
//process each value from query parameter and get expression's result.
120+
for (String val: entry.getValue()) {
121+
ValueExpression valExpr =
122+
expressionFactory.createValueExpression(context, val, String.class);
123+
ub.queryParam(entry.getKey(), valExpr.getValue(context).toString());
124+
}
125+
}
126+
127+
/* If user needs injection of request query parameters */
128+
if (link.copyFromRequestParams()) {
129+
Set<String> excludes = link.excludeFromRequestParams();
130+
for (Entry<String, List<String>> reqParam: uriInfo.getQueryParameters().entrySet()) {
131+
if (excludes != null && !excludes.isEmpty()) {
132+
/* Excludes the copy of this parameters */
133+
if (excludes.contains(reqParam.getKey())) {
134+
continue;
135+
}
136+
/* Rebuilds request params for link*/
137+
ub.queryParam(reqParam.getKey(), reqParam.getValue().toArray());
138+
}
139+
}
140+
}
141+
112142
return ub.buildFromMap(valueMap);
113143
}
114144

Diff for: incubator/declarative-linking/src/main/java/org/glassfish/jersey/linking/InjectLink.java

+31
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,37 @@ public enum Style {
211211
String value();
212212
}
213213

214+
/**
215+
* Specifies name-value pairs for Link's query part.
216+
*/
217+
LinkQueryParam[] queryParams() default {};
218+
219+
@Target({ElementType.TYPE, ElementType.FIELD})
220+
@Retention(RetentionPolicy.RUNTIME)
221+
public @interface LinkQueryParam {
222+
223+
/**
224+
* Specifies the name of the link query parameter.
225+
*/
226+
String name();
227+
228+
/**
229+
* Specifies the value of the link query parameter.
230+
*/
231+
String value();
232+
}
233+
234+
/**
235+
* Specifies that request query params must be include in Link.
236+
*/
237+
boolean copyRequestQueryParams() default false;
238+
239+
/**
240+
* If request query params are copied to Link, then exclude query parameters from this list.
241+
*/
242+
String[] excludeFromRequestQueryParams() default {};
243+
244+
214245
public static class Util {
215246

216247
public static Link buildLinkFromUri(URI uri, InjectLink link) {

Diff for: incubator/declarative-linking/src/main/java/org/glassfish/jersey/linking/InjectLinkDescriptor.java

+25
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242

4343
import org.glassfish.jersey.linking.mapping.ResourceMappingContext;
4444

45+
import javax.ws.rs.core.MultivaluedMap;
46+
47+
import java.util.Set;
48+
4549
/**
4650
* Utility for working with @Ref annotations
4751
*
@@ -75,4 +79,25 @@ interface InjectLinkDescriptor {
7579
* @return the condition
7680
*/
7781
String getCondition();
82+
83+
/**
84+
* Get the list of query parameters injected by @LinkQueryParam.
85+
* @return the list of query parameters.
86+
*/
87+
MultivaluedMap<String, String> getQueryParams();
88+
89+
/**
90+
* The request query parameters should be included in response Links.
91+
* @return true if we need request query parameters.
92+
*/
93+
boolean copyFromRequestParams();
94+
95+
/**
96+
* A list of request parameters keys to exclude from response links.
97+
* It's used if copyFromRequestParams() is enabled.
98+
*
99+
* @return the list of parameters keys names to exclude.
100+
*/
101+
Set<String> excludeFromRequestParams();
102+
78103
}

Diff for: incubator/declarative-linking/src/main/java/org/glassfish/jersey/linking/InjectLinkFieldDescriptor.java

+41-2
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@
4444
import java.lang.reflect.Field;
4545
import java.lang.reflect.Method;
4646
import java.net.URI;
47+
import java.util.Arrays;
48+
import java.util.Collections;
4749
import java.util.HashMap;
50+
import java.util.HashSet;
4851
import java.util.Iterator;
4952
import java.util.Map;
53+
import java.util.Objects;
54+
import java.util.Set;
5055
import java.util.logging.Level;
5156
import java.util.logging.Logger;
5257

@@ -55,7 +60,10 @@
5560
import javax.ws.rs.QueryParam;
5661
import javax.ws.rs.BeanParam;
5762
import javax.ws.rs.core.Link;
63+
import javax.ws.rs.core.MultivaluedHashMap;
64+
import javax.ws.rs.core.MultivaluedMap;
5865

66+
import org.glassfish.jersey.linking.InjectLink.LinkQueryParam;
5967
import org.glassfish.jersey.linking.mapping.ResourceMappingContext;
6068
import org.glassfish.jersey.server.model.AnnotatedMethod;
6169
import org.glassfish.jersey.server.model.MethodList;
@@ -71,6 +79,9 @@ class InjectLinkFieldDescriptor extends FieldDescriptor implements InjectLinkDes
7179
private InjectLink link;
7280
private Class<?> type;
7381
private Map<String, String> bindings;
82+
private MultivaluedMap<String, String> queryParams;
83+
private boolean copyFromRequestQueryParams = false;
84+
private Set<String> excludeFromRequestQueryParams = null;
7485

7586
/**
7687
* TODO javadoc.
@@ -83,6 +94,16 @@ public InjectLinkFieldDescriptor(Field f, InjectLink l, Class<?> t) {
8394
for (Binding binding : l.bindings()) {
8495
bindings.put(binding.name(), binding.value());
8596
}
97+
queryParams = new MultivaluedHashMap<>();
98+
for (LinkQueryParam param: l.queryParams()) {
99+
queryParams.add(param.name(), param.value());
100+
}
101+
copyFromRequestQueryParams = l.copyRequestQueryParams();
102+
if (copyFromRequestQueryParams) {
103+
excludeFromRequestQueryParams =
104+
Collections.unmodifiableSet(
105+
new HashSet<>(Arrays.asList(l.excludeFromRequestQueryParams())));
106+
}
86107
}
87108

88109
/**
@@ -93,13 +114,13 @@ public void setPropertyValue(Object instance, URI uri) {
93114
try {
94115

95116
Object value;
96-
if (URI.class.equals(type)) {
117+
if (Objects.equals(URI.class, type)) {
97118
value = uri;
98119
} else if (Link.class.isAssignableFrom(type)) {
99120

100121
// Make a link with the correct bindings
101122
value = getLink(uri);
102-
} else if (String.class.equals(type)) {
123+
} else if (Objects.equals(String.class, type)) {
103124
value = uri.toString();
104125
} else {
105126
throw new IllegalArgumentException("Field type " + type + " not one of supported String,URI and Link");
@@ -247,4 +268,22 @@ public String getBinding(String name) {
247268
public String getCondition() {
248269
return link.condition();
249270
}
271+
272+
@Override
273+
public MultivaluedMap<String, String> getQueryParams() {
274+
return queryParams;
275+
}
276+
277+
@Override
278+
public boolean copyFromRequestParams() {
279+
return copyFromRequestQueryParams;
280+
}
281+
282+
@Override
283+
public Set<String> excludeFromRequestParams() {
284+
if (!copyFromRequestQueryParams) {
285+
return null;
286+
}
287+
return excludeFromRequestQueryParams;
288+
}
250289
}

Diff for: incubator/declarative-linking/src/main/java/org/glassfish/jersey/linking/LinkHeaderDescriptor.java

+40
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,20 @@
4040

4141
package org.glassfish.jersey.linking;
4242

43+
import java.util.Arrays;
44+
import java.util.Collections;
4345
import java.util.HashMap;
46+
import java.util.HashSet;
4447
import java.util.Map;
48+
import java.util.Set;
4549

50+
import org.glassfish.jersey.linking.InjectLink.LinkQueryParam;
4651
import org.glassfish.jersey.linking.InjectLink.Style;
4752
import org.glassfish.jersey.linking.mapping.ResourceMappingContext;
4853

54+
import javax.ws.rs.core.MultivaluedHashMap;
55+
import javax.ws.rs.core.MultivaluedMap;
56+
4957
/**
5058
* Utility class for working with {@link org.glassfish.jersey.linking.InjectLink} annotations
5159
*
@@ -56,13 +64,27 @@ class LinkHeaderDescriptor implements InjectLinkDescriptor {
5664

5765
private InjectLink linkHeader;
5866
private Map<String, String> bindings;
67+
private MultivaluedMap<String, String> queryParams;
68+
private boolean copyFromRequestQueryParams = false;
69+
private Set<String> excludeFromRequestQueryParams = null;
70+
5971

6072
LinkHeaderDescriptor(InjectLink linkHeader) {
6173
this.linkHeader = linkHeader;
6274
bindings = new HashMap<String, String>();
6375
for (Binding binding : linkHeader.bindings()) {
6476
bindings.put(binding.name(), binding.value());
6577
}
78+
queryParams = new MultivaluedHashMap<>();
79+
for (LinkQueryParam param : linkHeader.queryParams()) {
80+
queryParams.add(param.name(), param.value());
81+
}
82+
copyFromRequestQueryParams = linkHeader.copyRequestQueryParams();
83+
if (copyFromRequestQueryParams) {
84+
excludeFromRequestQueryParams =
85+
Collections.unmodifiableSet(
86+
new HashSet<>(Arrays.asList(linkHeader.excludeFromRequestQueryParams())));
87+
}
6688
}
6789

6890
public InjectLink getLinkHeader() {
@@ -85,4 +107,22 @@ public String getCondition() {
85107
return linkHeader.condition();
86108
}
87109

110+
@Override
111+
public MultivaluedMap<String, String> getQueryParams() {
112+
return queryParams;
113+
}
114+
115+
@Override
116+
public boolean copyFromRequestParams() {
117+
return copyFromRequestQueryParams;
118+
}
119+
120+
@Override
121+
public Set<String> excludeFromRequestParams() {
122+
if (!copyFromRequestQueryParams) {
123+
return null;
124+
}
125+
return excludeFromRequestQueryParams;
126+
}
127+
88128
}

Diff for: incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/HeaderProcessorTest.java

+75-3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
5353
import org.glassfish.jersey.linking.InjectLink.Extension;
54+
import org.glassfish.jersey.linking.InjectLink.LinkQueryParam;
5455
import org.glassfish.jersey.linking.mapping.ResourceMappingContext;
5556
import org.glassfish.jersey.server.ExtendedUriInfo;
5657
import org.glassfish.jersey.server.model.Resource;
@@ -123,11 +124,15 @@ public MultivaluedMap<String, String> getPathParameters(boolean decode) {
123124
}
124125

125126
public MultivaluedMap<String, String> getQueryParameters() {
126-
return new MultivaluedStringMap();
127+
MultivaluedStringMap map = new MultivaluedStringMap();
128+
map.add("q", "somevalue");
129+
return map;
127130
}
128131

129132
public MultivaluedMap<String, String> getQueryParameters(boolean decode) {
130-
return new MultivaluedStringMap();
133+
MultivaluedStringMap map = new MultivaluedStringMap();
134+
map.add("q", "somevalue");
135+
return map;
131136
}
132137

133138
public List<String> getMatchedURIs() {
@@ -361,7 +366,6 @@ public String getId2() {
361366

362367
@Test
363368
public void testConditional() {
364-
System.out.println("EL");
365369
HeaderProcessor<EntityF> instance = new HeaderProcessor(EntityF.class);
366370
EntityF testClass = new EntityF();
367371
List<String> headerValues = instance.getLinkHeaderValues(testClass, mockUriInfo, mockRmc);
@@ -370,4 +374,72 @@ public void testConditional() {
370374
assertEquals("</application/resources/1>", headerValue);
371375
}
372376

377+
@InjectLinks({
378+
@InjectLink(
379+
value = "${entity.id1}",
380+
queryParams = { @LinkQueryParam (name = "page", value = "${instance.page}"),
381+
@LinkQueryParam (name = "page", value = "${instance.page2}"),
382+
}
383+
)
384+
})
385+
public static class EntityQ {
386+
387+
public String getId1() {
388+
return "1";
389+
}
390+
391+
public String getPage() {
392+
return "42";
393+
}
394+
395+
public String getPage2() {
396+
return "43";
397+
}
398+
}
399+
400+
@Test
401+
public void testQueryParam() {
402+
HeaderProcessor<EntityQ> instance = new HeaderProcessor(EntityQ.class);
403+
EntityQ testClass = new EntityQ();
404+
List<String> headerValues = instance.getLinkHeaderValues(testClass, mockUriInfo, mockRmc);
405+
assertEquals(1, headerValues.size());
406+
String headerValue = headerValues.get(0);
407+
assertEquals("</application/resources/1?page=42&page=43>", headerValue);
408+
}
409+
410+
411+
@InjectLinks({
412+
@InjectLink(
413+
value = "${entity.id1}",
414+
copyRequestQueryParams = true,
415+
excludeFromRequestQueryParams = {"page"},
416+
queryParams = {
417+
@LinkQueryParam (name = "page", value = "${instance.page}"),
418+
}
419+
)
420+
})
421+
public static class EntityR {
422+
423+
public String getId1() {
424+
return "1";
425+
}
426+
427+
public String getPage() {
428+
return "42";
429+
}
430+
431+
public String getPage2() {
432+
return "43";
433+
}
434+
}
435+
436+
@Test
437+
public void testRequestQueryParam() {
438+
HeaderProcessor<EntityR> instance = new HeaderProcessor(EntityR.class);
439+
EntityR testClass = new EntityR();
440+
List<String> headerValues = instance.getLinkHeaderValues(testClass, mockUriInfo, mockRmc);
441+
assertEquals(1, headerValues.size());
442+
String headerValue = headerValues.get(0);
443+
assertEquals("</application/resources/1?page=42&q=somevalue>", headerValue);
444+
}
373445
}

0 commit comments

Comments
 (0)