001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.remoteable; 014 015import static org.apache.juneau.internal.ClassUtils.*; 016import static org.apache.juneau.internal.StringUtils.*; 017 018import java.lang.annotation.*; 019import java.lang.reflect.*; 020import java.util.*; 021 022/** 023 * @deprecated Internal class. 024 */ 025@Deprecated 026public class RemoteableMethodMeta { 027 028 private final String httpMethod; 029 private final String url; 030 private final RemoteMethodArg[] pathArgs, queryArgs, headerArgs, formDataArgs, requestBeanArgs; 031 private final Integer[] otherArgs; 032 private final Integer bodyArg; 033 private final ReturnValue returnValue; 034 035 /** 036 * Constructor. 037 * 038 * @param restUrl The absolute URL of the REST interface backing the interface proxy. 039 * @param m The Java method. 040 */ 041 public RemoteableMethodMeta(final String restUrl, Method m) { 042 Builder b = new Builder(restUrl, m); 043 this.httpMethod = b.httpMethod; 044 this.url = b.url; 045 this.pathArgs = b.pathArgs.toArray(new RemoteMethodArg[b.pathArgs.size()]); 046 this.queryArgs = b.queryArgs.toArray(new RemoteMethodArg[b.queryArgs.size()]); 047 this.formDataArgs = b.formDataArgs.toArray(new RemoteMethodArg[b.formDataArgs.size()]); 048 this.headerArgs = b.headerArgs.toArray(new RemoteMethodArg[b.headerArgs.size()]); 049 this.requestBeanArgs = b.requestBeanArgs.toArray(new RemoteMethodArg[b.requestBeanArgs.size()]); 050 this.otherArgs = b.otherArgs.toArray(new Integer[b.otherArgs.size()]); 051 this.bodyArg = b.bodyArg; 052 this.returnValue = b.returnValue; 053 } 054 055 private static final class Builder { 056 String httpMethod, url; 057 List<RemoteMethodArg> 058 pathArgs = new LinkedList<>(), 059 queryArgs = new LinkedList<>(), 060 headerArgs = new LinkedList<>(), 061 formDataArgs = new LinkedList<>(), 062 requestBeanArgs = new LinkedList<>(); 063 List<Integer> 064 otherArgs = new LinkedList<>(); 065 Integer bodyArg; 066 ReturnValue returnValue; 067 068 Builder(String restUrl, Method m) { 069 Remoteable r = m.getDeclaringClass().getAnnotation(Remoteable.class); 070 RemoteMethod rm = m.getAnnotation(RemoteMethod.class); 071 072 httpMethod = rm == null ? "POST" : rm.httpMethod(); 073 if (! isOneOf(httpMethod, "DELETE", "GET", "POST", "PUT")) 074 throw new RemoteableMetadataException(m, 075 "Invalid value specified for @RemoteMethod.httpMethod() annotation. Valid values are [DELTE,GET,POST,PUT]."); 076 077 String path = rm == null || rm.path().isEmpty() ? null : rm.path(); 078 String methodPaths = r == null ? "NAME" : r.methodPaths(); 079 080 if (! isOneOf(methodPaths, "NAME", "SIGNATURE")) 081 throw new RemoteableMetadataException(m, 082 "Invalid value specified for @Remoteable.methodPaths() annotation. Valid values are [NAME,SIGNATURE]."); 083 084 returnValue = rm == null ? ReturnValue.BODY : rm.returns(); 085 086 url = 087 trimSlashes(restUrl) 088 + '/' 089 + (path != null ? trimSlashes(path) : urlEncode("NAME".equals(methodPaths) ? m.getName() : getMethodSignature(m))); 090 091 int index = 0; 092 for (Annotation[] aa : m.getParameterAnnotations()) { 093 boolean annotated = false; 094 for (Annotation a : aa) { 095 Class<?> ca = a.annotationType(); 096 if (ca == Path.class) { 097 Path p = (Path)a; 098 annotated = pathArgs.add(new RemoteMethodArg(p.name(), p.value(), index, false, p.serializer())); 099 } else if (ca == Query.class) { 100 Query q = (Query)a; 101 annotated = queryArgs.add(new RemoteMethodArg(q.name(), q.value(), index, q.skipIfEmpty(), q.serializer())); 102 } else if (ca == QueryIfNE.class) { 103 QueryIfNE q = (QueryIfNE)a; 104 annotated = queryArgs.add(new RemoteMethodArg(q.name(), q.value(), index, true, q.serializer())); 105 } else if (ca == FormData.class) { 106 FormData f = (FormData)a; 107 annotated = formDataArgs.add(new RemoteMethodArg(f.name(), f.value(), index, f.skipIfEmpty(), f.serializer())); 108 } else if (ca == FormDataIfNE.class) { 109 FormDataIfNE f = (FormDataIfNE)a; 110 annotated = formDataArgs.add(new RemoteMethodArg(f.name(), f.value(), index, true, f.serializer())); 111 } else if (ca == Header.class) { 112 Header h = (Header)a; 113 annotated = headerArgs.add(new RemoteMethodArg(h.name(), h.value(), index, h.skipIfEmpty(), h.serializer())); 114 } else if (ca == HeaderIfNE.class) { 115 HeaderIfNE h = (HeaderIfNE)a; 116 annotated = headerArgs.add(new RemoteMethodArg(h.name(), h.value(), index, true, h.serializer())); 117 } else if (ca == RequestBean.class) { 118 RequestBean rb = (RequestBean)a; 119 annotated = requestBeanArgs.add(new RemoteMethodArg("", "", index, false, rb.serializer())); 120 } else if (ca == Body.class) { 121 annotated = true; 122 if (bodyArg == null) 123 bodyArg = index; 124 else 125 throw new RemoteableMetadataException(m, 126 "Multiple @Body parameters found. Only one can be specified per Java method."); 127 } 128 } 129 if (! annotated) 130 otherArgs.add(index); 131 index++; 132 } 133 134 if (bodyArg != null && otherArgs.size() > 0) 135 throw new RemoteableMetadataException(m, 136 "@Body and non-annotated parameters found together. Non-annotated parameters cannot be used when @Body is used."); 137 } 138 } 139 140 /** 141 * Returns the value of the {@link RemoteMethod#httpMethod() @RemoteMethod.httpMethod()} annotation on this Java method. 142 * 143 * @return The value of the annotation, never <jk>null</jk>. 144 */ 145 public String getHttpMethod() { 146 return httpMethod; 147 } 148 149 /** 150 * Returns the absolute URL of the REST interface invoked by this Java method. 151 * 152 * @return The absolute URL of the REST interface, never <jk>null</jk>. 153 */ 154 public String getUrl() { 155 return url; 156 } 157 158 /** 159 * Returns the {@link Path @Path} annotated arguments on this Java method. 160 * 161 * @return A map of {@link Path#value() @Path.value()} names to zero-indexed argument indices. 162 */ 163 public RemoteMethodArg[] getPathArgs() { 164 return pathArgs; 165 } 166 167 /** 168 * Returns the {@link Query @Query} annotated arguments on this Java method. 169 * 170 * @return A map of {@link Query#value() @Query.value()} names to zero-indexed argument indices. 171 */ 172 public RemoteMethodArg[] getQueryArgs() { 173 return queryArgs; 174 } 175 176 /** 177 * Returns the {@link FormData @FormData} annotated arguments on this Java method. 178 * 179 * @return A map of {@link FormData#value() @FormData.value()} names to zero-indexed argument indices. 180 */ 181 public RemoteMethodArg[] getFormDataArgs() { 182 return formDataArgs; 183 } 184 185 /** 186 * Returns the {@link Header @Header} annotated arguments on this Java method. 187 * 188 * @return A map of {@link Header#value() @Header.value()} names to zero-indexed argument indices. 189 */ 190 public RemoteMethodArg[] getHeaderArgs() { 191 return headerArgs; 192 } 193 194 /** 195 * Returns the {@link RequestBean @RequestBean} annotated arguments on this Java method. 196 * 197 * @return A list of zero-indexed argument indices. 198 */ 199 public RemoteMethodArg[] getRequestBeanArgs() { 200 return requestBeanArgs; 201 } 202 203 /** 204 * Returns the remaining non-annotated arguments on this Java method. 205 * 206 * @return A list of zero-indexed argument indices. 207 */ 208 public Integer[] getOtherArgs() { 209 return otherArgs; 210 } 211 212 /** 213 * Returns the argument annotated with {@link Body @Body}. 214 * 215 * @return A index of the argument with the {@link Body @Body} annotation, or <jk>null</jk> if no argument exists. 216 */ 217 public Integer getBodyArg() { 218 return bodyArg; 219 } 220 221 /** 222 * Returns whether the method returns the HTTP response body or status code. 223 * 224 * @return Whether the method returns the HTTP response body or status code. 225 */ 226 public ReturnValue getReturns() { 227 return returnValue; 228 } 229}