1 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 ; 42 import java.lang.annotation.Annotation ; 43 import java.lang.reflect.InvocationHandler ; 44 import java.lang.reflect.Method ; 45 import java.net.HttpURLConnection ; 46 import java.net.URL ; 47 import java.net.URLConnection ; 48 import java.util.ArrayList ; 49 import java.util.HashMap ; 50 import java.util.logging.Logger ; 51 52 public class RestProxy implements InvocationHandler { 53 private static final Logger log = Logger.getLogger(RestProxy.class.getName()); 54 55 private Class _api; 56 private RestEncoding _defaultRestEncoding = RestEncoding.QUERY; 57 private String _url; 58 private JAXBContext _context; 59 60 public RestProxy(Class api, String url) 61 throws JAXBException 62 { 63 init(api, url); 64 65 ArrayList <Class > classList = new ArrayList <Class >(); 66 JAXBUtil.introspectClass(_api, classList); 67 68 _context = JAXBContext.newInstance(classList.toArray(new Class [0])); 69 } 70 71 public RestProxy(Class api, String url, Class [] jaxbClasses) 72 throws JAXBException 73 { 74 init(api, url); 75 76 _context = JAXBContext.newInstance(jaxbClasses); 77 } 78 79 public RestProxy(Class api, String url, String jaxbPackages) 80 throws JAXBException 81 { 82 init(api, url); 83 84 _context = JAXBContext.newInstance(jaxbPackages); 85 } 86 87 private void init(Class api, String 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 invoke(Object proxy, Method method, Object [] args) 101 throws Throwable 102 { 103 String 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 String 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 144 StringBuilder urlBuilder = new StringBuilder (_url); 145 StringBuilder queryBuilder = new StringBuilder (); 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 <Object > postValues = new ArrayList <Object >(); 162 HashMap <String ,String > headers = new HashMap <String ,String >(); 163 164 if (args != null) { 165 Class [] parameterTypes = method.getParameterTypes(); 166 Annotation [][] annotations = method.getParameterAnnotations(); 167 168 for (int i = 0; i < parameterTypes.length; i++) { 169 RestParam.Source source = RestParam.Source.QUERY; 170 String 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 url = new URL (urlBuilder.toString()); 214 URLConnection connection = url.openConnection(); 215 216 if (connection instanceof HttpURLConnection ) { 217 HttpURLConnection httpConnection = (HttpURLConnection ) 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 out = httpConnection.getOutputStream(); 227 228 Marshaller marshaller = _context.createMarshaller(); 229 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, 230 Boolean.TRUE); 231 232 for (Object 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 |