View Javadoc

1   /*
2    * Copyright 2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.resteasy.hypermedia.adapter;
17  
18  import java.lang.reflect.Method;
19  import java.util.List;
20  
21  import javax.ws.rs.core.UriInfo;
22  
23  import org.jboss.resteasy.core.ResourceMethodRegistry;
24  import org.jboss.resteasy.links.LinkResource;
25  import org.jboss.resteasy.links.LinkResources;
26  import org.jboss.resteasy.links.RESTServiceDiscovery;
27  import org.jboss.resteasy.links.impl.RESTUtils;
28  import org.jboss.resteasy.spi.Registry;
29  import org.jboss.resteasy.spi.ResteasyProviderFactory;
30  
31  import de.smartics.resteasy.hypermedia.resources.Resources;
32  
33  /**
34   * A brute force adapter to access the information of {@link RESTUtils}.
35   */
36  public final class RestEasyResourceDiscovery
37  {
38    // ********************************* Fields *********************************
39  
40    // --- constants ------------------------------------------------------------
41  
42    // --- members --------------------------------------------------------------
43  
44    /**
45     * Controls whether (<code>true</code>) or not (<code>false</code>) encoded
46     * slashes in the URL paths should be unencoded.
47     */
48    private static boolean unencodeSlashInPath;
49  
50    // ****************************** Initializer *******************************
51  
52    // ****************************** Constructors ******************************
53  
54    private RestEasyResourceDiscovery()
55    {
56    }
57  
58    // ****************************** Inner Classes *****************************
59  
60    // ********************************* Methods ********************************
61  
62    // --- init -----------------------------------------------------------------
63  
64    // --- get&set --------------------------------------------------------------
65  
66    /**
67     * Returns the flag that controls whether (<code>true</code>) or not (
68     * <code>false</code>) encoded slashes in the URL paths should be unencoded.
69     *
70     * @return the value of the flag.
71     */
72    public static boolean isUnencodeSlashInPath()
73    {
74      return unencodeSlashInPath;
75    }
76  
77    /**
78     * Sets the flag that controls whether (<code>true</code>) or not (
79     * <code>false</code>) encoded slashes in the URL paths should be unencoded.
80     *
81     * @param unencodeSlashInPath the value of the flag.
82     */
83    public static void setUnencodeSlashInPath(final boolean unencodeSlashInPath)
84    {
85      RestEasyResourceDiscovery.unencodeSlashInPath = unencodeSlashInPath;
86    }
87  
88    // --- business -------------------------------------------------------------
89  
90    /**
91     * Calculates the service discovery.
92     *
93     * @param entity the resource to analyze for link information.
94     * @param uriInfo the helper to construct links.
95     * @return the service discovery.
96     * @throws IllegalStateException if the method is unable to interface with a
97     *           private method of {@link RESTUtils}.
98     */
99    public static Resources createDiscovery(final Object entity,
100       final UriInfo uriInfo) throws IllegalStateException
101   {
102     try
103     {
104       final ResourceMethodRegistry registry =
105           (ResourceMethodRegistry) ResteasyProviderFactory
106               .getContextData(Registry.class);
107 
108       final List<Method> methods = RESTUtils.getServiceMethods(registry);
109       final DiscoveredResourceRepository discovery =
110           new DiscoveredResourceRepository();
111       discovery.setUnencodeSlashInPath(unencodeSlashInPath);
112       final Method processMethod = calcProcessMethod();
113       for (final Method method : methods)
114       {
115         if (method.isAnnotationPresent(LinkResource.class)
116             || method.isAnnotationPresent(LinkResources.class))
117         {
118           processMethod.invoke(RESTUtils.class, method, entity, uriInfo,
119               discovery);
120         }
121       }
122       return discovery;
123     }
124     catch (final Exception e)
125     {
126       throw new IllegalStateException(
127           "Cannot invoke method to create REST service discovery.", e);
128     }
129   }
130 
131   private static Method calcProcessMethod() throws IllegalStateException
132   {
133     final String methodName = "processLinkResources";
134     try
135     {
136       final Method method =
137           RESTUtils.class.getDeclaredMethod(methodName, Method.class,
138               Object.class, UriInfo.class, RESTServiceDiscovery.class);
139       method.setAccessible(true);
140       return method;
141     }
142     catch (final Exception e)
143     {
144       throw new IllegalStateException(String.format(
145           "Cannot access method '%s'.", methodName), e);
146     }
147   }
148 
149   // --- object basics --------------------------------------------------------
150 
151 }