feat[protocol]: 支持生成protobuf协议文件,提供从pojo到proto的生成方式

This commit is contained in:
jaysunxiao
2022-02-11 16:49:48 +08:00
parent b39fc50a21
commit b0ba151a8c
34 changed files with 607 additions and 77 deletions
-1
View File
@@ -39,7 +39,6 @@ hs_err_pid*
**/CsProtocol/
**/LuaProtocol/
**/zapp-user/protocol/
**/protobuf/
# 以下是web前端需要忽略的文件
# 忽略npm生成的package描述文件
@@ -53,26 +53,26 @@ public class MonitorVO {
var messages = new ArrayList<String>();
var uptimeMessage = uptime.pressure();
if (!StringUtils.isBlank(uptimeMessage)) {
if (StringUtils.isNotBlank(uptimeMessage)) {
messages.add(uptimeMessage);
}
for (var fileSystem : df) {
var dfMessage = fileSystem.pressure();
if (!StringUtils.isBlank(dfMessage)) {
if (StringUtils.isNotBlank(dfMessage)) {
messages.add(dfMessage);
}
}
var freeMessage = free.pressure();
if (!StringUtils.isBlank(freeMessage)) {
if (StringUtils.isNotBlank(freeMessage)) {
messages.add(freeMessage);
}
for (var networkIF : sar) {
var sarMessage = networkIF.pressure();
if (!StringUtils.isBlank(sarMessage)) {
if (StringUtils.isNotBlank(sarMessage)) {
messages.add(sarMessage);
}
}
-13
View File
@@ -134,19 +134,6 @@
<version>${netty.version}</version>
</dependency>
<!-- Protobuf -->
<dependency>
<groupId>com.baidu</groupId>
<artifactId>jprotobuf</artifactId>
<version>${jprotobuf.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 动态生成二进制字节码的javassist类库 -->
<dependency>
<groupId>org.javassist</groupId>
@@ -38,6 +38,7 @@ public class NetConfig {
private boolean generateCsProtocol;
private boolean generateLuaProtocol;
private boolean generateGdProtocol;
private boolean generateProtobufProtocol;
private RegistryConfig registry;
private MonitorConfig monitor;
@@ -154,6 +155,14 @@ public class NetConfig {
this.generateGdProtocol = generateGdProtocol;
}
public boolean isGenerateProtobufProtocol() {
return generateProtobufProtocol;
}
public void setGenerateProtobufProtocol(boolean generateProtobufProtocol) {
this.generateProtobufProtocol = generateProtobufProtocol;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -359,7 +359,7 @@ public class ZookeeperRegistry implements IRegistry {
private void initConsumerCache() throws Exception {
// 初始化providerCacheSet
var remoteProviderSet = curator.getChildren().forPath(PROVIDER_ROOT_PATH).stream()
.filter(it -> !StringUtils.isBlank(it) && !"null".equals(it))
.filter(it -> StringUtils.isNotBlank(it) && !"null".equals(it))
.map(it -> RegisterVO.parseString(it))
.filter(it -> Objects.nonNull(it))
.filter(it -> RegisterVO.providerHasConsumerModule(it, localRegisterVO))
@@ -505,7 +505,7 @@ public class ZookeeperRegistry implements IRegistry {
public List<String> children(String path) {
try {
var children = curator.getChildren().forPath(path).stream()
.filter(it -> !StringUtils.isBlank(it) && !"null".equals(it))
.filter(it -> StringUtils.isNotBlank(it) && !"null".equals(it))
.collect(Collectors.toList());
return children;
} catch (Exception e) {
@@ -520,7 +520,7 @@ public class ZookeeperRegistry implements IRegistry {
public Set<RegisterVO> remoteProviderRegisterSet() {
try {
var remoteProviderSet = curator.getChildren().forPath(PROVIDER_ROOT_PATH).stream()
.filter(it -> !StringUtils.isBlank(it) && !"null".equals(it))
.filter(it -> StringUtils.isNotBlank(it) && !"null".equals(it))
.map(it -> RegisterVO.parseString(it))
.filter(it -> Objects.nonNull(it))
.collect(Collectors.toSet());
@@ -89,6 +89,7 @@ public class PacketService implements IPacketService {
var generateCsharpProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateCsProtocol();
var generateLuaProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateLuaProtocol();
var generateGdProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateGdProtocol();
var generateProtobufProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateProtobufProtocol();
var generateOperation = new GenerateOperation();
generateOperation.setFoldProtocol(foldProtocol);
generateOperation.setProtocolPath(protocolPath);
@@ -105,6 +106,9 @@ public class PacketService implements IPacketService {
if (generateGdProtocol) {
generateOperation.getGenerateLanguages().add(CodeLanguage.GdScript);
}
if (generateProtobufProtocol) {
generateOperation.getGenerateLanguages().add(CodeLanguage.Protobuf);
}
// 设置生成协议的过滤器
GenerateProtocolFile.generateProtocolFilter = netGenerateProtocolFilter;
@@ -93,6 +93,7 @@ public class NetDefinitionParser implements BeanDefinitionParser {
resolvePlaceholder("generate-cs-protocol", "generateCsProtocol", builder, element, parserContext);
resolvePlaceholder("generate-lua-protocol", "generateLuaProtocol", builder, element, parserContext);
resolvePlaceholder("generate-gd-protocol", "generateGdProtocol", builder, element, parserContext);
resolvePlaceholder("generate-protobuf-protocol", "generateProtobufProtocol", builder, element, parserContext);
resolvePlaceholder("fold-protocol", "foldProtocol", builder, element, parserContext);
resolvePlaceholder("protocol-path", "protocolPath", builder, element, parserContext);
resolvePlaceholder("protocol-param", "protocolParam", builder, element, parserContext);
+1
View File
@@ -70,6 +70,7 @@
<xsd:attribute name="generate-cs-protocol" type="xsd:string" default="false"/>
<xsd:attribute name="generate-lua-protocol" type="xsd:string" default="false"/>
<xsd:attribute name="generate-gd-protocol" type="xsd:string" default="false"/>
<xsd:attribute name="generate-protobuf-protocol" type="xsd:string" default="false"/>
<xsd:attribute name="fold-protocol" type="xsd:string" default="false"/>
<xsd:attribute name="protocol-path" type="xsd:string"/>
<xsd:attribute name="protocol-param" type="xsd:string"/>
@@ -114,7 +114,7 @@ public class OrmManager implements IOrmManager {
}
// 设置数据库账号密码
if (!StringUtils.isBlank(hostConfig.getUser()) && !StringUtils.isBlank(hostConfig.getPassword())) {
if (StringUtils.isNotBlank(hostConfig.getUser()) && StringUtils.isNotBlank(hostConfig.getPassword())) {
mongoBuilder.credential(MongoCredential.createCredential(hostConfig.getUser(), "admin", hostConfig.getPassword().toCharArray()));
}
-1
View File
@@ -156,7 +156,6 @@
<groupId>com.baidu</groupId>
<artifactId>jprotobuf</artifactId>
<version>${jprotobuf.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
@@ -84,10 +84,11 @@ public abstract class GenerateProtocolDocument {
.collect(Collectors.toList());
for (var protocolRegistration : protocolRegistrations) {
var protocolClazzName = protocolRegistration.protocolConstructor().getDeclaringClass().getSimpleName();
var protocolClazz = protocolRegistration.protocolConstructor().getDeclaringClass();
var protocolClazzName = protocolClazz.getName();
var protocolFile = list.stream()
.filter(it -> it.getName().equals(StringUtils.format("{}.java", protocolClazzName)))
.filter(it -> it.getAbsolutePath().replace(StringUtils.SLASH, StringUtils.PERIOD).replace(StringUtils.BACK_SLASH, StringUtils.PERIOD).endsWith(StringUtils.format("{}.java", protocolClazzName)))
.findFirst();
// 如果搜索不到协议文件则直接返回
@@ -104,7 +105,7 @@ public abstract class GenerateProtocolDocument {
.collect(Collectors.toList());
// 搜索包名,报名不匹配则直接返回
var protocolClassTitle = StringUtils.format("public class {}", protocolClazzName);
var protocolClassTitle = StringUtils.format("public class {}", protocolClazz.getSimpleName());
if (protocolStringList.stream().noneMatch(it -> it.contains(protocolClassTitle))) {
continue;
}
@@ -21,6 +21,7 @@ import com.zfoo.protocol.serializer.cs.GenerateCsUtils;
import com.zfoo.protocol.serializer.gd.GenerateGdUtils;
import com.zfoo.protocol.serializer.js.GenerateJsUtils;
import com.zfoo.protocol.serializer.lua.GenerateLuaUtils;
import com.zfoo.protocol.serializer.protobuf.GenerateProtobufUtils;
import java.io.IOException;
import java.util.Arrays;
@@ -55,7 +56,7 @@ public abstract class GenerateProtocolFile {
index = null;
}
public static void generate(GenerateOperation generateOperation) throws IOException {
public static void generate(GenerateOperation generateOperation) throws IOException, ClassNotFoundException {
var protocols = ProtocolManager.protocols;
// 如果没有需要生成的协议则直接返回
@@ -124,6 +125,13 @@ public abstract class GenerateProtocolFile {
allSortedGenerateProtocols.forEach(it -> GenerateGdUtils.createGdProtocolFile((ProtocolRegistration) it));
}
// 生成Protobuf协议
if (generateLanguages.contains(CodeLanguage.Protobuf)) {
GenerateProtobufUtils.init(generateOperation);
GenerateProtobufUtils.createProtocolManager();
GenerateProtobufUtils.createProtocols();
}
// 预留参数,以后可能会用,比如给Lua修改一个后缀名称
var protocolParam = generateOperation.getProtocolParam();
}
@@ -111,7 +111,7 @@ public abstract class GenerateProtocolPath {
var protocolSimpleName = child.getData().protocolConstructor().getDeclaringClass().getSimpleName();
var splits = Arrays.stream(StringUtils.substringBeforeLast(StringUtils.substringAfterFirst(child.fullName(), pathBefore), protocolSimpleName)
.split(StringUtils.PERIOD_REGEX))
.filter(it -> !StringUtils.isBlank(it))
.filter(it -> StringUtils.isNotBlank(it))
.toArray();
protocolPathMap.put(child.getData().protocolId(), StringUtils.joinWith(StringUtils.PERIOD, splits));
}
@@ -26,6 +26,7 @@ import com.zfoo.protocol.serializer.cs.GenerateCsUtils;
import com.zfoo.protocol.serializer.gd.GenerateGdUtils;
import com.zfoo.protocol.serializer.js.GenerateJsUtils;
import com.zfoo.protocol.serializer.lua.GenerateLuaUtils;
import com.zfoo.protocol.serializer.protobuf.GenerateProtobufUtils;
import com.zfoo.protocol.serializer.reflect.*;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.ReflectionUtils;
@@ -199,7 +200,7 @@ public class ProtocolAnalysis {
}
}
private static void enhanceProtocolBefore(GenerateOperation generateOperation) throws IOException {
private static void enhanceProtocolBefore(GenerateOperation generateOperation) throws IOException, ClassNotFoundException {
// 检查协议格式
checkAllProtocolClass();
@@ -226,6 +227,7 @@ public class ProtocolAnalysis {
GenerateJsUtils.clear();
GenerateLuaUtils.clear();
GenerateGdUtils.clear();
GenerateProtobufUtils.clear();
EnhanceUtils.clear();
}
@@ -29,6 +29,8 @@ public enum CodeLanguage {
CSharp,
GdScript
GdScript,
Protobuf
}
@@ -255,7 +255,7 @@ public abstract class GenerateCsUtils {
var docFieldMap = protocolDocument.getValue();
var csBuilder = new StringBuilder();
if (!StringUtils.isBlank(docTitle)) {
if (StringUtils.isNotBlank(docTitle)) {
Arrays.stream(docTitle.split(LS)).forEach(it -> csBuilder.append(TAB).append(it).append(LS));
}
csBuilder.append(TAB)
@@ -272,7 +272,7 @@ public abstract class GenerateCsUtils {
var propertyFullName = StringUtils.format("public {} {};", propertyType, propertyName);
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
if (StringUtils.isNotBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> csBuilder.append(TAB + TAB).append(it).append(LS));
}
@@ -152,7 +152,7 @@ public abstract class GenerateGdUtils {
var gdBuilder = new StringBuilder();
if (!StringUtils.isBlank(docTitle)) {
if (StringUtils.isNotBlank(docTitle)) {
gdBuilder.append(gdDocument(docTitle)).append(LS);
}
@@ -161,7 +161,7 @@ public abstract class GenerateGdUtils {
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
if (StringUtils.isNotBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> gdBuilder.append(gdDocument(it)).append(LS));
}
@@ -164,7 +164,7 @@ public abstract class GenerateJsUtils {
var jsBuilder = new StringBuilder();
if (!StringUtils.isBlank(docTitle)) {
if (StringUtils.isNotBlank(docTitle)) {
jsBuilder.append(docTitle).append(LS);
}
@@ -178,7 +178,7 @@ public abstract class GenerateJsUtils {
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
if (StringUtils.isNotBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> jsBuilder.append(TAB).append(it).append(LS));
}
@@ -164,7 +164,7 @@ public abstract class GenerateLuaUtils {
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docTitle = protocolDocument.getKey();
if (!StringUtils.isBlank(docTitle)) {
if (StringUtils.isNotBlank(docTitle)) {
Arrays.stream(docTitle.split(LS)).forEach(it -> luaBuilder.append(docToLuaDoc(it)).append(LS));
luaBuilder.append(LS);
}
@@ -196,7 +196,7 @@ public abstract class GenerateLuaUtils {
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
if (StringUtils.isNotBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> luaBuilder.append(TAB + TAB).append(docToLuaDoc(it)).append(LS));
}
@@ -0,0 +1,310 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed 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 com.zfoo.protocol.serializer.protobuf;
import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.collection.ArrayUtils;
import com.zfoo.protocol.exception.RunException;
import com.zfoo.protocol.generate.GenerateOperation;
import com.zfoo.protocol.generate.GenerateProtocolDocument;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolAnalysis;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.*;
import com.zfoo.protocol.serializer.reflect.*;
import com.zfoo.protocol.util.ClassUtils;
import com.zfoo.protocol.util.DomUtils;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.stream.Collectors;
import static com.zfoo.protocol.util.FileUtils.LS;
import static com.zfoo.protocol.util.StringUtils.TAB;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateProtobufUtils {
private static String protocolOutputRootPath = "protos/";
private static String protocolManagerName = "protocols";
private static XmlProtobuf xmlProtobuf = null;
public static String syntax() {
return StringUtils.format("syntax = {}{}{};", StringUtils.QUOTATION_MARK, xmlProtobuf.getSyntax(), StringUtils.QUOTATION_MARK);
}
public static String option(String optionKey, String optionValue) {
return StringUtils.format("option {} = {}{}{};", optionKey, StringUtils.QUOTATION_MARK, optionValue, StringUtils.QUOTATION_MARK);
}
public static String importProto(String importValue) {
return StringUtils.format("import {}{}.proto{};", StringUtils.QUOTATION_MARK, importValue, StringUtils.QUOTATION_MARK);
}
public static Map<String, String> parseParam(String param) {
var params = param.trim().split(StringUtils.SEMICOLON_REGEX);
if (ArrayUtils.isEmpty(params)) {
throw new RunException("参数格式错误,格式protobuf=xxx;java=xxx");
}
var map = Arrays.stream(params)
.map(it -> it.trim())
.map(it -> new Pair<>(StringUtils.substringBeforeFirst(it, StringUtils.EQUAL), StringUtils.substringAfterFirst(it, StringUtils.EQUAL)))
.collect(Collectors.toMap(key -> key.getKey(), value -> value.getValue()));
return map;
}
public static void init(GenerateOperation generateOperation) throws IOException {
protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
var protocolParam = generateOperation.getProtocolParam();
if (StringUtils.isEmpty(protocolParam)) {
throw new RunException("生成protobuf协议的protocolParam参数不能为空");
}
var map = parseParam(protocolParam);
var protobufXmlPath = map.get("protobuf");
FileUtils.deleteFile(new File(protocolOutputRootPath));
FileUtils.createDirectory(protocolOutputRootPath);
var inputStream = ClassUtils.getFileFromClassPath(protobufXmlPath);
var xmlProtobufObj = DomUtils.inputStream2Object(inputStream, XmlProtobuf.class);
if (!xmlProtobufObj.getSyntax().equals("proto3")) {
throw new RunException("生成protobuf协议只支持proto3");
}
var protoSet = new HashSet<String>();
for (var protos : xmlProtobufObj.getProtos()) {
if (protos.getName().equals(protocolManagerName)) {
throw new RunException("protobuf的协议文件名称不能用保留名称[{}]", protocolManagerName);
}
if (protoSet.contains(protos.getName())) {
throw new RunException("protobuf的协议文件名称重复定义[{}]", protos.getName());
}
protoSet.add(protos.getName());
}
xmlProtobuf = xmlProtobufObj;
}
public static void createProtocolManager() throws ClassNotFoundException {
var allGenerateProtocols = new HashSet<IProtocolRegistration>();
for (var protos : xmlProtobuf.getProtos()) {
for (var protocol : protos.getProtocols()) {
var protocolClass = Class.forName(protocol.getLocation());
var protocolId = ProtocolAnalysis.getProtocolIdByClass(protocolClass);
var protocolRegistration = ProtocolManager.getProtocol(protocolId);
if (allGenerateProtocols.contains(protocolRegistration)) {
throw new RunException("protobuf的xml协议文件中重复定义了协议[{}]", protocolClass.getSimpleName());
}
allGenerateProtocols.add(protocolRegistration);
}
}
var builder = new StringBuilder();
builder.append(syntax());
builder.append(LS).append(LS);
if (StringUtils.isNotEmpty(xmlProtobuf.getOption())) {
var optionMap = parseParam(xmlProtobuf.getOption());
for (var option : optionMap.entrySet()) {
builder.append(option(option.getKey(), option.getValue())).append(LS);
}
}
builder.append(LS);
builder.append("enum ProtocolManager {").append(LS);
if (allGenerateProtocols.stream().noneMatch(it -> it.protocolId() == 0)) {
builder.append(TAB).append(StringUtils.format("{} = 0;", "ZFOO_AUTO_GENERATE_ZERO_ENUM_VALUE")).append(LS).append(LS);
}
allGenerateProtocols.stream()
.sorted((a, b) -> a.protocolId() - b.protocolId())
.forEach(it -> builder.append(TAB).append(StringUtils.format("{} = {};", it.protocolConstructor().getDeclaringClass().getSimpleName(), it.protocolId())).append(LS));
builder.append("}").append(LS);
var protocolOutputPath = StringUtils.format("{}/{}.proto", protocolOutputRootPath, protocolManagerName);
FileUtils.writeStringToFile(new File(protocolOutputPath), builder.toString());
}
public static void createProtocols() throws ClassNotFoundException {
for (var protos : xmlProtobuf.getProtos()) {
var builder = new StringBuilder();
builder.append(syntax());
builder.append(LS).append(LS);
if (StringUtils.isNotEmpty(protos.getImportProto())) {
var params = protos.getImportProto().trim().split(StringUtils.SEMICOLON_REGEX);
for (var importProto : params) {
if (StringUtils.isBlank(importProto)) {
continue;
}
builder.append(importProto(importProto.trim())).append(LS);
}
builder.append(LS);
}
if (StringUtils.isNotEmpty(protos.getOption())) {
var optionMap = parseParam(protos.getOption());
for (var option : optionMap.entrySet()) {
builder.append(option(option.getKey(), option.getValue())).append(LS);
}
builder.append(LS);
}
for (var protocol : protos.getProtocols()) {
var protocolClass = Class.forName(protocol.getLocation());
var protocolId = ProtocolAnalysis.getProtocolIdByClass(protocolClass);
var protocolRegistration = ProtocolManager.getProtocol(protocolId);
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docTitle = protocolDocument.getKey();
if (StringUtils.isNotBlank(docTitle)) {
Arrays.stream(docTitle.split(LS)).forEach(it -> builder.append(it).append(LS));
}
builder.append(StringUtils.format("message {} {", protocolClass.getSimpleName())).append(LS);
builder.append(protocolClass((ProtocolRegistration) protocolRegistration));
builder.append("}").append(LS).append(LS);
}
var protocolOutputPath = StringUtils.format("{}/{}.proto", protocolOutputRootPath, protos.getName());
FileUtils.writeStringToFile(new File(protocolOutputPath), builder.toString());
}
}
private static String protocolClass(ProtocolRegistration registration) {
var builder = new StringBuilder();
var protocolId = registration.getId();
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docFieldMap = protocolDocument.getValue();
for (int i = 0, length = fields.length; i < length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
var protobuf = field.getDeclaredAnnotation(Protobuf.class);
if (protobuf == null) {
throw new RunException("protobu协议类必须加上注解[{}],并且标识order的顺序", Protobuf.class.getSimpleName());
}
var order = protobuf.order();
var propertyName = field.getName();
// 生成注释
var doc = docFieldMap.get(propertyName);
if (StringUtils.isNotBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> builder.append(TAB).append(it).append(LS));
}
var singleFieldStr = toFieldTypeName(fieldRegistration);
if (StringUtils.isNotBlank(singleFieldStr)) {
builder.append(TAB).append(StringUtils.format("{} {} = {};", singleFieldStr, propertyName, order)).append(LS);
continue;
}
if (fieldRegistration instanceof ArrayField) {
var arrayField = (ArrayField) fieldRegistration;
var arrayFieldStr = toFieldTypeName(arrayField.getArrayElementRegistration());
builder.append(TAB).append(StringUtils.format("repeated {} {} = {};", arrayFieldStr, propertyName, order)).append(LS);
} else if (fieldRegistration instanceof ListField) {
var listField = (ListField) fieldRegistration;
var listFieldStr = toFieldTypeName(listField.getListElementRegistration());
builder.append(TAB).append(StringUtils.format("repeated {} {} = {};", listFieldStr, propertyName, order)).append(LS);
} else if (fieldRegistration instanceof SetField) {
var setField = (SetField) fieldRegistration;
var setFieldStr = toFieldTypeName(setField.getSetElementRegistration());
builder.append(TAB).append(StringUtils.format("repeated {} {} = {};", setFieldStr, propertyName, order)).append(LS);
} else if (fieldRegistration instanceof MapField) {
var mapField = (MapField) fieldRegistration;
var keyFieldStr = toFieldTypeName(mapField.getMapKeyRegistration());
var valueFieldStr = toFieldTypeName(mapField.getMapValueRegistration());
builder.append(TAB).append(StringUtils.format("map<{}, {}> {} = {};", keyFieldStr, valueFieldStr, propertyName, order)).append(LS);
} else {
throw new RunException("无法识别的protobuf类型[{}]", field.getName());
}
}
return builder.toString();
}
/**
* 注意protobuf不支持byteshortchar
*/
private static String toFieldTypeName(IFieldRegistration fieldRegistration) {
if (fieldRegistration instanceof BaseField) {
var serializer = fieldRegistration.serializer();
if (serializer instanceof BooleanSerializer) {
return "bool";
} else if (serializer instanceof ByteSerializer) {
return "byte";
} else if (serializer instanceof ShortSerializer) {
return "int16";
} else if (serializer instanceof IntSerializer) {
return "int32";
} else if (serializer instanceof LongSerializer) {
return "int64";
} else if (serializer instanceof FloatSerializer) {
return "float";
} else if (serializer instanceof DoubleSerializer) {
return "double";
} else if (serializer instanceof CharSerializer) {
return "char";
} else if (serializer instanceof StringSerializer) {
return "string";
}
} else if (fieldRegistration instanceof ObjectProtocolField) {
var objectProtocolField = (ObjectProtocolField) fieldRegistration;
return ProtocolManager.getProtocol(objectProtocolField.getProtocolId()).protocolConstructor().getDeclaringClass().getSimpleName();
}
return null;
}
public static void clear() {
protocolOutputRootPath = null;
protocolManagerName = null;
xmlProtobuf = null;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed 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 com.zfoo.protocol.serializer.protobuf;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;
@JacksonXmlRootElement(localName = "protocols")
public class XmlProtobuf {
@JacksonXmlProperty(isAttribute = true, localName = "syntax")
private String syntax;
@JacksonXmlProperty(isAttribute = true, localName = "option")
private String option;
@JacksonXmlProperty(localName = "proto")
@JacksonXmlElementWrapper(useWrapping = false)
private List<XmlProtobufProto> protos;
public String getSyntax() {
return syntax;
}
public String getOption() {
return option;
}
public List<XmlProtobufProto> getProtos() {
return protos;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed 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 com.zfoo.protocol.serializer.protobuf;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.util.List;
/**
* @author jaysunxiao
* @version 3.0
*/
public class XmlProtobufProto {
@JacksonXmlProperty(isAttribute = true, localName = "name")
private String name;
@JacksonXmlProperty(isAttribute = true, localName = "import")
private String importProto;
@JacksonXmlProperty(isAttribute = true, localName = "option")
private String option;
@JacksonXmlProperty(localName = "protocol")
@JacksonXmlElementWrapper(useWrapping = false)
private List<XmlProtobufProtocol> protocols;
public String getName() {
return name;
}
public String getImportProto() {
return importProto;
}
public String getOption() {
return option;
}
public List<XmlProtobufProtocol> getProtocols() {
return protocols;
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed 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 com.zfoo.protocol.serializer.protobuf;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
public class XmlProtobufProtocol {
@JacksonXmlProperty(isAttribute = true, localName = "location")
private String location;
public String getLocation() {
return location;
}
}
@@ -202,7 +202,7 @@ public abstract class AssertionUtils {
notNull(type, "Type to check against must not be null");
if (!type.isInstance(obj)) {
throw new AssertException(
(!StringUtils.isBlank(message) ? message + " " : "") +
(StringUtils.isNotBlank(message) ? message + " " : "") +
"Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
"] must be an instance of " + type);
}
@@ -227,7 +227,7 @@ public abstract class AssertionUtils {
public static void isAssignable(Class<?> superType, Class<?> subType, String message) {
notNull(superType, "Type to check against must not be null");
if (subType == null || !superType.isAssignableFrom(subType)) {
throw new AssertException((!StringUtils.isBlank(message) ? message + " " : "")
throw new AssertException((StringUtils.isNotBlank(message) ? message + " " : "")
+ subType + " is not assignable to " + superType);
}
}
@@ -129,7 +129,7 @@ public abstract class ClassUtils {
}
// 如果是java类文件则去掉后面的.class 只留下类名
String className = StringUtils.substringBeforeLast(fileName, CLASS_SUFFIX);
if (!StringUtils.isBlank(packageName)) {
if (StringUtils.isNotBlank(packageName)) {
String a = StringUtils.substringAfterFirst(file.getAbsolutePath(), FileUtils.getProAbsPath() + File.separator);
a = a.replaceAll(StringUtils.BACK_SLASH + File.separator, StringUtils.PERIOD);
String b = StringUtils.substringBeforeFirst(a, packageName);
@@ -37,52 +37,54 @@ public abstract class StringUtils {
public static final String TAB = " ";
public static final String TAB_ASCII = "\t";
public static final String COMMA = ",";// [com·ma || 'kɒmə] n. 逗点; 逗号
public static final String COMMA = ","; // [com·ma || 'kɒmə] n. 逗点; 逗号
public static final String COMMA_REGEX = ",|";
public static final String PERIOD = ".";// 句号
public static final String PERIOD = "."; // 句号
public static final String PERIOD_REGEX = "\\.";
public static final String LEFT_SQUARE_BRACKET = "[";//左方括号
public static final String LEFT_SQUARE_BRACKET = "["; // 左方括号
public static final String RIGHT_SQUARE_BRACKET = "]";//右方括号
public static final String RIGHT_SQUARE_BRACKET = "]"; // 右方括号
public static final String COLON = ":";//冒号[co·lon || 'kəʊlən]
public static final String COLON = ":"; // 冒号[co·lon || 'kəʊlən]
public static final String COLON_REGEX = ":|";
public static final String SEMICOLON = ";";//分号['semi'kәulәn]
public static final String SEMICOLON = ";"; // 分号['semi'kәulәn]
public static final String SEMICOLON_REGEX = ";|";
public static final String QUOTATION_MARK = "\"";//引号[quo·ta·tion || kwəʊ'teɪʃn]
public static final String QUOTATION_MARK = "\""; // 引号[quo·ta·tion || kwəʊ'teɪʃn]
public static final String ELLIPSIS = "...";//省略号
public static final String ELLIPSIS = "..."; // 省略号
public static final String EXCLAMATION_POINT = "!";//感叹号
public static final String EXCLAMATION_POINT = "!"; // 感叹号
public static final String DASH = "-";//破折号
public static final String DASH = "-"; // 破折号
public static final String QUESTION_MARK = "?";//问号
public static final String QUESTION_MARK = "?"; // 问号
public static final String HYPHEN = "-";//连接号连接号与破折号的区别是连接号的两头不用空格
public static final String HYPHEN = "-"; // 连接号连接号与破折号的区别是连接号的两头不用空格
public static final String SLASH = "/";//斜线号
public static final String SLASH = "/"; // 斜线号
public static final String BACK_SLASH = "\\";//反斜线
public static final String EQUAL = "="; // 等于
public static final String VERTICAL_BAR = "|";// 竖线
public static final String BACK_SLASH = "\\"; //反斜线号
public static final String VERTICAL_BAR = "|"; // 竖线
public static final String VERTICAL_BAR_REGEX = "\\|";
public static final String SHARP = "#";
public static final String SHARP_REGEX = "\\#";
public static final String DOLLAR = "$";// 美元符号
public static final String DOLLAR = "$"; // 美元符号
public static final String EMPTY_JSON = "{}";
public static final String MULTIPLE_HYPHENS = "-----------------------------------------------------------------------";
public static final int INDEX_NOT_FOUND = -1;//Represents a failed index search.
public static final int INDEX_NOT_FOUND = -1; // Represents a failed index search.
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
public static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_CHARSET_NAME);
@@ -23,7 +23,7 @@ import java.util.List;
* @author jaysunxiao
* @version 3.0
*/
@JsonPropertyOrder({"name", "minId", "maxId", "version"})
@JsonPropertyOrder({"id", "name", "minId", "maxId", "version"})
public class XmlModuleDefinition {
@JacksonXmlProperty(isAttribute = true, localName = "id")
@@ -26,30 +26,19 @@ public class XmlProtocolDefinition {
private String location;
@JacksonXmlProperty(isAttribute = true, localName = "enhance")
private boolean enhance = true;
private final boolean enhance = true;
public short getId() {
return id;
}
public void setId(short id) {
this.id = id;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public boolean isEnhance() {
return enhance;
}
public void setEnhance(boolean enhance) {
this.enhance = enhance;
}
}
@@ -13,7 +13,10 @@
package com.zfoo.protocol.jprotobuf;
import com.baidu.bjf.remoting.protobuf.ProtobufProxy;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.generate.GenerateOperation;
import com.zfoo.protocol.packet.ProtobufObject;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.util.JsonUtils;
import org.junit.Ignore;
import org.junit.Test;
@@ -21,6 +24,7 @@ import org.junit.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author jaysunxiao
@@ -67,4 +71,14 @@ public class JProtobufTest {
System.out.println(JsonUtils.object2String(newObj));
}
@Test
public void generateTest() throws IOException {
var op = GenerateOperation.NO_OPERATION;
op.getGenerateLanguages().add(CodeLanguage.Protobuf);
op.setFoldProtocol(true);
op.setProtocolParam("protobuf=protobufTest/protobuf.xml");
ProtocolManager.initProtocol(Set.of(ObjectA.class, ObjectB.class, ObjectC.class), op);
}
}
@@ -19,6 +19,9 @@ import com.zfoo.protocol.IPacket;
import java.util.Map;
/**
* protobuf的测试类型
* 包括了各种复杂的结构对象map
*
* @author jaysunxiao
* @version 3.0
*/
@@ -26,12 +29,18 @@ public class ObjectA implements IPacket {
public static final transient short PROTOCOL_ID = 102;
// int类型在protobuf中叫int32
@Protobuf(order = 1)
public int a;
// map类型
// protobuf中的map的key只能为基础类型
@Protobuf(order = 2)
public Map<Integer, String> m;
/**
* 对象类型
*/
@Protobuf(order = 3)
public ObjectB objectB;
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed 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 com.zfoo.protocol.jprotobuf;
import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;
import com.zfoo.protocol.IPacket;
import java.util.Map;
/**
* ObjectC的测试类型
*
* @author jaysunxiao
* @version 3.0
*/
public class ObjectC implements IPacket {
public static final transient short PROTOCOL_ID = 104;
// int类型在protobuf中叫int32
@Protobuf(order = 1)
public int a;
// map类型
// protobuf中的map的key只能为基础类型
@Protobuf(order = 2)
public Map<Integer, String> m;
/**
* 对象类型
*/
@Protobuf(order = 3)
public ObjectB objectB;
@Override
public short protocolId() {
return PROTOCOL_ID;
}
}
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<protobuf syntax="proto3" option="java_package=com.zfoo.zgame.common.proto.protobuf;java_outer_classname=Protocols">
<proto name="common" import=""
option="java_package=com.zfoo.zgame.common.proto.protobuf;java_outer_classname=ProtobufCommon">
<protocol location="com.zfoo.protocol.jprotobuf.ObjectA"/>
<protocol location="com.zfoo.protocol.jprotobuf.ObjectB"/>
</proto>
<proto name="other" import="common"
option="java_package=com.zfoo.zgame.common.proto.protobuf;java_outer_classname=ProtobufOther">
<protocol location="com.zfoo.protocol.jprotobuf.ObjectC"/>
</proto>
</protobuf>
@@ -155,7 +155,7 @@ public class ExcelResourceReader implements IResourceReader {
} catch (Exception e) {
// 没有setMethod是正确的
}
if (!StringUtils.isBlank(setMethodName)) {
if (StringUtils.isNotBlank(setMethodName)) {
throw new RunException("因为静态资源类是不能被修改的,所以资源类[class:{}]的属性[filed:{}]不能含有set方法[{}]", clazz, field.getName(), setMethodName);
}
}
@@ -448,7 +448,7 @@ public abstract class NumberUtils {
* @return 新值
*/
public static BigDecimal round(String numberStr, int scale, RoundingMode roundingMode) {
AssertionUtils.isTrue(!StringUtils.isBlank(numberStr));
AssertionUtils.isTrue(StringUtils.isNotBlank(numberStr));
if (scale < 0) {
scale = 0;
}
@@ -659,10 +659,7 @@ public abstract class NumberUtils {
public static boolean isDouble(String s) {
try {
Double.parseDouble(s);
if (s.contains(".")) {
return true;
}
return false;
return s.contains(".");
} catch (NumberFormatException e) {
return false;
}