blob: 6364c388b3b2d3906b4567e7e2cecced5710fc08 [file] [log] [blame]
/*
* 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 io.servicecomb.swagger.generator.core.utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.lang.model.SourceVersion;
import org.springframework.util.StringUtils;
import com.fasterxml.jackson.databind.JavaType;
import io.servicecomb.common.javassist.ClassConfig;
import io.servicecomb.common.javassist.JavassistUtils;
import io.servicecomb.common.javassist.MethodConfig;
import io.servicecomb.swagger.converter.ConverterMgr;
import io.servicecomb.swagger.generator.core.OperationGenerator;
import io.servicecomb.swagger.generator.core.SwaggerConst;
import io.servicecomb.swagger.generator.core.SwaggerGenerator;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Response;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.Property;
public final class ClassUtils {
// reference:
// https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
// https://en.wikipedia.org/wiki/List_of_Java_keywords
private ClassUtils() {
}
public static Class<?> getClassByName(ClassLoader classLoader, String clsName) {
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
try {
return classLoader.loadClass(clsName);
} catch (ClassNotFoundException e) {
return null;
}
}
// 获取modelImpl对应的class
public static Class<?> getOrCreateClass(ClassLoader classLoader, String packageName, Swagger swagger,
Map<String, Property> properties,
String clsName) {
Class<?> cls = getClassByName(classLoader, clsName);
if (cls != null) {
return cls;
}
ClassConfig classConfig = new ClassConfig();
classConfig.setClassName(clsName);
if (null != properties) {
for (Entry<String, Property> entry : properties.entrySet()) {
JavaType propertyJavaType =
ConverterMgr.findJavaType(classLoader,
packageName,
swagger,
entry.getValue());
classConfig.addField(entry.getKey(), propertyJavaType);
}
}
cls = JavassistUtils.createClass(classLoader, classConfig);
return cls;
}
// 将一系列body parameter包装成一个class
public static Class<?> getOrCreateBodyClass(OperationGenerator operationGenerator,
List<BodyParameter> bodyParameters) {
SwaggerGenerator swaggerGenerator = operationGenerator.getSwaggerGenerator();
Method method = operationGenerator.getProviderMethod();
String clsName = swaggerGenerator.ensureGetPackageName() + "." + method.getName() + "Body";
Class<?> cls = getClassByName(swaggerGenerator.getClassLoader(), clsName);
if (cls != null) {
return cls;
}
ClassConfig classConfig = new ClassConfig();
classConfig.setClassName(clsName);
// 1.全是预备body
// 2.预备body与明确body混合
for (BodyParameter bp : bodyParameters) {
JavaType javaType = ConverterMgr.findJavaType(swaggerGenerator.getClassLoader(),
swaggerGenerator.ensureGetPackageName(),
swaggerGenerator.getSwagger(),
bp);
classConfig.addField(bp.getName(), javaType);
}
return JavassistUtils.createClass(swaggerGenerator.getClassLoader(), classConfig);
}
public static boolean hasAnnotation(Class<?> cls, Class<? extends Annotation> annotation) {
if (cls.getAnnotation(annotation) != null) {
return true;
}
for (Method method : cls.getMethods()) {
if (method.getAnnotation(annotation) != null) {
return true;
}
}
return false;
}
public static boolean isRawJsonType(Parameter param) {
Object rawJson = param.getVendorExtensions().get(SwaggerConst.EXT_RAW_JSON_TYPE);
if (Boolean.class.isInstance(rawJson)) {
return (boolean) rawJson;
}
return false;
}
public static Class<?> getJavaInterface(Swagger swagger) {
return getClassByVendorExtensions(null, swagger.getInfo().getVendorExtensions(), SwaggerConst.EXT_JAVA_INTF);
}
public static Class<?> getClassByVendorExtensions(ClassLoader classLoader, Map<String, Object> vendorExtensions,
String clsKey) {
if (vendorExtensions == null) {
return null;
}
String clsName = (String) vendorExtensions.get(clsKey);
if (StringUtils.isEmpty(clsName)) {
return null;
}
return getClassByName(classLoader, clsName);
}
public static Class<?> getOrCreateInterface(SwaggerGenerator generator) {
return getOrCreateInterface(generator.getSwagger(),
generator.getClassLoader(),
generator.ensureGetPackageName());
}
public static Class<?> getOrCreateInterface(Swagger swagger, ClassLoader classLoader, String packageName) {
String intfName =
(String) swagger.getInfo().getVendorExtensions().get(SwaggerConst.EXT_JAVA_INTF);
Class<?> intf = getClassByName(classLoader, intfName);
if (intf != null) {
return intf;
}
if (packageName == null) {
int idx = intfName.lastIndexOf(".");
if (idx == -1) {
packageName = "";
} else {
packageName = intfName.substring(0, idx);
}
}
return createInterface(swagger, classLoader, packageName, intfName);
}
private static Class<?> createInterface(Swagger swagger, ClassLoader classLoader, String packageName,
String intfName) {
ClassConfig classConfig = new ClassConfig();
classConfig.setClassName(intfName);
classConfig.setIntf(true);
for (Path path : swagger.getPaths().values()) {
for (Operation operation : path.getOperations()) {
// 参数可能重名,所以packageName必须跟operation相关才能隔离
String opPackageName = packageName + "." + operation.getOperationId();
Response result = operation.getResponses().get(SwaggerConst.SUCCESS_KEY);
JavaType resultJavaType = ConverterMgr.findJavaType(classLoader,
opPackageName,
swagger,
result.getSchema());
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName(operation.getOperationId());
methodConfig.setResult(resultJavaType);
for (Parameter parameter : operation.getParameters()) {
String paramName = parameter.getName();
paramName = correctMethodParameterName(paramName);
JavaType paramJavaType = ConverterMgr.findJavaType(classLoader,
opPackageName,
swagger,
parameter);
methodConfig.addParameter(paramName, paramJavaType);
}
classConfig.addMethod(methodConfig);
}
}
return JavassistUtils.createClass(classLoader, classConfig);
}
public static String correctMethodParameterName(String paramName) {
if (SourceVersion.isName(paramName)) {
return paramName;
}
StringBuffer newParam = new StringBuffer();
char tempChar;
for (int index = 0; index < paramName.length(); index++) {
tempChar = paramName.charAt(index);
if (Character.isJavaIdentifierPart(tempChar)) {
newParam.append(paramName.charAt(index));
} else if (tempChar == '.' || tempChar == '-') {
newParam.append('_');
}
}
return newParam.toString();
}
public static String correctClassName(String name) {
if (SourceVersion.isIdentifier(name) && !SourceVersion.isKeyword(name)) {
return name;
}
String parts[] = name.split("\\.", -1);
for (int idx = 0; idx < parts.length; idx++) {
String part = parts[idx];
if (part.isEmpty()) {
parts[idx] = "_";
continue;
}
part = part.replace('-', '_');
if (Character.isDigit(part.charAt(0)) || SourceVersion.isKeyword(part)) {
part = "_" + part;
}
parts[idx] = part;
}
return String.join(".", parts);
}
}