blob: 7b0a66c3e45aef5a9bf3bc20554f4358e18b7a8c [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 hessian
import (
"bufio"
"io"
"os"
"regexp"
"strings"
)
var (
hessianImport = []byte{newLine, 105, 109, 112, 111, 114, 116, 32, 40, newLine, 9, 34, 103, 105, 116, 104, 117, 98, 46, 99, 111, 109, 47, 97, 112, 97, 99, 104, 101, 47, 100, 117, 98, 98, 111, 45, 103, 111, 45, 104, 101, 115, 115, 105, 97, 110, 50, 34, newLine, 41, newLine}
initFunctionPrefix = []byte{newLine, 102, 117, 110, 99, 32, 105, 110, 105, 116, 40, 41, 32, 123, newLine}
initFunctionSuffix = []byte{newLine, funcEnd, newLine}
hessianRegistryPOJOFunctionPrefix = []byte{9, 104, 101, 115, 115, 105, 97, 110, 46, 82, 101, 103, 105, 115, 116, 101, 114, 80, 79, 74, 79, 40, 38}
hessianRegistryPOJOFunctionSuffix = []byte{123, funcEnd, 41}
)
type fileInfo struct {
path string
packageStartIndex int
packageEndIndex int
hasInitFunc bool
initFuncStartIndex int
initFuncEndIndex int
initFuncStatementStartIndex int
hasHessianImport bool
buffer []byte
hessianPOJOList [][]byte
}
type Generator struct {
f string
}
func NewGenerator(f string) *Generator {
return &Generator{f}
}
func (g Generator) Execute() {
f := g.f
var file *fileInfo
var err error
showLog(infoLog, "=== Generate start [%s] ===", f)
file, err = scanFile(f)
if err != nil {
showLog(errorLog, "=== Generate error [%s] ===\n%v", f, err)
return
}
err = genRegistryStatement(file)
if err != nil {
showLog(errorLog, "=== Generate error [%s] ===\n%v", f, err)
return
}
showLog(infoLog, "=== Generate completed [%s] ===", f)
}
// scanFile 扫描文件内容
// nolint
func scanFile(filePath string) (file *fileInfo, err error) {
var f *os.File
f, err = os.Open(filePath)
if err != nil {
return
}
defer func(f *os.File) {
_ = f.Close()
}(f)
buf := bufio.NewReader(f)
file = &fileInfo{
path: filePath,
}
bufferSize := 0
buffer := make([]byte, bufferSize)
stack := make([][]byte, 0)
var line []byte
var lineSize int
for {
line, _, err = buf.ReadLine()
if err == io.EOF {
err = nil
break
}
bufferSize = len(buffer)
lineSize = len(line)
if file.hasInitFunc && lineSize > 0 && line[0] == funcEnd {
file.initFuncEndIndex = bufferSize + 1 // 检测初始化函数结束位
}
buffer = append(buffer, line...)
buffer = append(buffer, newLine)
if passed, _ := regexp.Match(PackageRegexp, line); passed { // 检测package位置
file.packageStartIndex = bufferSize // 检测初始化函数初始位
file.packageEndIndex = bufferSize + lineSize + 1 // 检测初始化函数初始位
continue
}
if passed, _ := regexp.Match(InitFunctionRegexp, line); passed { // 检测初始化函数
file.hasInitFunc = true
file.initFuncStartIndex = bufferSize // 检测初始化函数初始位
file.initFuncStatementStartIndex = bufferSize + lineSize // 初始化函数方法体初始位
continue
}
if !file.hasHessianImport {
r, _ := regexp.Compile(HessianImportRegexp)
rIndexList := r.FindIndex(line)
if len(rIndexList) > 0 { // 检测是否已导入hessian2包
checkStatement := line[:rIndexList[0]]
passed, _ := regexp.Match(LineCommentRegexp, checkStatement) // 是否被行注释
file.hasHessianImport = !passed
continue
}
}
if passed, _ := regexp.Match(HessianPOJORegexp, line); !passed { // 校验是否为Hessian.POJO实现类
continue
}
structName := getStructName(line)
if len(structName) != 0 {
stack = append(stack, structName)
}
}
file.buffer = buffer
file.hessianPOJOList = stack
return
}
// getStructName 获取Hessian.POJO实现类的类名
func getStructName(line []byte) []byte {
r, _ := regexp.Compile(HessianPOJONameRegexp)
line = r.Find(line)
if len(line) != 0 {
return line[1 : len(line)-1]
}
return nil
}
// genRegistryPOJOStatement 生成POJO注册方法体
func genRegistryPOJOStatement(pojo []byte) []byte {
var buffer []byte
buffer = append(buffer, hessianRegistryPOJOFunctionPrefix...)
buffer = append(buffer, pojo...)
buffer = append(buffer, hessianRegistryPOJOFunctionSuffix...)
return buffer
}
func lastIndexOf(buf []byte, b byte, s *int) int {
var l int
if s != nil {
l = *s
} else {
l = len(buf)
}
if l < 0 || l >= len(buf) {
return -1
}
for ; l >= 0; l-- {
if buf[l] == b {
return l
}
}
return -1
}
func escape(str string) string {
str = strings.TrimSpace(str)
str = strings.ReplaceAll(str, ".", "\\.")
str = strings.ReplaceAll(str, "(", "\\(")
str = strings.ReplaceAll(str, ")", "\\)")
str = strings.ReplaceAll(str, "{", "\\{")
str = strings.ReplaceAll(str, "}", "\\}")
return str
}
// genRegistryPOJOStatements 生成POJO注册方法体
// nolint
func genRegistryPOJOStatements(file *fileInfo, initFunctionStatement *[]byte) []byte {
f := file.path
hessianPOJOList := file.hessianPOJOList
var buffer []byte
var r *regexp.Regexp
var rIndexList []int
for _, name := range hessianPOJOList {
statement := genRegistryPOJOStatement(name)
if initFunctionStatement != nil { // 检测是否已存在注册方法体
r, _ = regexp.Compile(escape(string(statement)))
initStatement := *initFunctionStatement
rIndexList = r.FindIndex(initStatement)
if len(rIndexList) > 0 {
i := rIndexList[0]
n := lastIndexOf(initStatement, newLine, &i)
checkStatement := initStatement[lastIndexOf(initStatement, newLine, &n)+1 : i]
if passed, _ := regexp.Match(LineCommentRegexp, checkStatement); !passed { // 是否被行注释
showLog(infoLog, "=== Ignore POJO [%s].%s ===", f, name)
continue // 忽略相同的注册操作
}
}
}
showLog(infoLog, "=== Registry POJO [%s].%s ===", f, name)
buffer = append(buffer, newLine)
buffer = append(buffer, statement...)
buffer = append(buffer, newLine)
}
return buffer
}
func genRegistryStatement(file *fileInfo) error {
if file == nil || len(file.hessianPOJOList) == 0 {
return nil
}
buffer := file.buffer
offset := 0
if !file.hasHessianImport { // 追加hessian2导包
sliceIndex := file.packageEndIndex + offset
var bufferClone []byte
bufferClone = append(bufferClone, buffer[:sliceIndex]...)
bufferClone = append(bufferClone, hessianImport...)
bufferClone = append(bufferClone, buffer[sliceIndex:]...)
buffer = bufferClone
offset += len(hessianImport)
}
var registryPOJOStatement []byte
if file.hasInitFunc {
sliceIndex := file.initFuncStatementStartIndex + offset
initFunctionStatement := buffer[sliceIndex : file.initFuncEndIndex+offset-1]
registryPOJOStatement = genRegistryPOJOStatements(file, &initFunctionStatement)
var bufferClone []byte
bufferClone = append(bufferClone, buffer[:sliceIndex]...)
bufferClone = append(bufferClone, registryPOJOStatement...) // 追加POJO注册方法体至init函数
bufferClone = append(bufferClone, buffer[sliceIndex:]...)
buffer = bufferClone
} else { // 追加初始化函数
registryPOJOStatement = genRegistryPOJOStatements(file, nil)
buffer = append(buffer, initFunctionPrefix...) // 添加init函数
buffer = append(buffer, registryPOJOStatement...) // 追加POJO注册方法体至init函数
buffer = append(buffer, initFunctionSuffix...)
}
f, err := os.OpenFile(file.path, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return err
}
defer func(f *os.File) {
_ = f.Close()
}(f)
_, err = f.Write(buffer)
return err
}