| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.websvc.rest.client; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import javax.lang.model.element.Modifier; |
| |
| import org.netbeans.api.java.source.TreeMaker; |
| import org.netbeans.api.java.source.WorkingCopy; |
| import org.netbeans.modules.websvc.rest.client.ClientJavaSourceHelper.HttpMimeType; |
| import org.netbeans.modules.websvc.rest.client.ClientJavaSourceHelper.PathFormat; |
| import org.netbeans.modules.websvc.rest.client.Wadl2JavaHelper.Pair; |
| import org.netbeans.modules.websvc.rest.model.api.HttpMethod; |
| import org.netbeans.modules.websvc.rest.model.api.RestConstants; |
| import org.netbeans.modules.websvc.saas.model.WadlSaasMethod; |
| import org.netbeans.modules.websvc.saas.model.oauth.Metadata; |
| import org.netbeans.modules.websvc.saas.model.wadl.Method; |
| import org.netbeans.modules.websvc.saas.model.wadl.Representation; |
| import org.netbeans.modules.websvc.saas.model.wadl.Request; |
| import org.netbeans.modules.websvc.saas.model.wadl.Response; |
| import org.openide.nodes.Node; |
| |
| import com.sun.source.tree.ClassTree; |
| import com.sun.source.tree.ExpressionTree; |
| import com.sun.source.tree.MethodTree; |
| import com.sun.source.tree.ModifiersTree; |
| import com.sun.source.tree.Tree; |
| import com.sun.source.tree.TypeParameterTree; |
| import com.sun.source.tree.VariableTree; |
| |
| |
| /** |
| * @author ads |
| * |
| */ |
| abstract class ClientGenerationStrategy { |
| |
| private static final String SIGN_PARAMS_METHOD="signParams"; //NOI18N |
| |
| abstract ClassTree generateFields(TreeMaker maker, WorkingCopy copy,ClassTree classTree, |
| String resourceURI,Security security); |
| |
| abstract MethodTree generateConstructor(TreeMaker maker, WorkingCopy copy, |
| ClassTree classTree, PathFormat pf, Security security); |
| |
| abstract MethodTree generateSubresourceMethod(TreeMaker maker, WorkingCopy copy, |
| ClassTree classTree,PathFormat pf); |
| |
| abstract MethodTree generateClose(TreeMaker maker, WorkingCopy copy); |
| |
| abstract MethodTree generateBasicAuth(TreeMaker maker, WorkingCopy copy , |
| List<VariableTree> authParams) ; |
| |
| abstract MethodTree generateHttpPOSTMethod( WorkingCopy copy, |
| HttpMethod httpMethod, HttpMimeType mimeType, |
| boolean multipleMimeTypes ); |
| |
| abstract Collection<? extends MethodTree> generateHttpGETMethod( |
| WorkingCopy copy, HttpMethod httpMethod, HttpMimeType mimeType, |
| boolean multipleMimeTypes ); |
| |
| abstract MethodTree generateHttpGETMethod( WorkingCopy copy, |
| WadlSaasMethod saasMethod, HttpMimeType mimeType, |
| boolean multipleMimeTypes, HttpParams httpParams, Security security); |
| |
| abstract MethodTree generateHttpPOSTMethod( WorkingCopy copy, |
| WadlSaasMethod saasMethod, HttpMimeType mimeType, |
| boolean multipleMimeTypes, HttpParams httpParams, Security security ); |
| |
| abstract MethodTree generateFormMethod(TreeMaker maker, WorkingCopy copy); |
| |
| abstract MethodTree generateOptionalFormMethod(TreeMaker maker , WorkingCopy copy ); |
| |
| abstract ClassTree generateOAuthMethods( String projectType, |
| WorkingCopy copy, ClassTree modifiedClass, Metadata oauthMetadata ); |
| |
| /** |
| * @return true if generation requires Jersey specific classes for specified method arguments. |
| */ |
| abstract boolean requiresJersey(Node context, Security security); |
| |
| List<MethodTree> generateHttpMethods( WorkingCopy copy, |
| HttpMethod httpMethod ) |
| { |
| List<MethodTree> httpMethods = new ArrayList<MethodTree>(); |
| String method = httpMethod.getType(); |
| if (RestConstants.GET_ANNOTATION.equals(method)) { // GET |
| boolean found = false; |
| String produces = httpMethod.getProduceMime(); |
| if (produces.length() > 0) { |
| boolean multipleMimeTypes = produces.contains(","); // NOI18N |
| for (HttpMimeType mimeType : HttpMimeType.values()) { |
| if (produces.contains(mimeType.getMimeType())) { |
| httpMethods.addAll(generateHttpGETMethod(copy, |
| httpMethod, mimeType, multipleMimeTypes)); |
| found = true; |
| } |
| } |
| } |
| if (!found) { |
| httpMethods.addAll(generateHttpGETMethod(copy, httpMethod, null, |
| false)); |
| } |
| } |
| else if (RestConstants.PUT_ANNOTATION.equals(method) |
| || RestConstants.POST_ANNOTATION.equals(method) |
| || RestConstants.DELETE_ANNOTATION.equals(method)) |
| { |
| boolean found = false; |
| String consumes = httpMethod.getConsumeMime(); |
| if (consumes.length() > 0) { // NOI18N |
| boolean multipleMimeTypes = consumes.contains(","); // NOI18N |
| for (HttpMimeType mimeType : HttpMimeType.values()) { |
| if (consumes.contains(mimeType.getMimeType())) { |
| httpMethods.add(generateHttpPOSTMethod(copy, httpMethod, |
| mimeType, multipleMimeTypes)); |
| found = true; |
| } |
| } |
| } |
| if (!found) { |
| httpMethods.add(generateHttpPOSTMethod(copy, httpMethod, null, |
| false)); |
| } |
| } |
| |
| return httpMethods; |
| } |
| |
| MethodTree generateConstructorAuthBasic(TreeMaker maker) { |
| |
| ModifiersTree methodModifier = maker.Modifiers( |
| Collections.<Modifier>singleton(Modifier.PUBLIC)); |
| |
| List<VariableTree> paramList = new ArrayList<VariableTree>(); |
| |
| Tree argTypeTree = maker.Identifier("String"); //NOI18N |
| ModifiersTree fieldModifier = maker.Modifiers( |
| Collections.<Modifier>emptySet()); |
| VariableTree argFieldTree = maker.Variable(fieldModifier, |
| "username", argTypeTree, null); //NOI18N |
| paramList.add(argFieldTree); |
| argFieldTree = maker.Variable(fieldModifier, |
| "password", argTypeTree, null); //NOI18N |
| paramList.add(argFieldTree); |
| |
| |
| String body = |
| "{"+ |
| "this();" + |
| "setUsernamePassword(username, password);" + |
| "}"; //NOI18N |
| return maker.Constructor ( |
| methodModifier, |
| Collections.<TypeParameterTree>emptyList(), |
| paramList, |
| Collections.<ExpressionTree>emptyList(), |
| body); |
| |
| } |
| |
| List<MethodTree> generateHttpMethods( WorkingCopy copy, |
| WadlSaasMethod saasMethod, HttpParams httpParams, Security security ) |
| { |
| List<MethodTree> httpMethods = new ArrayList<MethodTree>(); |
| //String methodName = saasMethod.getName(); |
| Method wadlMethod = saasMethod.getWadlMethod(); |
| String methodType = wadlMethod.getName(); |
| //HeaderParamsInfo headerParamsInfo = new HeaderParamsInfo(saasMethod); |
| if (RestConstants.GET_ANNOTATION.equals(methodType)) { //GET |
| List<Representation> produces = new ArrayList<Representation>(); |
| for( Response wadlResponse : wadlMethod.getResponse() ) |
| if (wadlResponse != null) { |
| List<Representation> representations = wadlResponse.getRepresentation(); |
| produces.addAll(representations); |
| } |
| |
| boolean found = false; |
| boolean multipleMimeTypes = produces.size() > 1; |
| for (Representation prod : produces) { |
| String mediaType = prod.getMediaType(); |
| if (mediaType != null) { |
| for (HttpMimeType mimeType : HttpMimeType.values()) { |
| if (mediaType.equals(mimeType.getMimeType())) { |
| MethodTree method = generateHttpGETMethod(copy, |
| saasMethod, mimeType, multipleMimeTypes, |
| httpParams, security); |
| if (method != null) { |
| httpMethods.add(method); |
| } |
| found = true; |
| break; |
| } |
| } |
| } |
| } |
| if (!found) { |
| httpMethods.add(generateHttpGETMethod(copy, saasMethod, null, |
| false, httpParams, security)); |
| } |
| |
| } else if ( RestConstants.PUT_ANNOTATION.equals(methodType) || |
| RestConstants.POST_ANNOTATION.equals(methodType) || |
| RestConstants.DELETE_ANNOTATION.equals(methodType) |
| ) { |
| List<Representation> consumes = new ArrayList<Representation>(); |
| Request wadlRequest = wadlMethod.getRequest(); |
| if (wadlRequest != null) { |
| List<Representation> representationTypes = wadlRequest.getRepresentation(); |
| for (Representation reprType : representationTypes) { |
| consumes.add(reprType); |
| } |
| } |
| |
| boolean found = false; |
| boolean multipleMimeTypes = consumes.size() > 1; |
| for (Representation cons : consumes) { |
| String mediaType = cons.getMediaType(); |
| if (mediaType != null) { |
| for (HttpMimeType mimeType : HttpMimeType.values()) { |
| if (mediaType.equals(mimeType.getMimeType())) { |
| MethodTree method = generateHttpPOSTMethod(copy, |
| saasMethod, mimeType, multipleMimeTypes, |
| httpParams, security); |
| if (method != null) { |
| httpMethods.add(method); |
| } |
| found = true; |
| break; |
| } |
| } |
| } |
| } |
| if (!found) { |
| httpMethods.add(generateHttpPOSTMethod(copy, saasMethod, |
| null, false, httpParams, security)); |
| } |
| } |
| return httpMethods; |
| } |
| |
| protected abstract void buildQueryFormParams(StringBuilder queryString); |
| |
| protected abstract void buildQParams(StringBuilder queryString); |
| |
| protected String getPathExpression(PathFormat pf) { |
| String[] arguments = pf.getArguments(); |
| if (arguments.length == 0) { |
| return "\""+pf.getPattern()+"\""; //NOI18N |
| } else { |
| return "java.text.MessageFormat.format(\""+pf.getPattern()+ |
| "\", new Object[] {"+getArgumentList(arguments)+"})"; //NOI18N |
| } |
| } |
| |
| protected String getArgumentList(String[] arguments) { |
| if (arguments.length == 0) { |
| return ""; |
| } else { |
| StringBuilder buf = new StringBuilder(arguments[0]); |
| for (int i=1 ; i<arguments.length ; i++) { |
| buf.append(","+arguments[i]); |
| } |
| return buf.toString(); |
| } |
| } |
| |
| protected void buildQueryParams( StringBuilder body, HttpMethod httpMethod, |
| List<VariableTree> paramList , TreeMaker maker) |
| { |
| Map<String, String> queryParams = httpMethod.getQueryParams(); |
| if ( queryParams.size() == 0 ){ |
| return; |
| } |
| for (Entry<String, String> entry : queryParams.entrySet()) { |
| String paramName = entry.getKey(); |
| // default value is not needed in the client code |
| //String defaultValue = entry.getValue(); |
| if ( paramName == null ){ |
| continue; |
| } |
| String clientParam = getClientParamName( paramName , paramList ); |
| Tree typeTree = maker.Identifier("String"); //NOI18N |
| ModifiersTree fieldModifier = maker.Modifiers(Collections.<Modifier>emptySet()); |
| VariableTree fieldTree = maker.Variable(fieldModifier, clientParam, |
| typeTree, null); //NOI18N |
| paramList.add(fieldTree); |
| |
| body.append("if ("); //NOI18N |
| body.append(clientParam); |
| body.append("!=null){"); //NOI18N |
| body.append("resource = resource.queryParam(\""); //NOI18N |
| body.append(paramName); |
| body.append("\","); //NOI18N |
| body.append(clientParam); |
| body.append(");}"); //NOI18N |
| } |
| } |
| |
| protected String getClientParamName( String paramName, |
| List<VariableTree> paramList ) |
| { |
| return getClientParamName(paramName, paramList, 0); |
| } |
| |
| protected String getClientParamName( String paramName, |
| List<VariableTree> paramList , int index) |
| { |
| String result = paramName; |
| if ( index !=0 ){ |
| result = paramName +index; |
| } |
| for(VariableTree var: paramList ) { |
| String name = var.getName().toString(); |
| if ( name.equals( result)){ |
| return getClientParamName(paramName, paramList, index +1); |
| } |
| } |
| return result; |
| } |
| |
| protected void addQueryParams(TreeMaker maker, HttpParams httpParams, |
| Security security, List<VariableTree> paramList, |
| StringBuilder queryP, StringBuilder queryParamPart, |
| StringBuilder commentBuffer) |
| { |
| ModifiersTree paramModifier = maker.Modifiers(Collections.<Modifier>emptySet()); |
| SecurityParams securityParams = security.getSecurityParams(); |
| // adding form params |
| if (httpParams.hasFormParams()) { |
| for (String formParam : httpParams.getFormParams()) { |
| if (securityParams == null || |
| (!Wadl2JavaHelper.isSecurityParam(formParam, securityParams) |
| && !Wadl2JavaHelper.isSignatureParam(formParam, securityParams))) |
| { |
| String javaIdentifier = Wadl2JavaHelper.makeJavaIdentifier(formParam); |
| VariableTree paramTree = maker.Variable(paramModifier, |
| javaIdentifier, maker.Identifier("String"), null); //NOI18N |
| paramList.add(paramTree); |
| commentBuffer.append("@param "+javaIdentifier+" form parameter\n"); //NOI18N |
| } |
| } |
| Pair<String> paramPair = null; |
| if (securityParams != null) { |
| paramPair = Wadl2JavaHelper.getParamList(httpParams.getFormParams(), |
| httpParams.getFixedFormParams(), securityParams); |
| } else { |
| paramPair = Wadl2JavaHelper.getParamList(httpParams.getFormParams(), |
| httpParams.getFixedFormParams()); |
| } |
| queryParamPart.append("String[] formParamNames = new String[] {"+ |
| paramPair.getKey()+"};"); //NOI18N |
| queryParamPart.append("String[] formParamValues = new String[] {"+ |
| paramPair.getValue()+"};"); //NOI18N |
| } |
| // add query params |
| if (httpParams.hasQueryParams()) { |
| if (httpParams.hasRequiredQueryParams()) { |
| // adding method parameters |
| for (String requiredParam : httpParams.getRequiredQueryParams()) { |
| if (securityParams == null || |
| (!Wadl2JavaHelper.isSecurityParam(requiredParam, securityParams) && |
| !Wadl2JavaHelper.isSignatureParam(requiredParam, securityParams))) |
| { |
| String javaIdentifier = |
| Wadl2JavaHelper.makeJavaIdentifier(requiredParam); |
| VariableTree paramTree = maker.Variable(paramModifier, |
| javaIdentifier, maker.Identifier("String"), null); //NOI18N |
| paramList.add(paramTree); |
| commentBuffer.append("@param "+javaIdentifier+ |
| " query parameter[REQUIRED]\n"); //NOI18N |
| } |
| } |
| // adding query params calculation to metthod body |
| if (httpParams.hasMultipleParamsInList()) { |
| Pair<String> paramPair = null; |
| if (securityParams != null) { |
| paramPair = Wadl2JavaHelper.getParamList( |
| httpParams.getRequiredQueryParams(), |
| httpParams.getFixedQueryParams(), securityParams); |
| } else { |
| paramPair = Wadl2JavaHelper.getParamList( |
| httpParams.getRequiredQueryParams(), |
| httpParams.getFixedQueryParams()); |
| } |
| queryParamPart.append("String[] queryParamNames = new String[] {"+ |
| paramPair.getKey()+"};"); //NOI18N |
| queryParamPart.append("String[] queryParamValues = new String[] {"+ |
| paramPair.getValue()+"};"); //NOI18N |
| if (Security.Authentication.SESSION_KEY == |
| security.getAuthentication() && securityParams != null) |
| { |
| String optParams = ""; //NOI18N |
| if (httpParams.hasOptionalQueryParams()) { |
| optParams = ", optionalQueryParams"; |
| } |
| queryParamPart.append("String signature = "+ |
| SIGN_PARAMS_METHOD+ |
| "(queryParamNames, queryParamValues"+optParams+ |
| ");"); //NOI18N |
| String sigParam = securityParams.getSignature(); |
| queryP.append(".queryParam(\""+ |
| sigParam+"\", signature)"); //NOI18N |
| buildQueryFormParams(queryP); |
| } else { |
| buildQueryFormParams(queryP); |
| } |
| } else { |
| List<String> requiredParams = httpParams.getRequiredQueryParams(); |
| if (requiredParams.size() > 0) { |
| String paramName = requiredParams.get(0); |
| String paramValue = Wadl2JavaHelper.makeJavaIdentifier( |
| requiredParams.get(0)); |
| if (Security.Authentication.SESSION_KEY == |
| security.getAuthentication() && |
| securityParams != null && httpParams.hasFormParams()) |
| { |
| String optParams = ""; //NOI18N |
| if (httpParams.hasOptionalQueryParams()) { |
| optParams = ", optionalQueryParams"; |
| } |
| queryParamPart.append("String signature = "+ |
| SIGN_PARAMS_METHOD+ |
| "(formParamNames, formParamValues"+optParams+");"); //NOI18N |
| String sigParam = securityParams.getSignature(); |
| queryP.append(".queryParam(\""+sigParam+"\", signature)"); //NOI18N |
| } else { |
| queryP.append(".queryParam(\""+paramName+"\","+paramValue+")"); //NOI18N |
| } |
| } else { |
| Map<String, String> fixedParams = httpParams.getFixedQueryParams(); |
| for(Entry<String, String> entry: fixedParams.entrySet()) { |
| String paramName = entry.getKey(); |
| String paramValue = entry.getValue(); |
| queryP.append(".queryParam(\""+paramName+"\",\""+paramValue+"\")"); //NOI18N" |
| } |
| } |
| } |
| } else if (httpParams.hasOptionalQueryParams()) { |
| // optional params should be listed also when there are no required params |
| for (String optionalParam : httpParams.getOptionalQueryParams()) { |
| String javaIdentifier = Wadl2JavaHelper.makeJavaIdentifier( |
| optionalParam); |
| VariableTree paramTree = maker.Variable(paramModifier, |
| javaIdentifier, maker.Identifier("String"), null); //NOI18N |
| paramList.add(paramTree); |
| commentBuffer.append("@param "+javaIdentifier+" query parameter\n"); //NOI18N |
| } |
| // there are no fixed params in this case |
| Pair<String> paramPair = Wadl2JavaHelper.getParamList( |
| httpParams.getOptionalQueryParams(), |
| Collections.<String, String>emptyMap()); |
| queryParamPart.append("String[] queryParamNames = new String[] {"+ |
| paramPair.getKey()+"};"); //NOI18N |
| queryParamPart.append("String[] queryParamValues = new String[] {"+ |
| paramPair.getValue()+"};"); //NOI18N |
| buildQueryFormParams(queryP); |
| } |
| |
| // add optional params (only when there are also some required params) |
| if ((httpParams.hasOptionalQueryParams() && httpParams.hasRequiredQueryParams()) || |
| httpParams.hasDefaultQueryParams()) |
| { |
| VariableTree paramTree = maker.Variable(paramModifier, |
| "optionalQueryParams", maker.Identifier("String..."), null); //NOI18N |
| paramList.add(paramTree); |
| |
| commentBuffer.append("@param optionalQueryParams List of optional query parameters in the form of \"param_name=param_value\",...<br>\nList of optional query parameters:\n"); //NOI18N |
| for (String otherParam : httpParams.getOptionalQueryParams()) { |
| commentBuffer.append("<LI>"+otherParam+" [OPTIONAL]\n"); //NOI18N |
| } |
| // add default params |
| Map<String,String> defaultParams = httpParams.getDefaultQueryParams(); |
| for (String key : defaultParams.keySet()) { |
| commentBuffer.append("<LI>"+key+" [OPTIONAL, DEFAULT VALUE: \""+ |
| defaultParams.get(key)+"\"]\n"); //NOI18N |
| } |
| buildQParams(queryP); |
| } |
| } |
| } |
| |
| protected void addHeaderParams( TreeMaker maker, HttpParams httpParams, |
| List<VariableTree> paramList, StringBuilder queryP, |
| StringBuilder commentBuffer ) |
| { |
| ModifiersTree paramModifier = maker.Modifiers(Collections.<Modifier>emptySet()); |
| // add header params |
| if (httpParams.hasHeaderParams()) { |
| for (String headerParam : httpParams.getHeaderParams()) { |
| String javaIdentifier = Wadl2JavaHelper.makeJavaIdentifier(headerParam); |
| VariableTree paramTree = maker.Variable(paramModifier, |
| javaIdentifier, maker.Identifier("String"), null); //NOI18N |
| paramList.add(paramTree); |
| commentBuffer.append("@param "+javaIdentifier+" header parameter[REQUIRED]\n"); //NOI18N |
| queryP.append(".header(\""+headerParam+"\","+javaIdentifier+")"); //NOI18N |
| } |
| Map<String, String> fixedHeaderParams = httpParams.getFixedHeaderParams(); |
| for (String paramName : fixedHeaderParams.keySet()) { |
| String paramValue = fixedHeaderParams.get(paramName); |
| queryP.append(".header(\""+paramName+"\",\""+paramValue+"\")"); //NOI18N |
| } |
| } |
| } |
| |
| |
| static PathFormat getPathFormat(String path) { |
| String p = normalizePath(path); //NOI18N |
| PathFormat pathFormat = new PathFormat(); |
| StringBuilder buf = new StringBuilder(); |
| List<String> arguments = new ArrayList<String>(); |
| for (int i=0 ; i<p.length() ; i++) { |
| char ch = p.charAt(i); |
| if (ch == '{') { //NOI18N |
| int j=i+1; |
| while (j<p.length() && p.charAt(j) != '}') { //NOI18N |
| j++; |
| } |
| String arg = p.substring(i+1,j); |
| int index = arg.indexOf(':'); |
| if ( index > -1){ |
| arg = arg.substring(0, index); |
| } |
| buf.append("{"+arguments.size()+"}"); //NOI18N |
| arguments.add(arg); |
| i = j; |
| } else { |
| buf.append(ch); |
| } |
| } |
| |
| pathFormat.setPattern(buf.toString().trim()); |
| pathFormat.setArguments(arguments.toArray(new String[arguments.size()])); |
| return pathFormat; |
| } |
| |
| static String normalizePath(String path) { |
| String s = path; |
| while (s.startsWith("/")) { //NOI18N |
| s = s.substring(1); |
| } |
| while (s.endsWith("/")) { //NOI18N |
| s = s.substring(0, s.length()-1); |
| } |
| return s; |
| } |
| |
| } |