PageRenderTime 49ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/FieldProcessorTest.java

http://github.com/jersey/jersey
Java | 877 lines | 654 code | 173 blank | 50 comment | 5 complexity | 2b169b5095b0d1b562ad89d1cbbf0114 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright (c) 2010-2017 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * The contents of this file are subject to the terms of either the GNU
  7. * General Public License Version 2 only ("GPL") or the Common Development
  8. * and Distribution License("CDDL") (collectively, the "License"). You
  9. * may not use this file except in compliance with the License. You can
  10. * obtain a copy of the License at
  11. * https://oss.oracle.com/licenses/CDDL+GPL-1.1
  12. * or LICENSE.txt. See the License for the specific
  13. * language governing permissions and limitations under the License.
  14. *
  15. * When distributing the software, include this License Header Notice in each
  16. * file and include the License file at LICENSE.txt.
  17. *
  18. * GPL Classpath Exception:
  19. * Oracle designates this particular file as subject to the "Classpath"
  20. * exception as provided by Oracle in the GPL Version 2 section of the License
  21. * file that accompanied this code.
  22. *
  23. * Modifications:
  24. * If applicable, add the following below the License Header, with the fields
  25. * enclosed by brackets [] replaced by your own identifying information:
  26. * "Portions Copyright [year] [name of copyright owner]"
  27. *
  28. * Contributor(s):
  29. * If you wish your version of this file to be governed by only the CDDL or
  30. * only the GPL Version 2, indicate your decision by adding "[Contributor]
  31. * elects to include this software in this distribution under the [CDDL or GPL
  32. * Version 2] license." If you don't indicate a single choice of license, a
  33. * recipient has the option to distribute your version of this file under
  34. * either the CDDL, the GPL Version 2 or to extend the choice of license to
  35. * its licensees as provided above. However, if you add GPL Version 2 code
  36. * and therefore, elected the GPL Version 2 license, then the option applies
  37. * only if the new code is made subject to such option by the copyright
  38. * holder.
  39. */
  40. package org.glassfish.jersey.linking;
  41. import java.net.URI;
  42. import java.util.Arrays;
  43. import java.util.Collections;
  44. import java.util.HashMap;
  45. import java.util.Iterator;
  46. import java.util.List;
  47. import java.util.Map;
  48. import java.util.logging.Filter;
  49. import java.util.logging.LogRecord;
  50. import java.util.logging.Logger;
  51. import java.util.regex.MatchResult;
  52. import java.util.zip.ZipEntry;
  53. import javax.ws.rs.BeanParam;
  54. import javax.ws.rs.GET;
  55. import javax.ws.rs.Path;
  56. import javax.ws.rs.QueryParam;
  57. import javax.ws.rs.core.Link;
  58. import javax.ws.rs.core.MultivaluedMap;
  59. import javax.ws.rs.core.PathSegment;
  60. import javax.ws.rs.core.UriBuilder;
  61. import javax.xml.bind.annotation.XmlTransient;
  62. import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
  63. import org.glassfish.jersey.linking.contributing.ResourceLinkContributionContext;
  64. import org.glassfish.jersey.linking.mapping.ResourceMappingContext;
  65. import org.glassfish.jersey.server.ExtendedUriInfo;
  66. import org.glassfish.jersey.server.model.Resource;
  67. import org.glassfish.jersey.server.model.ResourceMethod;
  68. import org.glassfish.jersey.server.model.RuntimeResource;
  69. import org.glassfish.jersey.uri.UriTemplate;
  70. import org.junit.Test;
  71. import static org.junit.Assert.assertEquals;
  72. import static org.junit.Assert.assertTrue;
  73. /**
  74. * @author Mark Hadley
  75. * @author Gerard Davison (gerard.davison at oracle.com)
  76. */
  77. public class FieldProcessorTest {
  78. private static final Logger LOG = Logger.getLogger(FieldProcessor.class.getName());
  79. ExtendedUriInfo mockUriInfo = new ExtendedUriInfo() {
  80. private static final String baseURI = "http://example.com/application/resources";
  81. private MultivaluedMap queryParams = new MultivaluedStringMap();
  82. @Override
  83. public String getPath() {
  84. throw new UnsupportedOperationException("Not supported yet.");
  85. }
  86. @Override
  87. public String getPath(boolean decode) {
  88. throw new UnsupportedOperationException("Not supported yet.");
  89. }
  90. @Override
  91. public List<PathSegment> getPathSegments() {
  92. throw new UnsupportedOperationException("Not supported yet.");
  93. }
  94. @Override
  95. public List<PathSegment> getPathSegments(boolean decode) {
  96. throw new UnsupportedOperationException("Not supported yet.");
  97. }
  98. @Override
  99. public URI getRequestUri() {
  100. throw new UnsupportedOperationException("Not supported yet.");
  101. }
  102. @Override
  103. public UriBuilder getRequestUriBuilder() {
  104. throw new UnsupportedOperationException("Not supported yet.");
  105. }
  106. @Override
  107. public URI getAbsolutePath() {
  108. throw new UnsupportedOperationException("Not supported yet.");
  109. }
  110. @Override
  111. public UriBuilder getAbsolutePathBuilder() {
  112. throw new UnsupportedOperationException("Not supported yet.");
  113. }
  114. @Override
  115. public URI getBaseUri() {
  116. return getBaseUriBuilder().build();
  117. }
  118. @Override
  119. public UriBuilder getBaseUriBuilder() {
  120. return UriBuilder.fromUri(baseURI);
  121. }
  122. @Override
  123. public MultivaluedMap<String, String> getPathParameters() {
  124. return new MultivaluedStringMap();
  125. }
  126. @Override
  127. public MultivaluedMap<String, String> getPathParameters(boolean decode) {
  128. return new MultivaluedStringMap();
  129. }
  130. @Override
  131. public MultivaluedMap<String, String> getQueryParameters() {
  132. return queryParams;
  133. }
  134. @Override
  135. public MultivaluedMap<String, String> getQueryParameters(boolean decode) {
  136. return queryParams;
  137. }
  138. @Override
  139. public List<String> getMatchedURIs() {
  140. throw new UnsupportedOperationException("Not supported yet.");
  141. }
  142. @Override
  143. public List<String> getMatchedURIs(boolean decode) {
  144. throw new UnsupportedOperationException("Not supported yet.");
  145. }
  146. @Override
  147. public List<Object> getMatchedResources() {
  148. Object dummyResource = new Object() {
  149. };
  150. return Collections.singletonList(dummyResource);
  151. }
  152. @Override
  153. public Throwable getMappedThrowable() {
  154. throw new UnsupportedOperationException("Not supported yet.");
  155. }
  156. @Override
  157. public List<MatchResult> getMatchedResults() {
  158. throw new UnsupportedOperationException("Not supported yet.");
  159. }
  160. @Override
  161. public List<UriTemplate> getMatchedTemplates() {
  162. throw new UnsupportedOperationException("Not supported yet.");
  163. }
  164. @Override
  165. public List<PathSegment> getPathSegments(String name) {
  166. throw new UnsupportedOperationException("Not supported yet.");
  167. }
  168. @Override
  169. public List<PathSegment> getPathSegments(String name, boolean decode) {
  170. throw new UnsupportedOperationException("Not supported yet.");
  171. }
  172. @Override
  173. public List<RuntimeResource> getMatchedRuntimeResources() {
  174. throw new UnsupportedOperationException("Not supported yet.");
  175. }
  176. @Override
  177. public ResourceMethod getMatchedResourceMethod() {
  178. throw new UnsupportedOperationException("Not supported yet.");
  179. }
  180. @Override
  181. public Resource getMatchedModelResource() {
  182. throw new UnsupportedOperationException("Not supported yet.");
  183. }
  184. @Override
  185. public List<ResourceMethod> getMatchedResourceLocators() {
  186. throw new UnsupportedOperationException("Not supported yet.");
  187. }
  188. @Override
  189. public List<Resource> getLocatorSubResources() {
  190. throw new UnsupportedOperationException("Not supported yet.");
  191. }
  192. @Override
  193. public URI resolve(URI uri) {
  194. throw new UnsupportedOperationException("Not supported yet.");
  195. }
  196. @Override
  197. public URI relativize(URI uri) {
  198. throw new UnsupportedOperationException("Not supported yet.");
  199. }
  200. };
  201. private final ResourceMappingContext mockRmc = new ResourceMappingContext() {
  202. @Override
  203. public ResourceMappingContext.Mapping getMapping(Class<?> resource) {
  204. return null;
  205. }
  206. };
  207. protected final ResourceLinkContributionContext mockRlcc = new ResourceLinkContributionContext() {
  208. @Override
  209. public List<ProvideLinkDescriptor> getContributorsFor(Class<?> entityClass) {
  210. return Collections.emptyList();
  211. }
  212. };
  213. private static final String TEMPLATE_A = "foo";
  214. public static class TestClassD {
  215. @InjectLink(value = TEMPLATE_A, style = InjectLink.Style.RELATIVE_PATH)
  216. private String res1;
  217. @InjectLink(value = TEMPLATE_A, style = InjectLink.Style.RELATIVE_PATH)
  218. private URI res2;
  219. }
  220. @Test
  221. public void testProcessLinks() {
  222. LOG.info("Links");
  223. FieldProcessor<TestClassD> instance = new FieldProcessor(TestClassD.class);
  224. TestClassD testClass = new TestClassD();
  225. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  226. assertEquals(TEMPLATE_A, testClass.res1);
  227. assertEquals(TEMPLATE_A, testClass.res2.toString());
  228. }
  229. private static final String TEMPLATE_B = "widgets/{id}";
  230. public static class TestClassE {
  231. @InjectLink(value = TEMPLATE_B, style = InjectLink.Style.RELATIVE_PATH)
  232. private String link;
  233. private String id;
  234. public TestClassE(String id) {
  235. this.id = id;
  236. }
  237. public String getId() {
  238. return id;
  239. }
  240. }
  241. @Test
  242. public void testProcessLinksWithFields() {
  243. LOG.info("Links from field values");
  244. FieldProcessor<TestClassE> instance = new FieldProcessor(TestClassE.class);
  245. TestClassE testClass = new TestClassE("10");
  246. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  247. assertEquals("widgets/10", testClass.link);
  248. }
  249. public static class TestClassF {
  250. @InjectLink(value = TEMPLATE_B, style = InjectLink.Style.RELATIVE_PATH)
  251. private String thelink;
  252. private String id;
  253. private TestClassE nested;
  254. public TestClassF(String id, TestClassE e) {
  255. this.id = id;
  256. this.nested = e;
  257. }
  258. public String getId() {
  259. return id;
  260. }
  261. }
  262. @Test
  263. public void testNesting() {
  264. LOG.info("Nesting");
  265. FieldProcessor<TestClassF> instance = new FieldProcessor(TestClassF.class);
  266. TestClassE nested = new TestClassE("10");
  267. TestClassF testClass = new TestClassF("20", nested);
  268. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  269. assertEquals("widgets/20", testClass.thelink);
  270. assertEquals("widgets/10", testClass.nested.link);
  271. }
  272. @Test
  273. public void testArray() {
  274. LOG.info("Array");
  275. FieldProcessor<TestClassE[]> instance = new FieldProcessor(TestClassE[].class);
  276. TestClassE item1 = new TestClassE("10");
  277. TestClassE item2 = new TestClassE("20");
  278. TestClassE array[] = {item1, item2};
  279. instance.processLinks(array, mockUriInfo, mockRmc, mockRlcc);
  280. assertEquals("widgets/10", array[0].link);
  281. assertEquals("widgets/20", array[1].link);
  282. }
  283. @Test
  284. public void testCollection() {
  285. LOG.info("Collection");
  286. FieldProcessor<List> instance = new FieldProcessor(List.class);
  287. TestClassE item1 = new TestClassE("10");
  288. TestClassE item2 = new TestClassE("20");
  289. List<TestClassE> list = Arrays.asList(item1, item2);
  290. instance.processLinks(list, mockUriInfo, mockRmc, mockRlcc);
  291. assertEquals("widgets/10", list.get(0).link);
  292. assertEquals("widgets/20", list.get(1).link);
  293. }
  294. @Test
  295. public void testMap() {
  296. LOG.info("Map");
  297. FieldProcessor<Map> instance = new FieldProcessor(Map.class);
  298. TestClassE item1 = new TestClassE("10");
  299. TestClassE item2 = new TestClassE("20");
  300. Map<String, TestClassE> map = new HashMap<>();
  301. for (TestClassE item : Arrays.asList(item1, item2)) {
  302. map.put(item.getId(), item);
  303. }
  304. instance.processLinks(map, mockUriInfo, mockRmc, mockRlcc);
  305. assertEquals("widgets/10", map.get("10").link);
  306. assertEquals("widgets/20", map.get("20").link);
  307. }
  308. public static class TestClassG {
  309. @InjectLink(value = TEMPLATE_B, style = InjectLink.Style.RELATIVE_PATH)
  310. private String relativePath;
  311. @InjectLink(value = TEMPLATE_B, style = InjectLink.Style.ABSOLUTE_PATH)
  312. private String absolutePath;
  313. @InjectLink(value = TEMPLATE_B, style = InjectLink.Style.ABSOLUTE)
  314. private String absolute;
  315. @InjectLink(TEMPLATE_B)
  316. private String defaultStyle;
  317. private String id;
  318. public TestClassG(String id) {
  319. this.id = id;
  320. }
  321. public String getId() {
  322. return id;
  323. }
  324. }
  325. @Test
  326. public void testLinkStyles() {
  327. LOG.info("Link styles");
  328. FieldProcessor<TestClassG> instance = new FieldProcessor(TestClassG.class);
  329. TestClassG testClass = new TestClassG("10");
  330. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  331. assertEquals("widgets/10", testClass.relativePath);
  332. assertEquals("/application/resources/widgets/10", testClass.absolutePath);
  333. assertEquals("/application/resources/widgets/10", testClass.defaultStyle);
  334. assertEquals("http://example.com/application/resources/widgets/10", testClass.absolute);
  335. }
  336. public static class TestClassH {
  337. @InjectLink(TEMPLATE_B)
  338. private String link;
  339. public String getId() {
  340. return "10";
  341. }
  342. }
  343. @Test
  344. public void testComputedProperty() {
  345. LOG.info("Computed property");
  346. FieldProcessor<TestClassH> instance = new FieldProcessor(TestClassH.class);
  347. TestClassH testClass = new TestClassH();
  348. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  349. assertEquals("/application/resources/widgets/10", testClass.link);
  350. }
  351. public static class TestClassI {
  352. @InjectLink("widgets/${entity.id}")
  353. private String link;
  354. public String getId() {
  355. return "10";
  356. }
  357. }
  358. @Test
  359. public void testEL() {
  360. LOG.info("El link");
  361. FieldProcessor<TestClassI> instance = new FieldProcessor(TestClassI.class);
  362. TestClassI testClass = new TestClassI();
  363. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  364. assertEquals("/application/resources/widgets/10", testClass.link);
  365. }
  366. public static class TestClassJ {
  367. @InjectLink("widgets/${entity.id}/widget/{id}")
  368. private String link;
  369. public String getId() {
  370. return "10";
  371. }
  372. }
  373. @Test
  374. public void testMixed() {
  375. LOG.info("Mixed EL and template vars link");
  376. FieldProcessor<TestClassJ> instance = new FieldProcessor(TestClassJ.class);
  377. TestClassJ testClass = new TestClassJ();
  378. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  379. assertEquals("/application/resources/widgets/10/widget/10", testClass.link);
  380. }
  381. public static class DependentInnerBean {
  382. @InjectLink("${entity.id}")
  383. public String outerUri;
  384. @InjectLink("${instance.id}")
  385. public String innerUri;
  386. public String getId() {
  387. return "inner";
  388. }
  389. }
  390. public static class OuterBean {
  391. public DependentInnerBean inner = new DependentInnerBean();
  392. public String getId() {
  393. return "outer";
  394. }
  395. }
  396. @Test
  397. public void testELScopes() {
  398. LOG.info("EL scopes");
  399. FieldProcessor<OuterBean> instance = new FieldProcessor(OuterBean.class);
  400. OuterBean testClass = new OuterBean();
  401. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  402. assertEquals("/application/resources/inner", testClass.inner.innerUri);
  403. assertEquals("/application/resources/outer", testClass.inner.outerUri);
  404. }
  405. public static class BoundLinkBean {
  406. @InjectLink(value = "{id}", bindings = {@Binding(name = "id", value = "${instance.name}")})
  407. public String uri;
  408. public String getName() {
  409. return "name";
  410. }
  411. }
  412. @Test
  413. public void testELBinding() {
  414. LOG.info("EL binding");
  415. FieldProcessor<BoundLinkBean> instance = new FieldProcessor(BoundLinkBean.class);
  416. BoundLinkBean testClass = new BoundLinkBean();
  417. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  418. assertEquals("/application/resources/name", testClass.uri);
  419. }
  420. public static class BoundLinkOnLinkBean {
  421. @InjectLink(value = "{id}",
  422. bindings = {@Binding(name = "id", value = "${instance.name}")},
  423. rel = "self")
  424. public Link link;
  425. public String getName() {
  426. return "name";
  427. }
  428. }
  429. @Test
  430. public void testELBindingOnLink() {
  431. LOG.info("EL binding");
  432. FieldProcessor<BoundLinkOnLinkBean> instance = new FieldProcessor(BoundLinkOnLinkBean.class);
  433. BoundLinkOnLinkBean testClass = new BoundLinkOnLinkBean();
  434. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  435. assertEquals("/application/resources/name", testClass.link.getUri().toString());
  436. assertEquals("self", testClass.link.getRel());
  437. }
  438. public static class BoundLinkOnLinksBean {
  439. @InjectLinks({
  440. @InjectLink(value = "{id}",
  441. bindings = {@Binding(name = "id", value = "${instance.name}")},
  442. rel = "self"),
  443. @InjectLink(value = "{id}",
  444. bindings = {@Binding(name = "id", value = "${instance.name}")},
  445. rel = "other"),
  446. })
  447. public List<Link> links;
  448. @InjectLinks({
  449. @InjectLink(value = "{id}",
  450. bindings = {@Binding(name = "id", value = "${instance.name}")},
  451. rel = "self"),
  452. @InjectLink(value = "{id}",
  453. bindings = {@Binding(name = "id", value = "${instance.name}")},
  454. rel = "other"),
  455. })
  456. public Link[] linksArray;
  457. public String getName() {
  458. return "name";
  459. }
  460. }
  461. @Test
  462. public void testELBindingOnLinks() {
  463. LOG.info("EL binding");
  464. FieldProcessor<BoundLinkOnLinksBean> instance = new FieldProcessor(BoundLinkOnLinksBean.class);
  465. BoundLinkOnLinksBean testClass = new BoundLinkOnLinksBean();
  466. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  467. assertEquals("/application/resources/name", testClass.links.get(0).getUri().toString());
  468. assertEquals("self", testClass.links.get(0).getRel());
  469. assertEquals("other", testClass.links.get(1).getRel());
  470. assertEquals("/application/resources/name", testClass.linksArray[0].getUri().toString());
  471. assertEquals("self", testClass.linksArray[0].getRel());
  472. assertEquals("other", testClass.linksArray[1].getRel());
  473. }
  474. public static class ConditionalLinkBean {
  475. @InjectLink(value = "{id}", condition = "${entity.uri1Enabled}")
  476. public String uri1;
  477. @InjectLink(value = "{id}", condition = "${entity.uri2Enabled}")
  478. public String uri2;
  479. public String getId() {
  480. return "name";
  481. }
  482. public boolean isUri1Enabled() {
  483. return true;
  484. }
  485. public boolean isUri2Enabled() {
  486. return false;
  487. }
  488. }
  489. @Test
  490. public void testCondition() {
  491. LOG.info("Condition");
  492. FieldProcessor<ConditionalLinkBean> instance = new FieldProcessor(ConditionalLinkBean.class);
  493. ConditionalLinkBean testClass = new ConditionalLinkBean();
  494. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  495. assertEquals("/application/resources/name", testClass.uri1);
  496. assertEquals(null, testClass.uri2);
  497. }
  498. @Path("a")
  499. public static class SubResource {
  500. @Path("b")
  501. @GET
  502. public String getB() {
  503. return "hello world";
  504. }
  505. }
  506. public static class SubResourceBean {
  507. @InjectLink(resource = SubResource.class, method = "getB")
  508. public String uri;
  509. }
  510. @Test
  511. public void testSubresource() {
  512. LOG.info("Subresource");
  513. FieldProcessor<SubResourceBean> instance = new FieldProcessor(SubResourceBean.class);
  514. SubResourceBean testClass = new SubResourceBean();
  515. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  516. assertEquals("/application/resources/a/b", testClass.uri);
  517. }
  518. @Path("a")
  519. public static class QueryResource {
  520. @Path("b")
  521. @GET
  522. public String getB(@QueryParam("query") String query, @QueryParam("query2") String query2) {
  523. return "hello world";
  524. }
  525. }
  526. public static class QueryResourceBean {
  527. public String getQueryParam() {
  528. return queryExample;
  529. }
  530. private String queryExample;
  531. public QueryResourceBean(String queryExample, String queryExample2) {
  532. this.queryExample = queryExample;
  533. this.queryExample2 = queryExample2;
  534. }
  535. public String getQueryParam2() {
  536. return queryExample2;
  537. }
  538. private String queryExample2;
  539. @InjectLink(resource = QueryResource.class, method = "getB",
  540. bindings = {
  541. @Binding(name = "query", value = "${instance.queryParam}"),
  542. @Binding(name = "query2", value = "${instance.queryParam2}")
  543. })
  544. public String uri;
  545. }
  546. public static class QueryResourceBeanNoBindings {
  547. //query parameters will be populated from uriInfo
  548. //JERSEY-2863
  549. @InjectLink(resource = QueryResource.class, method = "getB")
  550. public String uri;
  551. }
  552. @Test
  553. public void testQueryResource() {
  554. LOG.info("QueryResource");
  555. FieldProcessor<QueryResourceBean> instance = new FieldProcessor(QueryResourceBean.class);
  556. QueryResourceBean testClass = new QueryResourceBean("queryExample", null);
  557. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  558. assertEquals("/application/resources/a/b?query=queryExample&query2=", testClass.uri);
  559. }
  560. @Test
  561. public void testDoubleQueryResource() {
  562. LOG.info("QueryResource");
  563. FieldProcessor<QueryResourceBean> instance = new FieldProcessor(QueryResourceBean.class);
  564. QueryResourceBean testClass = new QueryResourceBean("queryExample", "queryExample2");
  565. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  566. assertEquals("/application/resources/a/b?query=queryExample&query2=queryExample2", testClass.uri);
  567. }
  568. @Test
  569. public void testQueryResourceWithoutBindings() {
  570. LOG.info("QueryResource");
  571. FieldProcessor<QueryResourceBeanNoBindings> instance = new FieldProcessor(QueryResourceBeanNoBindings.class);
  572. QueryResourceBeanNoBindings testClass = new QueryResourceBeanNoBindings();
  573. mockUriInfo.getQueryParameters().putSingle("query", "queryExample");
  574. mockUriInfo.getQueryParameters().putSingle("query2", "queryExample2");
  575. assertEquals("queryExample", mockUriInfo.getQueryParameters().getFirst("query"));
  576. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  577. assertEquals("/application/resources/a/b?query=queryExample&query2=queryExample2", testClass.uri);
  578. //clean mock
  579. mockUriInfo.getQueryParameters().clear();
  580. }
  581. /** Bean param with method setter QueryParam. */
  582. public static class BeanParamBeanA {
  583. private String qparam;
  584. @QueryParam("qparam")
  585. public void setQParam(String qparam) {
  586. this.qparam = qparam;
  587. }
  588. }
  589. /** Bean param with field QueryParam. */
  590. public static class BeanParamBeanB {
  591. @QueryParam("query") public String query;
  592. }
  593. @Path("a")
  594. public static class BeanParamQueryResource {
  595. @Path("b")
  596. @GET
  597. public String getB(@BeanParam BeanParamBeanA beanParamBeanA, @BeanParam BeanParamBeanB beanParamBeanB) {
  598. return "hello world";
  599. }
  600. }
  601. public static class BeanParamResourceBean {
  602. public String getQueryParam() {
  603. return queryExample;
  604. }
  605. private String queryExample;
  606. public BeanParamResourceBean(String queryExample) {
  607. this.queryExample = queryExample;
  608. }
  609. @InjectLink(resource = BeanParamQueryResource.class, method = "getB",
  610. bindings = {
  611. @Binding(name = "query", value = "${instance.queryParam}"),
  612. @Binding(name = "qparam", value = "foo")
  613. })
  614. public String uri;
  615. }
  616. @Test
  617. public void testBeanParamResource() {
  618. LOG.info("BeanParamResource");
  619. FieldProcessor<BeanParamResourceBean> instance = new FieldProcessor(BeanParamResourceBean.class);
  620. BeanParamResourceBean testClass = new BeanParamResourceBean("queryExample");
  621. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  622. assertEquals("/application/resources/a/b?qparam=foo&query=queryExample", testClass.uri);
  623. }
  624. public static class TestClassK {
  625. public static final ZipEntry zipEntry = new ZipEntry("entry");
  626. }
  627. public static class TestClassL {
  628. public final ZipEntry zipEntry = new ZipEntry("entry");
  629. }
  630. private class LoggingFilter implements Filter {
  631. private int count = 0;
  632. @Override
  633. public synchronized boolean isLoggable(LogRecord logRecord) {
  634. if (logRecord.getThrown() instanceof IllegalAccessException) {
  635. count++;
  636. return false;
  637. }
  638. return true;
  639. }
  640. public int getCount() {
  641. return count;
  642. }
  643. }
  644. @Test
  645. public void testKL() {
  646. final LoggingFilter lf = new LoggingFilter();
  647. Logger.getLogger(FieldDescriptor.class.getName()).setFilter(lf);
  648. assertTrue(lf.getCount() == 0);
  649. FieldProcessor<TestClassK> instanceK = new FieldProcessor(TestClassK.class);
  650. TestClassK testClassK = new TestClassK();
  651. instanceK.processLinks(testClassK, mockUriInfo, mockRmc, mockRlcc);
  652. assertTrue(lf.getCount() == 0);
  653. FieldProcessor<TestClassL> instanceL = new FieldProcessor(TestClassL.class);
  654. TestClassL testClassL = new TestClassL();
  655. instanceL.processLinks(testClassL, mockUriInfo, mockRmc, mockRlcc);
  656. assertTrue(lf.getCount() == 0);
  657. Logger.getLogger(FieldDescriptor.class.getName()).setFilter(null);
  658. }
  659. public static class TestClassM {
  660. @InjectLink(value = TEMPLATE_B, style = InjectLink.Style.RELATIVE_PATH)
  661. private String thelink;
  662. private String id;
  663. @InjectLinkNoFollow
  664. private TestClassE nested;
  665. @XmlTransient
  666. private TestClassE transientNested;
  667. public TestClassM(String id, TestClassE e, TestClassE transientNested) {
  668. this.id = id;
  669. this.nested = e;
  670. this.transientNested = transientNested;
  671. }
  672. public String getId() {
  673. return id;
  674. }
  675. }
  676. @Test
  677. public void testNoRecursiveNesting() {
  678. LOG.info("No Recursive Nesting");
  679. FieldProcessor<TestClassM> instance = new FieldProcessor(TestClassM.class);
  680. TestClassE nested = new TestClassE("10");
  681. TestClassE transientNested = new TestClassE("30");
  682. TestClassM testClass = new TestClassM("20", nested, transientNested);
  683. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  684. assertEquals("widgets/20", testClass.thelink);
  685. assertEquals(null, testClass.nested.link);
  686. assertEquals(null, testClass.transientNested.link);
  687. }
  688. public static class TestClassN {
  689. // Simulate object injected by JPA
  690. // in order to test a fix for JERSEY-2625
  691. private transient Iterable res1 = new Iterable() {
  692. @Override
  693. public Iterator iterator() {
  694. throw new RuntimeException("Declarative linking feature is incorrectly processing a transient iterator");
  695. }
  696. };
  697. }
  698. @Test
  699. public void testIgnoreTransient() {
  700. TestClassN testClass = new TestClassN();
  701. FieldProcessor<TestClassN> instance = new FieldProcessor(TestClassN.class);
  702. instance.processLinks(testClass, mockUriInfo, mockRmc, mockRlcc);
  703. }
  704. }