KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > soa > rest > RestProxy


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Emil Ong
28  */

29
30 package com.caucho.soa.rest;
31
32 import com.caucho.jaxb.JAXBUtil;
33 import com.caucho.util.URLUtil;
34
35 import javax.jws.WebMethod;
36 import javax.jws.WebParam;
37 import javax.xml.bind.JAXBContext;
38 import javax.xml.bind.JAXBException;
39 import javax.xml.bind.Marshaller;
40 import javax.xml.bind.Unmarshaller;
41 import java.io.OutputStream JavaDoc;
42 import java.lang.annotation.Annotation JavaDoc;
43 import java.lang.reflect.InvocationHandler JavaDoc;
44 import java.lang.reflect.Method JavaDoc;
45 import java.net.HttpURLConnection JavaDoc;
46 import java.net.URL JavaDoc;
47 import java.net.URLConnection JavaDoc;
48 import java.util.ArrayList JavaDoc;
49 import java.util.HashMap JavaDoc;
50 import java.util.logging.Logger JavaDoc;
51
52 public class RestProxy implements InvocationHandler JavaDoc {
53   private static final Logger JavaDoc log = Logger.getLogger(RestProxy.class.getName());
54
55   private Class JavaDoc _api;
56   private RestEncoding _defaultRestEncoding = RestEncoding.QUERY;
57   private String JavaDoc _url;
58   private JAXBContext _context;
59
60   public RestProxy(Class JavaDoc api, String JavaDoc url)
61     throws JAXBException
62   {
63     init(api, url);
64
65     ArrayList JavaDoc<Class JavaDoc> classList = new ArrayList JavaDoc<Class JavaDoc>();
66     JAXBUtil.introspectClass(_api, classList);
67
68     _context = JAXBContext.newInstance(classList.toArray(new Class JavaDoc[0]));
69   }
70
71   public RestProxy(Class JavaDoc api, String JavaDoc url, Class JavaDoc[] jaxbClasses)
72     throws JAXBException
73   {
74     init(api, url);
75
76     _context = JAXBContext.newInstance(jaxbClasses);
77   }
78
79   public RestProxy(Class JavaDoc api, String JavaDoc url, String JavaDoc jaxbPackages)
80     throws JAXBException
81   {
82     init(api, url);
83
84     _context = JAXBContext.newInstance(jaxbPackages);
85   }
86
87   private void init(Class JavaDoc api, String JavaDoc url)
88   {
89     _api = api;
90     _url = url;
91
92     if (_api.isAnnotationPresent(RestService.class)) {
93       RestService restService =
94         (RestService) _api.getAnnotation(RestService.class);
95
96       _defaultRestEncoding = restService.encoding();
97     }
98   }
99
100   public Object JavaDoc invoke(Object JavaDoc proxy, Method method, Object JavaDoc[] args)
101     throws Throwable JavaDoc
102   {
103     String JavaDoc httpMethod = "GET";
104
105     if (method.isAnnotationPresent(Delete.class))
106       httpMethod = "DELETE";
107
108     if (method.isAnnotationPresent(Get.class))
109       httpMethod = "GET";
110
111     if (method.isAnnotationPresent(Post.class))
112       httpMethod = "POST";
113
114     if (method.isAnnotationPresent(Put.class))
115       httpMethod = "PUT";
116
117     if (method.isAnnotationPresent(Head.class))
118       httpMethod = "HEAD";
119
120     // Check annotations
121
String JavaDoc methodName = method.getName();
122     RestEncoding restEncoding = _defaultRestEncoding;
123
124     if (method.isAnnotationPresent(WebMethod.class)) {
125       WebMethod webMethod = (WebMethod) method.getAnnotation(WebMethod.class);
126
127       if (webMethod.operationName().length() > 0)
128         methodName = webMethod.operationName();
129     }
130
131     if (method.isAnnotationPresent(RestMethod.class)) {
132       RestMethod restMethod =
133         (RestMethod) method.getAnnotation(RestMethod.class);
134
135       if (restMethod.operationName().length() > 0)
136         methodName = restMethod.operationName();
137
138       if (restMethod.encoding() != RestEncoding.UNSET)
139         restEncoding = restMethod.encoding();
140     }
141
142     // Build the url
143

144     StringBuilder JavaDoc urlBuilder = new StringBuilder JavaDoc(_url);
145     StringBuilder JavaDoc queryBuilder = new StringBuilder JavaDoc();
146     
147     switch (restEncoding) {
148       case PATH:
149         if (! _url.endsWith("/"))
150           urlBuilder.append("/");
151
152         urlBuilder.append(methodName);
153         urlBuilder.append("/");
154         break;
155       case QUERY:
156         queryBuilder.append("method=");
157         queryBuilder.append(methodName);
158         break;
159     }
160
161     ArrayList JavaDoc<Object JavaDoc> postValues = new ArrayList JavaDoc<Object JavaDoc>();
162     HashMap JavaDoc<String JavaDoc,String JavaDoc> headers = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
163
164     if (args != null) {
165       Class JavaDoc[] parameterTypes = method.getParameterTypes();
166       Annotation JavaDoc[][] annotations = method.getParameterAnnotations();
167
168       for (int i = 0; i < parameterTypes.length; i++) {
169         RestParam.Source source = RestParam.Source.QUERY;
170         String JavaDoc key = "arg" + i;
171
172         for (int j = 0; j < annotations[i].length; j++) {
173           if (annotations[i][j].annotationType().equals(RestParam.class)) {
174             RestParam restParam = (RestParam) annotations[i][j];
175             source = restParam.source();
176           }
177           else if (annotations[i][j].annotationType().equals(WebParam.class)) {
178             WebParam webParam = (WebParam) annotations[i][j];
179
180             if (! "".equals(webParam.name()))
181               key = webParam.name();
182           }
183         }
184
185         switch (source) {
186           case PATH:
187             urlBuilder.append(URLUtil.encodeURL(args[i].toString()));
188             urlBuilder.append('/');
189             break;
190           case QUERY:
191             if (queryBuilder.length() > 0)
192               queryBuilder.append('&');
193
194             queryBuilder.append(URLUtil.encodeURL(key));
195             queryBuilder.append('=');
196             queryBuilder.append(URLUtil.encodeURL(args[i].toString()));
197             break;
198           case POST:
199             postValues.add(args[i]);
200             break;
201           case HEADER:
202             headers.put(key, args[i].toString());
203             break;
204         }
205       }
206     }
207
208     if (queryBuilder.length() > 0) {
209       urlBuilder.append('?');
210       urlBuilder.append(queryBuilder);
211     }
212
213     URL JavaDoc url = new URL JavaDoc(urlBuilder.toString());
214     URLConnection JavaDoc connection = url.openConnection();
215
216     if (connection instanceof HttpURLConnection JavaDoc) {
217       HttpURLConnection JavaDoc httpConnection = (HttpURLConnection JavaDoc) connection;
218
219       try {
220     httpConnection.setRequestMethod(httpMethod);
221     httpConnection.setDoInput(true);
222
223     if (postValues.size() > 0) {
224       httpConnection.setDoOutput(true);
225
226       OutputStream JavaDoc out = httpConnection.getOutputStream();
227
228       Marshaller marshaller = _context.createMarshaller();
229       marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
230                  Boolean.TRUE);
231
232       for (Object JavaDoc postValue : postValues)
233         marshaller.marshal(postValue, out);
234
235       out.flush();
236     }
237
238     int code = httpConnection.getResponseCode();
239
240     if (code == 200) {
241       if (method.getReturnType() == null)
242         return null;
243
244       Unmarshaller unmarshaller = _context.createUnmarshaller();
245
246       return unmarshaller.unmarshal(httpConnection.getInputStream());
247     }
248     else {
249       log.info("request failed: " + httpConnection.getResponseMessage());
250     
251       throw new RestException(httpConnection.getResponseMessage());
252     }
253       } finally {
254     httpConnection.disconnect();
255       }
256     }
257     else
258       throw new RestException();
259   }
260 }
261
Popular Tags