Redkale 2.5.0 结束
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=APIDOC -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=APIDOC -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
|
||||
@@ -6,7 +6,7 @@ APP_HOME=`dirname "$0"`
|
||||
|
||||
if [ ! -f "$APP_HOME"/conf/application.xml ]; then
|
||||
APP_HOME="$APP_HOME"/..
|
||||
fi
|
||||
fi
|
||||
|
||||
lib='.'
|
||||
for jar in `ls $APP_HOME/lib/*.jar`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=%1 -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=%1 -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
call "%APP_HOME%\bin\shutdown.bat"
|
||||
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
call "%APP_HOME%\bin\shutdown.bat"
|
||||
|
||||
call "%APP_HOME%\bin\start.bat"
|
||||
@@ -1,7 +1,7 @@
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=SHUTDOWN -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=SHUTDOWN -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -server -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -server -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<shared-cache-mode>ALL</shared-cache-mode>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/center?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"/>
|
||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||
<property name="javax.persistence.jdbc.password" value="1234"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>jarĬ<EFBFBD>Ϸ<EFBFBD><EFBFBD>ڴ˴<EFBFBD>
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>jarĬ<EFBFBD>Ϸ<EFBFBD><EFBFBD>ڴ˴<EFBFBD>
|
||||
196
my/settings.xml
196
my/settings.xml
@@ -1,99 +1,99 @@
|
||||
<settings>
|
||||
<servers>
|
||||
<server>
|
||||
<id>ossrh</id>
|
||||
<username>redkale</username>
|
||||
<password>xxxxxxxxxxxxxxxxxxxxxxxxx</password>
|
||||
</server>
|
||||
</servers>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>ossrh</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<gpg.executable>gpg2</gpg.executable>
|
||||
<gpg.passphrase>xxxxxxxxxxxxxxxxxxxxxxxxx</gpg.passphrase>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<!--
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
<goals>deploy</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
-->
|
||||
</profile>
|
||||
</profiles>
|
||||
<settings>
|
||||
<servers>
|
||||
<server>
|
||||
<id>ossrh</id>
|
||||
<username>redkale</username>
|
||||
<password>xxxxxxxxxxxxxxxxxxxxxxxxx</password>
|
||||
</server>
|
||||
</servers>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>ossrh</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<gpg.executable>gpg2</gpg.executable>
|
||||
<gpg.passphrase>xxxxxxxxxxxxxxxxxxxxxxxxx</gpg.passphrase>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<!--
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
<goals>deploy</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
-->
|
||||
</profile>
|
||||
</profiles>
|
||||
</settings>
|
||||
2
pom.xml
2
pom.xml
@@ -7,7 +7,7 @@
|
||||
<name>RedkaleProject</name>
|
||||
<url>https://redkale.org</url>
|
||||
<description>redkale -- java framework</description>
|
||||
<version>2.5.0</version>
|
||||
<version>2.5.0</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* 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 javax.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 值越大,优先级越高
|
||||
*
|
||||
* @since Common Annotations 1.2
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Priority {
|
||||
|
||||
/**
|
||||
* 优先级值
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
/*
|
||||
* 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 javax.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 值越大,优先级越高
|
||||
*
|
||||
* @since Common Annotations 1.2
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Priority {
|
||||
|
||||
/**
|
||||
* 优先级值
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
|
||||
@@ -1,83 +1,83 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Resource {
|
||||
|
||||
/**
|
||||
* AuthenticationType
|
||||
*/
|
||||
@Deprecated
|
||||
public enum AuthenticationType {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
CONTAINER,
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
APPLICATION
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源名称
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String name() default "";
|
||||
|
||||
/**
|
||||
* 依赖注入的类型
|
||||
*
|
||||
* @return Class
|
||||
*/
|
||||
public Class<?> type() default Object.class;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AuthenticationType
|
||||
*/
|
||||
@Deprecated
|
||||
public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean shareable() default true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
public String description() default "";
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
public String mappedName() default "";
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
public String lookup() default "";
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Resource {
|
||||
|
||||
/**
|
||||
* AuthenticationType
|
||||
*/
|
||||
@Deprecated
|
||||
public enum AuthenticationType {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
CONTAINER,
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
APPLICATION
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源名称
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String name() default "";
|
||||
|
||||
/**
|
||||
* 依赖注入的类型
|
||||
*
|
||||
* @return Class
|
||||
*/
|
||||
public Class<?> type() default Object.class;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AuthenticationType
|
||||
*/
|
||||
@Deprecated
|
||||
public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean shareable() default true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
public String description() default "";
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
public String mappedName() default "";
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
public String lookup() default "";
|
||||
}
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
/** *****************************************************************************
|
||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
|
||||
* which accompanies this distribution.
|
||||
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Linda DeMichiel - Java Persistence 2.1
|
||||
* Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
***************************************************************************** */
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies whether an entity should be cached if caching is enabled
|
||||
* when the value of the <code>persistence.xml</code> caching element
|
||||
* is <code>ENABLE_SELECTIVE</code> or <code>DISABLE_SELECTIVE</code>.
|
||||
* The value of the <code>Cacheable</code> annotation is inherited by
|
||||
* subclasses; it can be overridden by specifying
|
||||
* <code>Cacheable</code> on a subclass.
|
||||
*
|
||||
* <p>
|
||||
* <code>Cacheable(false)</code> means that the entity and its state must
|
||||
* not be cached by the provider.
|
||||
*
|
||||
* @since Java Persistence 2.0
|
||||
*/
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cacheable {
|
||||
|
||||
/**
|
||||
* (Optional) Whether or not the entity should be cached.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int interval() default 0;
|
||||
|
||||
/**
|
||||
* DataSource是否直接返回对象的真实引用, 而不是copy一份
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean direct() default false;
|
||||
|
||||
}
|
||||
/** *****************************************************************************
|
||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
|
||||
* which accompanies this distribution.
|
||||
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Linda DeMichiel - Java Persistence 2.1
|
||||
* Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
***************************************************************************** */
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies whether an entity should be cached if caching is enabled
|
||||
* when the value of the <code>persistence.xml</code> caching element
|
||||
* is <code>ENABLE_SELECTIVE</code> or <code>DISABLE_SELECTIVE</code>.
|
||||
* The value of the <code>Cacheable</code> annotation is inherited by
|
||||
* subclasses; it can be overridden by specifying
|
||||
* <code>Cacheable</code> on a subclass.
|
||||
*
|
||||
* <p>
|
||||
* <code>Cacheable(false)</code> means that the entity and its state must
|
||||
* not be cached by the provider.
|
||||
*
|
||||
* @since Java Persistence 2.0
|
||||
*/
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cacheable {
|
||||
|
||||
/**
|
||||
* (Optional) Whether or not the entity should be cached.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int interval() default 0;
|
||||
|
||||
/**
|
||||
* DataSource是否直接返回对象的真实引用, 而不是copy一份
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean direct() default false;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,274 +1,274 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
|
||||
/**
|
||||
* MethodVisitor 的调试类
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class MethodDebugVisitor {
|
||||
|
||||
private final MethodVisitor visitor;
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
public MethodDebugVisitor setDebug(boolean d) {
|
||||
debug = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void debugLine() {
|
||||
if (!debug) return;
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
||||
|
||||
private static final String[] opcodes = new String[200]; //0 -18
|
||||
|
||||
static {
|
||||
try {
|
||||
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
||||
String name = field.getName();
|
||||
if (name.startsWith("ASM")) continue;
|
||||
if (name.startsWith("V1_")) continue;
|
||||
if (name.startsWith("ACC_")) continue;
|
||||
if (name.startsWith("T_")) continue;
|
||||
if (name.startsWith("H_")) continue;
|
||||
if (name.startsWith("F_")) continue;
|
||||
if (field.getType() != int.class) continue;
|
||||
opcodes[(int) (Integer) field.get(null)] = name;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex); //不可能会发生
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param visitor MethodVisitor
|
||||
*/
|
||||
public MethodDebugVisitor(MethodVisitor visitor) {
|
||||
//super(Opcodes.ASM5, visitor);
|
||||
this.visitor = visitor;
|
||||
}
|
||||
|
||||
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
|
||||
visitor.visitTryCatchBlock(start, end, handler, type);
|
||||
if (debug) System.out.println("mv.visitTryCatchBlock(label0, label1, label2, \"" + type + "\");");
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
||||
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
||||
if (debug) System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
||||
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
||||
if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
if (debug) System.out.println("mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
|
||||
return av;
|
||||
}
|
||||
|
||||
public void visitParameter(String name, int access) {
|
||||
visitor.visitParameter(name, access);
|
||||
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
||||
}
|
||||
|
||||
public void visitVarInsn(int opcode, int var) {
|
||||
visitor.visitVarInsn(opcode, var);
|
||||
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
||||
}
|
||||
|
||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
||||
visitor.visitFrame(type, nLocal, local, nStack, stack);
|
||||
if (debug) {
|
||||
String typestr = "" + type;
|
||||
if (type == -1) {
|
||||
typestr = "Opcodes.F_NEW";
|
||||
} else if (type == 1) {
|
||||
typestr = "Opcodes.F_APPEND";
|
||||
} else if (type == 2) {
|
||||
typestr = "Opcodes.F_CHOP";
|
||||
} else if (type == 3) {
|
||||
typestr = "Opcodes.F_SAME";
|
||||
} else if (type == 4) {
|
||||
typestr = "Opcodes.F_SAME1";
|
||||
}
|
||||
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", " + nStack + ", " + Arrays.toString(stack) + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
||||
visitor.visitJumpInsn(opcode, var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCode() {
|
||||
visitor.visitCode();
|
||||
if (debug) System.out.println("mv.visitCode();");
|
||||
}
|
||||
|
||||
public void visitLabel(Label var) {
|
||||
visitor.visitLabel(var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitLabel(l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");");
|
||||
}
|
||||
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||
visitor.visitFieldInsn(opcode, owner, name, desc);
|
||||
if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");");
|
||||
}
|
||||
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
visitor.visitTypeInsn(opcode, type);
|
||||
if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
||||
}
|
||||
|
||||
public void visitInsn(int opcode) {
|
||||
visitor.visitInsn(opcode);
|
||||
if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
||||
}
|
||||
|
||||
public void visitIntInsn(int opcode, int value) {
|
||||
visitor.visitIntInsn(opcode, value);
|
||||
if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
||||
}
|
||||
|
||||
public void visitIincInsn(int opcode, int value) {
|
||||
visitor.visitIincInsn(opcode, value);
|
||||
if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
||||
}
|
||||
|
||||
public void visitLdcInsn(Object o) {
|
||||
visitor.visitLdcInsn(o);
|
||||
if (debug) {
|
||||
if (o instanceof CharSequence) {
|
||||
System.out.println("mv.visitLdcInsn(\"" + o + "\");");
|
||||
} else if (o instanceof org.redkale.asm.Type) {
|
||||
System.out.println("mv.visitLdcInsn(Type.getType(\"" + o + "\"));");
|
||||
} else {
|
||||
System.out.println("mv.visitLdcInsn(" + o + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
visitor.visitMaxs(maxStack, maxLocals);
|
||||
if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
visitor.visitEnd();
|
||||
if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
||||
}
|
||||
|
||||
public static void pushInt(MethodDebugVisitor mv, int num) {
|
||||
if (num < 6) {
|
||||
mv.visitInsn(ICONST_0 + num);
|
||||
} else if (num <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(BIPUSH, num);
|
||||
} else if (num <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(SIPUSH, num);
|
||||
} else {
|
||||
mv.visitLdcInsn(num);
|
||||
}
|
||||
}
|
||||
|
||||
public static void pushInt(MethodVisitor mv, int num) {
|
||||
if (num < 6) {
|
||||
mv.visitInsn(ICONST_0 + num);
|
||||
} else if (num <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(BIPUSH, num);
|
||||
} else if (num <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(SIPUSH, num);
|
||||
} else {
|
||||
mv.visitLdcInsn(num);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitAnnotation(final AnnotationVisitor av, final Annotation ann) {
|
||||
try {
|
||||
for (Method anm : ann.annotationType().getMethods()) {
|
||||
final String mname = anm.getName();
|
||||
if ("equals".equals(mname) || "hashCode".equals(mname) || "toString".equals(mname) || "annotationType".equals(mname)) continue;
|
||||
final Object r = anm.invoke(ann);
|
||||
if (r instanceof String[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (String item : (String[]) r) {
|
||||
av1.visit(null, item);
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Class[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (Class item : (Class[]) r) {
|
||||
av1.visit(null, Type.getType(item));
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Enum[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (Enum item : (Enum[]) r) {
|
||||
av1.visitEnum(null, Type.getDescriptor(item.getClass()), ((Enum) item).name());
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Annotation[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (Annotation item : (Annotation[]) r) {
|
||||
visitAnnotation(av1.visitAnnotation(null, Type.getDescriptor(((Annotation) item).annotationType())), item);
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Class) {
|
||||
av.visit(mname, Type.getType((Class) r));
|
||||
} else if (r instanceof Enum) {
|
||||
av.visitEnum(mname, Type.getDescriptor(r.getClass()), ((Enum) r).name());
|
||||
} else if (r instanceof Annotation) {
|
||||
visitAnnotation(av.visitAnnotation(null, Type.getDescriptor(((Annotation) r).annotationType())), (Annotation) r);
|
||||
} else {
|
||||
av.visit(mname, r);
|
||||
}
|
||||
}
|
||||
av.visitEnd();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
|
||||
/**
|
||||
* MethodVisitor 的调试类
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class MethodDebugVisitor {
|
||||
|
||||
private final MethodVisitor visitor;
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
public MethodDebugVisitor setDebug(boolean d) {
|
||||
debug = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void debugLine() {
|
||||
if (!debug) return;
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
||||
|
||||
private static final String[] opcodes = new String[200]; //0 -18
|
||||
|
||||
static {
|
||||
try {
|
||||
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
||||
String name = field.getName();
|
||||
if (name.startsWith("ASM")) continue;
|
||||
if (name.startsWith("V1_")) continue;
|
||||
if (name.startsWith("ACC_")) continue;
|
||||
if (name.startsWith("T_")) continue;
|
||||
if (name.startsWith("H_")) continue;
|
||||
if (name.startsWith("F_")) continue;
|
||||
if (field.getType() != int.class) continue;
|
||||
opcodes[(int) (Integer) field.get(null)] = name;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex); //不可能会发生
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param visitor MethodVisitor
|
||||
*/
|
||||
public MethodDebugVisitor(MethodVisitor visitor) {
|
||||
//super(Opcodes.ASM5, visitor);
|
||||
this.visitor = visitor;
|
||||
}
|
||||
|
||||
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
|
||||
visitor.visitTryCatchBlock(start, end, handler, type);
|
||||
if (debug) System.out.println("mv.visitTryCatchBlock(label0, label1, label2, \"" + type + "\");");
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
||||
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
||||
if (debug) System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
||||
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
||||
if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
if (debug) System.out.println("mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
|
||||
return av;
|
||||
}
|
||||
|
||||
public void visitParameter(String name, int access) {
|
||||
visitor.visitParameter(name, access);
|
||||
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
||||
}
|
||||
|
||||
public void visitVarInsn(int opcode, int var) {
|
||||
visitor.visitVarInsn(opcode, var);
|
||||
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
||||
}
|
||||
|
||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
||||
visitor.visitFrame(type, nLocal, local, nStack, stack);
|
||||
if (debug) {
|
||||
String typestr = "" + type;
|
||||
if (type == -1) {
|
||||
typestr = "Opcodes.F_NEW";
|
||||
} else if (type == 1) {
|
||||
typestr = "Opcodes.F_APPEND";
|
||||
} else if (type == 2) {
|
||||
typestr = "Opcodes.F_CHOP";
|
||||
} else if (type == 3) {
|
||||
typestr = "Opcodes.F_SAME";
|
||||
} else if (type == 4) {
|
||||
typestr = "Opcodes.F_SAME1";
|
||||
}
|
||||
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", " + nStack + ", " + Arrays.toString(stack) + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
||||
visitor.visitJumpInsn(opcode, var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCode() {
|
||||
visitor.visitCode();
|
||||
if (debug) System.out.println("mv.visitCode();");
|
||||
}
|
||||
|
||||
public void visitLabel(Label var) {
|
||||
visitor.visitLabel(var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitLabel(l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");");
|
||||
}
|
||||
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||
visitor.visitFieldInsn(opcode, owner, name, desc);
|
||||
if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");");
|
||||
}
|
||||
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
visitor.visitTypeInsn(opcode, type);
|
||||
if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
||||
}
|
||||
|
||||
public void visitInsn(int opcode) {
|
||||
visitor.visitInsn(opcode);
|
||||
if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
||||
}
|
||||
|
||||
public void visitIntInsn(int opcode, int value) {
|
||||
visitor.visitIntInsn(opcode, value);
|
||||
if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
||||
}
|
||||
|
||||
public void visitIincInsn(int opcode, int value) {
|
||||
visitor.visitIincInsn(opcode, value);
|
||||
if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
||||
}
|
||||
|
||||
public void visitLdcInsn(Object o) {
|
||||
visitor.visitLdcInsn(o);
|
||||
if (debug) {
|
||||
if (o instanceof CharSequence) {
|
||||
System.out.println("mv.visitLdcInsn(\"" + o + "\");");
|
||||
} else if (o instanceof org.redkale.asm.Type) {
|
||||
System.out.println("mv.visitLdcInsn(Type.getType(\"" + o + "\"));");
|
||||
} else {
|
||||
System.out.println("mv.visitLdcInsn(" + o + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
visitor.visitMaxs(maxStack, maxLocals);
|
||||
if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
visitor.visitEnd();
|
||||
if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
||||
}
|
||||
|
||||
public static void pushInt(MethodDebugVisitor mv, int num) {
|
||||
if (num < 6) {
|
||||
mv.visitInsn(ICONST_0 + num);
|
||||
} else if (num <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(BIPUSH, num);
|
||||
} else if (num <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(SIPUSH, num);
|
||||
} else {
|
||||
mv.visitLdcInsn(num);
|
||||
}
|
||||
}
|
||||
|
||||
public static void pushInt(MethodVisitor mv, int num) {
|
||||
if (num < 6) {
|
||||
mv.visitInsn(ICONST_0 + num);
|
||||
} else if (num <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(BIPUSH, num);
|
||||
} else if (num <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(SIPUSH, num);
|
||||
} else {
|
||||
mv.visitLdcInsn(num);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitAnnotation(final AnnotationVisitor av, final Annotation ann) {
|
||||
try {
|
||||
for (Method anm : ann.annotationType().getMethods()) {
|
||||
final String mname = anm.getName();
|
||||
if ("equals".equals(mname) || "hashCode".equals(mname) || "toString".equals(mname) || "annotationType".equals(mname)) continue;
|
||||
final Object r = anm.invoke(ann);
|
||||
if (r instanceof String[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (String item : (String[]) r) {
|
||||
av1.visit(null, item);
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Class[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (Class item : (Class[]) r) {
|
||||
av1.visit(null, Type.getType(item));
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Enum[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (Enum item : (Enum[]) r) {
|
||||
av1.visitEnum(null, Type.getDescriptor(item.getClass()), ((Enum) item).name());
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Annotation[]) {
|
||||
AnnotationVisitor av1 = av.visitArray(mname);
|
||||
for (Annotation item : (Annotation[]) r) {
|
||||
visitAnnotation(av1.visitAnnotation(null, Type.getDescriptor(((Annotation) item).annotationType())), item);
|
||||
}
|
||||
av1.visitEnd();
|
||||
} else if (r instanceof Class) {
|
||||
av.visit(mname, Type.getType((Class) r));
|
||||
} else if (r instanceof Enum) {
|
||||
av.visitEnum(mname, Type.getDescriptor(r.getClass()), ((Enum) r).name());
|
||||
} else if (r instanceof Annotation) {
|
||||
visitAnnotation(av.visitAnnotation(null, Type.getDescriptor(((Annotation) r).annotationType())), (Annotation) r);
|
||||
} else {
|
||||
av.visit(mname, r);
|
||||
}
|
||||
}
|
||||
av.visitEnd();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
need copy classes:
|
||||
|
||||
AnnotationVisitor.java
|
||||
AnnotationWriter.java
|
||||
Attribute.java
|
||||
ByteVector.java
|
||||
ClassReader.java
|
||||
ClassVisitor.java
|
||||
ClassWriter.java
|
||||
Context.java
|
||||
CurrentFrame.java
|
||||
Edge.java
|
||||
FieldVisitor.java
|
||||
FieldWriter.java
|
||||
Frame.java
|
||||
Handle.java
|
||||
Handler.java
|
||||
Item.java
|
||||
Label.java
|
||||
MethodVisitor.java
|
||||
MethodWriter.java
|
||||
ModuleVisitor.java
|
||||
ModuleWriter.java
|
||||
Opcodes.java
|
||||
Type.java
|
||||
TypePath.java
|
||||
TypeReference.java
|
||||
need copy classes:
|
||||
|
||||
AnnotationVisitor.java
|
||||
AnnotationWriter.java
|
||||
Attribute.java
|
||||
ByteVector.java
|
||||
ClassReader.java
|
||||
ClassVisitor.java
|
||||
ClassWriter.java
|
||||
Context.java
|
||||
CurrentFrame.java
|
||||
Edge.java
|
||||
FieldVisitor.java
|
||||
FieldWriter.java
|
||||
Frame.java
|
||||
Handle.java
|
||||
Handler.java
|
||||
Item.java
|
||||
Label.java
|
||||
MethodVisitor.java
|
||||
MethodWriter.java
|
||||
ModuleVisitor.java
|
||||
ModuleWriter.java
|
||||
Opcodes.java
|
||||
Type.java
|
||||
TypePath.java
|
||||
TypeReference.java
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 本包下所有代码均是从/java.base/jdk/internal/org/objectweb/asm 拷贝过来的
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
/**
|
||||
* 本包下所有代码均是从/java.base/jdk/internal/org/objectweb/asm 拷贝过来的
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,69 +1,69 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* Application启动和关闭时的监听事件 <br>
|
||||
* 只能通过application.xml配置
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface ApplicationListener {
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*
|
||||
* @param config 配置参数
|
||||
*/
|
||||
default void init(AnyValue config) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行start前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void preStart(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行start后调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void postStart(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行Compile前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void preCompile(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行Compile后调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void postCompile(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行shutdown前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void preShutdown(Application application) {
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* Application启动和关闭时的监听事件 <br>
|
||||
* 只能通过application.xml配置
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface ApplicationListener {
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*
|
||||
* @param config 配置参数
|
||||
*/
|
||||
default void init(AnyValue config) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行start前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void preStart(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行start后调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void postStart(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行Compile前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void preCompile(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行Compile后调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void postCompile(Application application) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Application 在运行shutdown前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void preShutdown(Application application) {
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,372 +1,372 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 自定义的日志输出类
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LoggingFileHandler extends Handler {
|
||||
|
||||
//public static final String FORMATTER_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s%n%5$s%6$s%n";
|
||||
public static final String FORMATTER_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s\r\n%5$s%6$s\r\n";
|
||||
|
||||
/**
|
||||
* SNCP的日志输出Handler
|
||||
*/
|
||||
public static class LoggingSncpFileHandler extends LoggingFileHandler {
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "sncp-";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认的日志时间格式化类
|
||||
* 与SimpleFormatter的区别在于level不使用本地化
|
||||
*
|
||||
*/
|
||||
public static class LoggingFormater extends Formatter {
|
||||
|
||||
@Override
|
||||
public String format(LogRecord log) {
|
||||
String source;
|
||||
if (log.getSourceClassName() != null) {
|
||||
source = log.getSourceClassName();
|
||||
if (log.getSourceMethodName() != null) {
|
||||
source += " " + log.getSourceMethodName();
|
||||
}
|
||||
} else {
|
||||
source = log.getLoggerName();
|
||||
}
|
||||
String message = formatMessage(log);
|
||||
String throwable = "";
|
||||
if (log.getThrown() != null) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw) {
|
||||
@Override
|
||||
public void println() {
|
||||
super.print("\r\n");
|
||||
}
|
||||
};
|
||||
pw.println();
|
||||
log.getThrown().printStackTrace(pw);
|
||||
pw.close();
|
||||
throwable = sw.toString();
|
||||
}
|
||||
return String.format(FORMATTER_FORMAT,
|
||||
System.currentTimeMillis(),
|
||||
source,
|
||||
log.getLoggerName(),
|
||||
log.getLevel().getName(),
|
||||
message,
|
||||
throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initDebugLogConfig() {
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final PrintStream ps = new PrintStream(out);
|
||||
ps.println("handlers = java.util.logging.ConsoleHandler");
|
||||
ps.println(".level = FINEST");
|
||||
ps.println("jdk.level = INFO");
|
||||
ps.println("sun.level = INFO");
|
||||
ps.println("com.sun.level = INFO");
|
||||
ps.println("javax.level = INFO");
|
||||
ps.println("java.util.logging.ConsoleHandler.level = FINEST");
|
||||
ps.println("java.util.logging.ConsoleHandler.formatter = " + LoggingFileHandler.LoggingFormater.class.getName());
|
||||
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected final LinkedBlockingQueue<LogRecord> logqueue = new LinkedBlockingQueue();
|
||||
|
||||
private String pattern;
|
||||
|
||||
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||
|
||||
private int limit; //文件大小限制
|
||||
|
||||
private final AtomicInteger logindex = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger logunusualindex = new AtomicInteger();
|
||||
|
||||
private int count = 1; //文件限制
|
||||
|
||||
private long tomorrow;
|
||||
|
||||
private boolean append;
|
||||
|
||||
private Pattern denyreg;
|
||||
|
||||
private final AtomicLong loglength = new AtomicLong();
|
||||
|
||||
private final AtomicLong logunusuallength = new AtomicLong();
|
||||
|
||||
private File logfile;
|
||||
|
||||
private File logunusualfile;
|
||||
|
||||
private OutputStream logstream;
|
||||
|
||||
private OutputStream logunusualstream;
|
||||
|
||||
public LoggingFileHandler() {
|
||||
updateTomorrow();
|
||||
configure();
|
||||
open();
|
||||
}
|
||||
|
||||
private void updateTomorrow() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
long t = cal.getTimeInMillis();
|
||||
if (this.tomorrow != t) logindex.set(0);
|
||||
this.tomorrow = t;
|
||||
}
|
||||
|
||||
private void open() {
|
||||
final String name = "Redkale-Logging-" + getClass().getSimpleName() + "-Thread";
|
||||
new Thread() {
|
||||
{
|
||||
setName(name);
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
LogRecord log = logqueue.take();
|
||||
final boolean bigger = (limit > 0 && limit <= loglength.get());
|
||||
final boolean changeday = tomorrow <= log.getMillis();
|
||||
if (bigger || changeday) {
|
||||
updateTomorrow();
|
||||
if (logstream != null) {
|
||||
logstream.close();
|
||||
if (bigger) {
|
||||
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) {
|
||||
File greater = new File(logfile.getPath() + "." + i);
|
||||
if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
} else {
|
||||
if (logfile.exists() && logfile.length() < 1) logfile.delete();
|
||||
}
|
||||
logstream = null;
|
||||
}
|
||||
}
|
||||
if (unusual != null && changeday && logunusualstream != null) {
|
||||
logunusualstream.close();
|
||||
if (limit > 0 && limit <= logunusuallength.get()) {
|
||||
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) {
|
||||
File greater = new File(logunusualfile.getPath() + "." + i);
|
||||
if (greater.exists()) Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
} else {
|
||||
if (logunusualfile.exists() && logunusualfile.length() < 1) logunusualfile.delete();
|
||||
}
|
||||
logunusualstream = null;
|
||||
}
|
||||
if (logstream == null) {
|
||||
logindex.incrementAndGet();
|
||||
java.time.LocalDate date = LocalDate.now();
|
||||
logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||
logfile.getParentFile().mkdirs();
|
||||
loglength.set(logfile.length());
|
||||
logstream = new FileOutputStream(logfile, append);
|
||||
}
|
||||
if (unusual != null && logunusualstream == null) {
|
||||
logunusualindex.incrementAndGet();
|
||||
java.time.LocalDate date = LocalDate.now();
|
||||
logunusualfile = new File(unusual.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||
logunusualfile.getParentFile().mkdirs();
|
||||
logunusuallength.set(logunusualfile.length());
|
||||
logunusualstream = new FileOutputStream(logunusualfile, append);
|
||||
}
|
||||
//----------------------写日志-------------------------
|
||||
String message = getFormatter().format(log);
|
||||
String encoding = getEncoding();
|
||||
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
||||
logstream.write(bytes);
|
||||
loglength.addAndGet(bytes.length);
|
||||
if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) {
|
||||
logunusualstream.write(bytes);
|
||||
logunusuallength.addAndGet(bytes.length);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = LoggingFileHandler.class.getName();
|
||||
this.pattern = manager.getProperty(cname + ".pattern");
|
||||
if (this.pattern == null) {
|
||||
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
||||
} else {
|
||||
int pos = this.pattern.lastIndexOf('/');
|
||||
if (pos > 0) {
|
||||
this.pattern = this.pattern.substring(0, pos + 1) + getPrefix() + this.pattern.substring(pos + 1);
|
||||
} else {
|
||||
this.pattern = getPrefix() + this.pattern;
|
||||
}
|
||||
}
|
||||
String unusualstr = manager.getProperty(cname + ".unusual");
|
||||
if (unusualstr != null) {
|
||||
int pos = unusualstr.lastIndexOf('/');
|
||||
if (pos > 0) {
|
||||
this.unusual = unusualstr.substring(0, pos + 1) + getPrefix() + unusualstr.substring(pos + 1);
|
||||
} else {
|
||||
this.unusual = getPrefix() + unusualstr;
|
||||
}
|
||||
}
|
||||
String limitstr = manager.getProperty(cname + ".limit");
|
||||
try {
|
||||
if (limitstr != null) {
|
||||
limitstr = limitstr.toUpperCase();
|
||||
boolean g = limitstr.indexOf('G') > 0;
|
||||
boolean m = limitstr.indexOf('M') > 0;
|
||||
boolean k = limitstr.indexOf('K') > 0;
|
||||
int ls = Math.abs(Integer.decode(limitstr.replace("G", "").replace("M", "").replace("K", "").replace("B", "")));
|
||||
if (g) {
|
||||
ls *= 1024 * 1024 * 1024;
|
||||
} else if (m) {
|
||||
ls *= 1024 * 1024;
|
||||
} else if (k) {
|
||||
ls *= 1024;
|
||||
}
|
||||
this.limit = ls;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String countstr = manager.getProperty(cname + ".count");
|
||||
try {
|
||||
if (countstr != null) this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String appendstr = manager.getProperty(cname + ".append");
|
||||
try {
|
||||
if (appendstr != null) this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String levelstr = manager.getProperty(cname + ".level");
|
||||
try {
|
||||
if (levelstr != null) {
|
||||
Level l = Level.parse(levelstr);
|
||||
setLevel(l != null ? l : Level.ALL);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String filterstr = manager.getProperty(cname + ".filter");
|
||||
try {
|
||||
if (filterstr != null) {
|
||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
|
||||
setFilter((Filter) clz.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String formatterstr = manager.getProperty(cname + ".formatter");
|
||||
try {
|
||||
if (formatterstr != null) {
|
||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
|
||||
setFormatter((Formatter) clz.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (getFormatter() == null) setFormatter(new SimpleFormatter());
|
||||
|
||||
String encodingstr = manager.getProperty(cname + ".encoding");
|
||||
try {
|
||||
if (encodingstr != null) setEncoding(encodingstr);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
String denyregstr = manager.getProperty(cname + ".denyreg");
|
||||
try {
|
||||
if (denyregstr != null && !denyregstr.trim().isEmpty()) {
|
||||
denyreg = Pattern.compile(denyregstr);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(LogRecord log) {
|
||||
final String sourceClassName = log.getSourceClassName();
|
||||
if (sourceClassName == null || true) {
|
||||
StackTraceElement[] ses = new Throwable().getStackTrace();
|
||||
for (int i = 2; i < ses.length; i++) {
|
||||
if (ses[i].getClassName().startsWith("java.util.logging")) continue;
|
||||
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + ses[i].getClassName());
|
||||
log.setSourceMethodName(ses[i].getMethodName());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + sourceClassName);
|
||||
}
|
||||
if (denyreg != null && denyreg.matcher(log.getMessage()).find()) return;
|
||||
logqueue.offer(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
if (logstream != null) logstream.flush();
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
try {
|
||||
if (logstream != null) logstream.close();
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 自定义的日志输出类
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LoggingFileHandler extends Handler {
|
||||
|
||||
//public static final String FORMATTER_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s%n%5$s%6$s%n";
|
||||
public static final String FORMATTER_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s\r\n%5$s%6$s\r\n";
|
||||
|
||||
/**
|
||||
* SNCP的日志输出Handler
|
||||
*/
|
||||
public static class LoggingSncpFileHandler extends LoggingFileHandler {
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "sncp-";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认的日志时间格式化类
|
||||
* 与SimpleFormatter的区别在于level不使用本地化
|
||||
*
|
||||
*/
|
||||
public static class LoggingFormater extends Formatter {
|
||||
|
||||
@Override
|
||||
public String format(LogRecord log) {
|
||||
String source;
|
||||
if (log.getSourceClassName() != null) {
|
||||
source = log.getSourceClassName();
|
||||
if (log.getSourceMethodName() != null) {
|
||||
source += " " + log.getSourceMethodName();
|
||||
}
|
||||
} else {
|
||||
source = log.getLoggerName();
|
||||
}
|
||||
String message = formatMessage(log);
|
||||
String throwable = "";
|
||||
if (log.getThrown() != null) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw) {
|
||||
@Override
|
||||
public void println() {
|
||||
super.print("\r\n");
|
||||
}
|
||||
};
|
||||
pw.println();
|
||||
log.getThrown().printStackTrace(pw);
|
||||
pw.close();
|
||||
throwable = sw.toString();
|
||||
}
|
||||
return String.format(FORMATTER_FORMAT,
|
||||
System.currentTimeMillis(),
|
||||
source,
|
||||
log.getLoggerName(),
|
||||
log.getLevel().getName(),
|
||||
message,
|
||||
throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initDebugLogConfig() {
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final PrintStream ps = new PrintStream(out);
|
||||
ps.println("handlers = java.util.logging.ConsoleHandler");
|
||||
ps.println(".level = FINEST");
|
||||
ps.println("jdk.level = INFO");
|
||||
ps.println("sun.level = INFO");
|
||||
ps.println("com.sun.level = INFO");
|
||||
ps.println("javax.level = INFO");
|
||||
ps.println("java.util.logging.ConsoleHandler.level = FINEST");
|
||||
ps.println("java.util.logging.ConsoleHandler.formatter = " + LoggingFileHandler.LoggingFormater.class.getName());
|
||||
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected final LinkedBlockingQueue<LogRecord> logqueue = new LinkedBlockingQueue();
|
||||
|
||||
private String pattern;
|
||||
|
||||
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||
|
||||
private int limit; //文件大小限制
|
||||
|
||||
private final AtomicInteger logindex = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger logunusualindex = new AtomicInteger();
|
||||
|
||||
private int count = 1; //文件限制
|
||||
|
||||
private long tomorrow;
|
||||
|
||||
private boolean append;
|
||||
|
||||
private Pattern denyreg;
|
||||
|
||||
private final AtomicLong loglength = new AtomicLong();
|
||||
|
||||
private final AtomicLong logunusuallength = new AtomicLong();
|
||||
|
||||
private File logfile;
|
||||
|
||||
private File logunusualfile;
|
||||
|
||||
private OutputStream logstream;
|
||||
|
||||
private OutputStream logunusualstream;
|
||||
|
||||
public LoggingFileHandler() {
|
||||
updateTomorrow();
|
||||
configure();
|
||||
open();
|
||||
}
|
||||
|
||||
private void updateTomorrow() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
long t = cal.getTimeInMillis();
|
||||
if (this.tomorrow != t) logindex.set(0);
|
||||
this.tomorrow = t;
|
||||
}
|
||||
|
||||
private void open() {
|
||||
final String name = "Redkale-Logging-" + getClass().getSimpleName() + "-Thread";
|
||||
new Thread() {
|
||||
{
|
||||
setName(name);
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
LogRecord log = logqueue.take();
|
||||
final boolean bigger = (limit > 0 && limit <= loglength.get());
|
||||
final boolean changeday = tomorrow <= log.getMillis();
|
||||
if (bigger || changeday) {
|
||||
updateTomorrow();
|
||||
if (logstream != null) {
|
||||
logstream.close();
|
||||
if (bigger) {
|
||||
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) {
|
||||
File greater = new File(logfile.getPath() + "." + i);
|
||||
if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
} else {
|
||||
if (logfile.exists() && logfile.length() < 1) logfile.delete();
|
||||
}
|
||||
logstream = null;
|
||||
}
|
||||
}
|
||||
if (unusual != null && changeday && logunusualstream != null) {
|
||||
logunusualstream.close();
|
||||
if (limit > 0 && limit <= logunusuallength.get()) {
|
||||
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) {
|
||||
File greater = new File(logunusualfile.getPath() + "." + i);
|
||||
if (greater.exists()) Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
} else {
|
||||
if (logunusualfile.exists() && logunusualfile.length() < 1) logunusualfile.delete();
|
||||
}
|
||||
logunusualstream = null;
|
||||
}
|
||||
if (logstream == null) {
|
||||
logindex.incrementAndGet();
|
||||
java.time.LocalDate date = LocalDate.now();
|
||||
logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||
logfile.getParentFile().mkdirs();
|
||||
loglength.set(logfile.length());
|
||||
logstream = new FileOutputStream(logfile, append);
|
||||
}
|
||||
if (unusual != null && logunusualstream == null) {
|
||||
logunusualindex.incrementAndGet();
|
||||
java.time.LocalDate date = LocalDate.now();
|
||||
logunusualfile = new File(unusual.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||
logunusualfile.getParentFile().mkdirs();
|
||||
logunusuallength.set(logunusualfile.length());
|
||||
logunusualstream = new FileOutputStream(logunusualfile, append);
|
||||
}
|
||||
//----------------------写日志-------------------------
|
||||
String message = getFormatter().format(log);
|
||||
String encoding = getEncoding();
|
||||
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
||||
logstream.write(bytes);
|
||||
loglength.addAndGet(bytes.length);
|
||||
if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) {
|
||||
logunusualstream.write(bytes);
|
||||
logunusuallength.addAndGet(bytes.length);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = LoggingFileHandler.class.getName();
|
||||
this.pattern = manager.getProperty(cname + ".pattern");
|
||||
if (this.pattern == null) {
|
||||
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
||||
} else {
|
||||
int pos = this.pattern.lastIndexOf('/');
|
||||
if (pos > 0) {
|
||||
this.pattern = this.pattern.substring(0, pos + 1) + getPrefix() + this.pattern.substring(pos + 1);
|
||||
} else {
|
||||
this.pattern = getPrefix() + this.pattern;
|
||||
}
|
||||
}
|
||||
String unusualstr = manager.getProperty(cname + ".unusual");
|
||||
if (unusualstr != null) {
|
||||
int pos = unusualstr.lastIndexOf('/');
|
||||
if (pos > 0) {
|
||||
this.unusual = unusualstr.substring(0, pos + 1) + getPrefix() + unusualstr.substring(pos + 1);
|
||||
} else {
|
||||
this.unusual = getPrefix() + unusualstr;
|
||||
}
|
||||
}
|
||||
String limitstr = manager.getProperty(cname + ".limit");
|
||||
try {
|
||||
if (limitstr != null) {
|
||||
limitstr = limitstr.toUpperCase();
|
||||
boolean g = limitstr.indexOf('G') > 0;
|
||||
boolean m = limitstr.indexOf('M') > 0;
|
||||
boolean k = limitstr.indexOf('K') > 0;
|
||||
int ls = Math.abs(Integer.decode(limitstr.replace("G", "").replace("M", "").replace("K", "").replace("B", "")));
|
||||
if (g) {
|
||||
ls *= 1024 * 1024 * 1024;
|
||||
} else if (m) {
|
||||
ls *= 1024 * 1024;
|
||||
} else if (k) {
|
||||
ls *= 1024;
|
||||
}
|
||||
this.limit = ls;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String countstr = manager.getProperty(cname + ".count");
|
||||
try {
|
||||
if (countstr != null) this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String appendstr = manager.getProperty(cname + ".append");
|
||||
try {
|
||||
if (appendstr != null) this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String levelstr = manager.getProperty(cname + ".level");
|
||||
try {
|
||||
if (levelstr != null) {
|
||||
Level l = Level.parse(levelstr);
|
||||
setLevel(l != null ? l : Level.ALL);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String filterstr = manager.getProperty(cname + ".filter");
|
||||
try {
|
||||
if (filterstr != null) {
|
||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
|
||||
setFilter((Filter) clz.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String formatterstr = manager.getProperty(cname + ".formatter");
|
||||
try {
|
||||
if (formatterstr != null) {
|
||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
|
||||
setFormatter((Formatter) clz.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (getFormatter() == null) setFormatter(new SimpleFormatter());
|
||||
|
||||
String encodingstr = manager.getProperty(cname + ".encoding");
|
||||
try {
|
||||
if (encodingstr != null) setEncoding(encodingstr);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
String denyregstr = manager.getProperty(cname + ".denyreg");
|
||||
try {
|
||||
if (denyregstr != null && !denyregstr.trim().isEmpty()) {
|
||||
denyreg = Pattern.compile(denyregstr);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(LogRecord log) {
|
||||
final String sourceClassName = log.getSourceClassName();
|
||||
if (sourceClassName == null || true) {
|
||||
StackTraceElement[] ses = new Throwable().getStackTrace();
|
||||
for (int i = 2; i < ses.length; i++) {
|
||||
if (ses[i].getClassName().startsWith("java.util.logging")) continue;
|
||||
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + ses[i].getClassName());
|
||||
log.setSourceMethodName(ses[i].getMethodName());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + sourceClassName);
|
||||
}
|
||||
if (denyreg != null && denyreg.matcher(log.getMessage()).find()) return;
|
||||
logqueue.offer(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
if (logstream != null) logstream.flush();
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
try {
|
||||
if (logstream != null) logstream.close();
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
/**
|
||||
* NodeServer的拦截类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class NodeInterceptor {
|
||||
|
||||
/** *
|
||||
* Server.start之前调用 <br>
|
||||
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preStart(NodeServer server) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server.shutdown之前调用 <br>
|
||||
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.sshutdown 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preShutdown(NodeServer server) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
/**
|
||||
* NodeServer的拦截类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class NodeInterceptor {
|
||||
|
||||
/** *
|
||||
* Server.start之前调用 <br>
|
||||
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preStart(NodeServer server) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server.shutdown之前调用 <br>
|
||||
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.sshutdown 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preShutdown(NodeServer server) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface NodeProtocol {
|
||||
|
||||
String value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface NodeProtocol {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
@@ -1,125 +1,125 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.mq.MessageAgent;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||
|
||||
/**
|
||||
* SNCP Server节点的配置Server
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol("SNCP")
|
||||
public class NodeSncpServer extends NodeServer {
|
||||
|
||||
protected final SncpServer sncpServer;
|
||||
|
||||
private NodeSncpServer(Application application, AnyValue serconf) {
|
||||
super(application, createServer(application, serconf));
|
||||
this.sncpServer = (SncpServer) this.server;
|
||||
this.consumer = sncpServer == null || application.isSingletonMode() ? null : (agent, x) -> {//singleton模式下不生成SncpServlet
|
||||
if (x.getClass().getAnnotation(Local.class) != null) return; //本地模式的Service不生成SncpServlet
|
||||
SncpDynServlet servlet = sncpServer.addSncpServlet(x);
|
||||
dynServletMap.put(x, servlet);
|
||||
if (agent != null) agent.putService(this, x, servlet);
|
||||
};
|
||||
}
|
||||
|
||||
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
||||
return new NodeSncpServer(application, serconf);
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
return new SncpServer(application, application.getStartTime(), serconf, application.getResourceFactory().createChild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||
}
|
||||
|
||||
public void consumerAccept(MessageAgent messageAgent, Service service) {
|
||||
if (this.consumer != null) this.consumer.accept(messageAgent, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(AnyValue config) throws Exception {
|
||||
super.init(config);
|
||||
//-------------------------------------------------------------------
|
||||
if (sncpServer == null) return; //调试时server才可能为null
|
||||
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
||||
Collections.sort(servlets);
|
||||
for (SncpServlet en : servlets) {
|
||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(en).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSNCP() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public SncpServer getSncpServer() {
|
||||
return sncpServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadFilter(ClassFilter<? extends Filter> filterFilter, ClassFilter otherFilter) throws Exception {
|
||||
if (sncpServer != null) loadSncpFilter(this.serverConf.getAnyValue("fliters"), filterFilter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void loadSncpFilter(final AnyValue servletsConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
||||
for (FilterEntry<? extends Filter> en : list) {
|
||||
Class<SncpFilter> clazz = (Class<SncpFilter>) en.getType();
|
||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
|
||||
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
||||
resourceFactory.inject(filter, this);
|
||||
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
||||
this.sncpServer.addSncpFilter(filter, filterConf);
|
||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(clazz.getName()).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||
RedkaleClassLoader.putReflectionPublicClasses(SncpServlet.class.getName());
|
||||
RedkaleClassLoader.putReflectionPublicClasses(SncpDynServlet.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||
return createClassFilter(null, null, SncpFilter.class, new Class[]{org.redkale.watch.WatchFilter.class}, null, "filters", "filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.mq.MessageAgent;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||
|
||||
/**
|
||||
* SNCP Server节点的配置Server
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol("SNCP")
|
||||
public class NodeSncpServer extends NodeServer {
|
||||
|
||||
protected final SncpServer sncpServer;
|
||||
|
||||
private NodeSncpServer(Application application, AnyValue serconf) {
|
||||
super(application, createServer(application, serconf));
|
||||
this.sncpServer = (SncpServer) this.server;
|
||||
this.consumer = sncpServer == null || application.isSingletonMode() ? null : (agent, x) -> {//singleton模式下不生成SncpServlet
|
||||
if (x.getClass().getAnnotation(Local.class) != null) return; //本地模式的Service不生成SncpServlet
|
||||
SncpDynServlet servlet = sncpServer.addSncpServlet(x);
|
||||
dynServletMap.put(x, servlet);
|
||||
if (agent != null) agent.putService(this, x, servlet);
|
||||
};
|
||||
}
|
||||
|
||||
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
||||
return new NodeSncpServer(application, serconf);
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
return new SncpServer(application, application.getStartTime(), serconf, application.getResourceFactory().createChild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||
}
|
||||
|
||||
public void consumerAccept(MessageAgent messageAgent, Service service) {
|
||||
if (this.consumer != null) this.consumer.accept(messageAgent, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(AnyValue config) throws Exception {
|
||||
super.init(config);
|
||||
//-------------------------------------------------------------------
|
||||
if (sncpServer == null) return; //调试时server才可能为null
|
||||
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
||||
Collections.sort(servlets);
|
||||
for (SncpServlet en : servlets) {
|
||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(en).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSNCP() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public SncpServer getSncpServer() {
|
||||
return sncpServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadFilter(ClassFilter<? extends Filter> filterFilter, ClassFilter otherFilter) throws Exception {
|
||||
if (sncpServer != null) loadSncpFilter(this.serverConf.getAnyValue("fliters"), filterFilter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void loadSncpFilter(final AnyValue servletsConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
||||
for (FilterEntry<? extends Filter> en : list) {
|
||||
Class<SncpFilter> clazz = (Class<SncpFilter>) en.getType();
|
||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
|
||||
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
||||
resourceFactory.inject(filter, this);
|
||||
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
||||
this.sncpServer.addSncpFilter(filter, filterConf);
|
||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(clazz.getName()).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||
RedkaleClassLoader.putReflectionPublicClasses(SncpServlet.class.getName());
|
||||
RedkaleClassLoader.putReflectionPublicClasses(SncpDynServlet.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||
return createClassFilter(null, null, SncpFilter.class, new Class[]{org.redkale.watch.WatchFilter.class}, null, "filters", "filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.watch.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol("WATCH")
|
||||
public class NodeWatchServer extends NodeHttpServer {
|
||||
|
||||
public NodeWatchServer(Application application, AnyValue serconf) {
|
||||
super(application, serconf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Service> createServiceClassFilter() {
|
||||
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassFilter createOtherClassFilter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWATCH() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.watch.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol("WATCH")
|
||||
public class NodeWatchServer extends NodeHttpServer {
|
||||
|
||||
public NodeWatchServer(Application application, AnyValue serconf) {
|
||||
super(application, serconf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Service> createServiceClassFilter() {
|
||||
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassFilter createOtherClassFilter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWATCH() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import javax.persistence.Entity;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.convert.Decodeable;
|
||||
import org.redkale.convert.bson.BsonFactory;
|
||||
import org.redkale.convert.json.*;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 执行一次Application.run提前获取所有动态类
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class PrepareCompiler {
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// new PrepareCompiler().run();
|
||||
// }
|
||||
public Application run() throws Exception {
|
||||
final Application application = new Application(false, true, Application.loadAppConfig());
|
||||
application.init();
|
||||
for (ApplicationListener listener : application.listeners) {
|
||||
listener.preStart(application);
|
||||
}
|
||||
for (ApplicationListener listener : application.listeners) {
|
||||
listener.preCompile(application);
|
||||
}
|
||||
application.start();
|
||||
final boolean hasSncp = application.getNodeServers().stream().filter(v -> v instanceof NodeSncpServer).findFirst().isPresent();
|
||||
final String[] exlibs = (application.excludelibs != null ? (application.excludelibs + ";") : "").split(";");
|
||||
|
||||
final ClassFilter<?> entityFilter = new ClassFilter(application.getClassLoader(), Entity.class, Object.class, (Class[]) null);
|
||||
final ClassFilter<?> beanFilter = new ClassFilter(application.getClassLoader(), Bean.class, Object.class, (Class[]) null);
|
||||
final ClassFilter<?> filterFilter = new ClassFilter(application.getClassLoader(), null, FilterBean.class, (Class[]) null);
|
||||
|
||||
ClassFilter.Loader.load(application.getHome(), application.getClassLoader(), exlibs, entityFilter, beanFilter, filterFilter);
|
||||
|
||||
for (FilterEntry en : entityFilter.getFilterEntrys()) {
|
||||
Class clz = en.getType();
|
||||
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||
try {
|
||||
application.dataSources.forEach(source -> source.compile(clz));
|
||||
JsonFactory.root().loadEncoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadEncoder(clz);
|
||||
Decodeable decoder = JsonFactory.root().loadDecoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadDecoder(clz);
|
||||
decoder.convertFrom(new JsonReader("{}"));
|
||||
} catch (Exception e) { //JsonFactory.loadDecoder可能会失败,因为class可能包含抽象类字段,如ColumnValue.value字段
|
||||
}
|
||||
}
|
||||
for (FilterEntry en : beanFilter.getFilterEntrys()) {
|
||||
Class clz = en.getType();
|
||||
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||
try {
|
||||
JsonFactory.root().loadEncoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadEncoder(clz);
|
||||
Decodeable decoder = JsonFactory.root().loadDecoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadDecoder(clz);
|
||||
decoder.convertFrom(new JsonReader("{}"));
|
||||
} catch (Exception e) { //JsonFactory.loadDecoder可能会失败,因为class可能包含抽象类字段,如ColumnValue.value字段
|
||||
}
|
||||
}
|
||||
for (FilterEntry en : filterFilter.getFilterEntrys()) {
|
||||
Class clz = en.getType();
|
||||
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||
try {
|
||||
FilterNodeBean.load(clz);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
for (ApplicationListener listener : application.listeners) {
|
||||
listener.postCompile(application);
|
||||
}
|
||||
application.shutdown();
|
||||
return application;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import javax.persistence.Entity;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.convert.Decodeable;
|
||||
import org.redkale.convert.bson.BsonFactory;
|
||||
import org.redkale.convert.json.*;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 执行一次Application.run提前获取所有动态类
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class PrepareCompiler {
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// new PrepareCompiler().run();
|
||||
// }
|
||||
public Application run() throws Exception {
|
||||
final Application application = new Application(false, true, Application.loadAppConfig());
|
||||
application.init();
|
||||
for (ApplicationListener listener : application.listeners) {
|
||||
listener.preStart(application);
|
||||
}
|
||||
for (ApplicationListener listener : application.listeners) {
|
||||
listener.preCompile(application);
|
||||
}
|
||||
application.start();
|
||||
final boolean hasSncp = application.getNodeServers().stream().filter(v -> v instanceof NodeSncpServer).findFirst().isPresent();
|
||||
final String[] exlibs = (application.excludelibs != null ? (application.excludelibs + ";") : "").split(";");
|
||||
|
||||
final ClassFilter<?> entityFilter = new ClassFilter(application.getClassLoader(), Entity.class, Object.class, (Class[]) null);
|
||||
final ClassFilter<?> beanFilter = new ClassFilter(application.getClassLoader(), Bean.class, Object.class, (Class[]) null);
|
||||
final ClassFilter<?> filterFilter = new ClassFilter(application.getClassLoader(), null, FilterBean.class, (Class[]) null);
|
||||
|
||||
ClassFilter.Loader.load(application.getHome(), application.getClassLoader(), exlibs, entityFilter, beanFilter, filterFilter);
|
||||
|
||||
for (FilterEntry en : entityFilter.getFilterEntrys()) {
|
||||
Class clz = en.getType();
|
||||
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||
try {
|
||||
application.dataSources.forEach(source -> source.compile(clz));
|
||||
JsonFactory.root().loadEncoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadEncoder(clz);
|
||||
Decodeable decoder = JsonFactory.root().loadDecoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadDecoder(clz);
|
||||
decoder.convertFrom(new JsonReader("{}"));
|
||||
} catch (Exception e) { //JsonFactory.loadDecoder可能会失败,因为class可能包含抽象类字段,如ColumnValue.value字段
|
||||
}
|
||||
}
|
||||
for (FilterEntry en : beanFilter.getFilterEntrys()) {
|
||||
Class clz = en.getType();
|
||||
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||
try {
|
||||
JsonFactory.root().loadEncoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadEncoder(clz);
|
||||
Decodeable decoder = JsonFactory.root().loadDecoder(clz);
|
||||
if (hasSncp) BsonFactory.root().loadDecoder(clz);
|
||||
decoder.convertFrom(new JsonReader("{}"));
|
||||
} catch (Exception e) { //JsonFactory.loadDecoder可能会失败,因为class可能包含抽象类字段,如ColumnValue.value字段
|
||||
}
|
||||
}
|
||||
for (FilterEntry en : filterFilter.getFilterEntrys()) {
|
||||
Class clz = en.getType();
|
||||
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||
try {
|
||||
FilterNodeBean.load(clz);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
for (ApplicationListener listener : application.listeners) {
|
||||
listener.postCompile(application);
|
||||
}
|
||||
application.shutdown();
|
||||
return application;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,110 +1,110 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
|
||||
<style type="text/css">
|
||||
body {text-align: center;margin:auto;}
|
||||
a{text-decoration: none;}
|
||||
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
||||
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
|
||||
.table td {text-align: left;}
|
||||
.s {font-size: 0.8rem; vertical-align: middle;}
|
||||
.subtable {border-spacing: 0;border: 0;margin:0;}
|
||||
.subtable td{border: 0;padding: 0 0 0 10px;}
|
||||
.typetable {border-spacing: 0;border: 0;margin:0;}
|
||||
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
|
||||
.typetable .l{border-bottom: 1px solid red;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var createhtml = function (jsoncontent) {
|
||||
var classmap = jsoncontent.types;
|
||||
var html = [];
|
||||
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
||||
html.push('<br/><br/><table class="table" align="center">');
|
||||
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
||||
var servlets = jsoncontent.servers[i].servlets;
|
||||
if (servlets.length && (servlets[0].comment || "").indexOf("【") === 0) {
|
||||
servlets.sort(function (a, b) {
|
||||
return a.comment > b.comment ? -1 : (a.comment == b.comment ? 0 : 1);
|
||||
});
|
||||
}
|
||||
for (var j = 0; j < servlets.length; j++) {
|
||||
var servlet = servlets[j];
|
||||
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
|
||||
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
||||
for (var k = 0; k < servlet.mappings.length; k++) {
|
||||
var action = servlet.mappings[k];
|
||||
html.push(' <tr>');
|
||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||
html.push('<td>' + action.comment + '</td>');
|
||||
html.push('<td class="s" style="width:80px;">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
||||
var paramshtml = [];
|
||||
paramshtml.push('<table class="subtable">');
|
||||
for (var p = 0; p < action.params.length; p++) {
|
||||
var param = action.params[p];
|
||||
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
|
||||
if (classmap[param.type.replace('[]', '')]) {
|
||||
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
|
||||
}
|
||||
if (param.name == '&') {
|
||||
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
||||
} else {
|
||||
var w = param.required ? "font-weight:bold;" : "";
|
||||
var c = ' style="' + w + '"';
|
||||
if (param.style == "HEADER") c = ' style="color:red;' + w + '"';
|
||||
if (param.style == "COOKIE") c = ' style="color:blue;' + w + '"';
|
||||
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
||||
}
|
||||
}
|
||||
paramshtml.push('</table>');
|
||||
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
||||
var rs = [];
|
||||
rs.push(action.result.replace(/</g, "<").replace(/>/g, ">").replace(/([a-zA-Z0-9_\$]+\.)+/g, ""));
|
||||
var results = action.results || [];
|
||||
for (var r = 0; r < results.length; r++) {
|
||||
rs.push('<a href="#' + results[r].replace('[]', '') + '">' + results[r].replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</a>');
|
||||
}
|
||||
html.push('<td>' + rs.join("<br/>") + '</td>');
|
||||
html.push('</tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var type in classmap) {
|
||||
html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr id="' + type + '"><th colspan="5" style="border-top:0;">' + type + '</th></tr>');
|
||||
html.push(' <tr><td colspan="5"><table class="typetable">');
|
||||
for (var fieldname in classmap[type]) {
|
||||
var field = classmap[type][fieldname];
|
||||
var t = field.type.replace(/</g, "<").replace(/>/g, ">").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
||||
if (t == 'boolean' || t == 'short' || t == 'int' || t == 'long' || t == 'float' || t == 'double'
|
||||
|| t == 'boolean[]' || t == 'short[]' || t == 'int[]' || t == 'long[]' || t == 'float[]' || t == 'double[]') {
|
||||
t = '<font color=blue>' + t + '</font>';
|
||||
} else if (t == 'String' || t == 'String[]' || t == 'LongRange' || t.indexOf('Map<') === 0) {
|
||||
t = '<font color=red>' + t + '</font>';
|
||||
}
|
||||
var c = (field.comment || '');
|
||||
if (field.primary) {
|
||||
c = '【主键】 ' + c;
|
||||
} else if (!field.updatable) {
|
||||
c = '【只读】 ' + c;
|
||||
}
|
||||
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + c + '</td></tr>');
|
||||
}
|
||||
html.push(' </table></td></tr>');
|
||||
}
|
||||
html.push('</table><br/><br/><br/>');
|
||||
html.push('</div>');
|
||||
return html.join('');
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var jsoncontent = '${content}'; //这里必须要用单引号引起来
|
||||
document.write(createhtml(jsoncontent));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
|
||||
<style type="text/css">
|
||||
body {text-align: center;margin:auto;}
|
||||
a{text-decoration: none;}
|
||||
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
||||
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
|
||||
.table td {text-align: left;}
|
||||
.s {font-size: 0.8rem; vertical-align: middle;}
|
||||
.subtable {border-spacing: 0;border: 0;margin:0;}
|
||||
.subtable td{border: 0;padding: 0 0 0 10px;}
|
||||
.typetable {border-spacing: 0;border: 0;margin:0;}
|
||||
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
|
||||
.typetable .l{border-bottom: 1px solid red;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var createhtml = function (jsoncontent) {
|
||||
var classmap = jsoncontent.types;
|
||||
var html = [];
|
||||
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
||||
html.push('<br/><br/><table class="table" align="center">');
|
||||
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
||||
var servlets = jsoncontent.servers[i].servlets;
|
||||
if (servlets.length && (servlets[0].comment || "").indexOf("【") === 0) {
|
||||
servlets.sort(function (a, b) {
|
||||
return a.comment > b.comment ? -1 : (a.comment == b.comment ? 0 : 1);
|
||||
});
|
||||
}
|
||||
for (var j = 0; j < servlets.length; j++) {
|
||||
var servlet = servlets[j];
|
||||
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
|
||||
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
||||
for (var k = 0; k < servlet.mappings.length; k++) {
|
||||
var action = servlet.mappings[k];
|
||||
html.push(' <tr>');
|
||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||
html.push('<td>' + action.comment + '</td>');
|
||||
html.push('<td class="s" style="width:80px;">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
||||
var paramshtml = [];
|
||||
paramshtml.push('<table class="subtable">');
|
||||
for (var p = 0; p < action.params.length; p++) {
|
||||
var param = action.params[p];
|
||||
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
|
||||
if (classmap[param.type.replace('[]', '')]) {
|
||||
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
|
||||
}
|
||||
if (param.name == '&') {
|
||||
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
||||
} else {
|
||||
var w = param.required ? "font-weight:bold;" : "";
|
||||
var c = ' style="' + w + '"';
|
||||
if (param.style == "HEADER") c = ' style="color:red;' + w + '"';
|
||||
if (param.style == "COOKIE") c = ' style="color:blue;' + w + '"';
|
||||
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
||||
}
|
||||
}
|
||||
paramshtml.push('</table>');
|
||||
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
||||
var rs = [];
|
||||
rs.push(action.result.replace(/</g, "<").replace(/>/g, ">").replace(/([a-zA-Z0-9_\$]+\.)+/g, ""));
|
||||
var results = action.results || [];
|
||||
for (var r = 0; r < results.length; r++) {
|
||||
rs.push('<a href="#' + results[r].replace('[]', '') + '">' + results[r].replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</a>');
|
||||
}
|
||||
html.push('<td>' + rs.join("<br/>") + '</td>');
|
||||
html.push('</tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var type in classmap) {
|
||||
html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr id="' + type + '"><th colspan="5" style="border-top:0;">' + type + '</th></tr>');
|
||||
html.push(' <tr><td colspan="5"><table class="typetable">');
|
||||
for (var fieldname in classmap[type]) {
|
||||
var field = classmap[type][fieldname];
|
||||
var t = field.type.replace(/</g, "<").replace(/>/g, ">").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
||||
if (t == 'boolean' || t == 'short' || t == 'int' || t == 'long' || t == 'float' || t == 'double'
|
||||
|| t == 'boolean[]' || t == 'short[]' || t == 'int[]' || t == 'long[]' || t == 'float[]' || t == 'double[]') {
|
||||
t = '<font color=blue>' + t + '</font>';
|
||||
} else if (t == 'String' || t == 'String[]' || t == 'LongRange' || t.indexOf('Map<') === 0) {
|
||||
t = '<font color=red>' + t + '</font>';
|
||||
}
|
||||
var c = (field.comment || '');
|
||||
if (field.primary) {
|
||||
c = '【主键】 ' + c;
|
||||
} else if (!field.updatable) {
|
||||
c = '【只读】 ' + c;
|
||||
}
|
||||
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + c + '</td></tr>');
|
||||
}
|
||||
html.push(' </table></td></tr>');
|
||||
}
|
||||
html.push('</table><br/><br/><br/>');
|
||||
html.push('</div>');
|
||||
return html.join('');
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var jsoncontent = '${content}'; //这里必须要用单引号引起来
|
||||
document.write(createhtml(jsoncontent));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 提供Redkale服务器的启动、初始化和加载功能
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
/**
|
||||
* 提供Redkale服务器的启动、初始化和加载功能
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import org.redkale.service.AbstractService;
|
||||
import org.redkale.util.Comment;
|
||||
import org.redkale.watch.WatchService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
||||
|
||||
@Comment("缺少参数")
|
||||
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
||||
|
||||
@Comment("执行异常")
|
||||
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import org.redkale.service.AbstractService;
|
||||
import org.redkale.util.Comment;
|
||||
import org.redkale.watch.WatchService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
||||
|
||||
@Comment("缺少参数")
|
||||
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
||||
|
||||
@Comment("执行异常")
|
||||
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
||||
}
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
import org.redkale.util.Comment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "filter", catalog = "watch", repair = false)
|
||||
public class FilterWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("Filter类名不存在")
|
||||
public static final int RET_FILTER_TYPE_NOT_EXISTS = 1601_0002;
|
||||
|
||||
@Comment("Filter类名不合法")
|
||||
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
|
||||
|
||||
@Comment("Filter类名已存在")
|
||||
public static final int RET_FILTER_EXISTS = 1601_0004;
|
||||
|
||||
@Comment("Filter的JAR包不存在")
|
||||
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
|
||||
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
|
||||
@RestParam(name = "server", comment = "Server节点名") final String serverName,
|
||||
@RestParam(name = "type", comment = "Filter类名") final String filterType) throws IOException {
|
||||
if (filterType == null) return new RetResult(RET_FILTER_TYPE_NOT_EXISTS, "Not found Filter Type (" + filterType + ")");
|
||||
if (jar == null) return new RetResult(RET_FILTER_JAR_ILLEGAL, "Not found jar file");
|
||||
List<NodeServer> nodes = application.getNodeServers();
|
||||
for (NodeServer node : nodes) {
|
||||
if (node.getServer().containsFilter(filterType)) return new RetResult(RET_FILTER_EXISTS, "Filter(" + filterType + ") exists");
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||
public RetResult test1() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||
public RetResult test2() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||
public RetResult test3() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||
public RetResult test4() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||
public RetResult test5() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||
public RetResult test6() {
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
import org.redkale.util.Comment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "filter", catalog = "watch", repair = false)
|
||||
public class FilterWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("Filter类名不存在")
|
||||
public static final int RET_FILTER_TYPE_NOT_EXISTS = 1601_0002;
|
||||
|
||||
@Comment("Filter类名不合法")
|
||||
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
|
||||
|
||||
@Comment("Filter类名已存在")
|
||||
public static final int RET_FILTER_EXISTS = 1601_0004;
|
||||
|
||||
@Comment("Filter的JAR包不存在")
|
||||
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
|
||||
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
|
||||
@RestParam(name = "server", comment = "Server节点名") final String serverName,
|
||||
@RestParam(name = "type", comment = "Filter类名") final String filterType) throws IOException {
|
||||
if (filterType == null) return new RetResult(RET_FILTER_TYPE_NOT_EXISTS, "Not found Filter Type (" + filterType + ")");
|
||||
if (jar == null) return new RetResult(RET_FILTER_JAR_ILLEGAL, "Not found jar file");
|
||||
List<NodeServer> nodes = application.getNodeServers();
|
||||
for (NodeServer node : nodes) {
|
||||
if (node.getServer().containsFilter(filterType)) return new RetResult(RET_FILTER_EXISTS, "Filter(" + filterType + ") exists");
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||
public RetResult test1() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||
public RetResult test2() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||
public RetResult test3() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||
public RetResult test4() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||
public RetResult test5() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||
public RetResult test6() {
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +1,104 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.Server;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
import org.redkale.util.Comment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "server", catalog = "watch", repair = false)
|
||||
public class ServerWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("不存在的Server节点")
|
||||
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
||||
|
||||
@Comment("更改Server监听地址端口失败")
|
||||
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "info", comment = "单个Server信息查询")
|
||||
public RetResult info(@RestParam(name = "#port:") final int port) {
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port).findFirst().orElse(null);
|
||||
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
||||
return new RetResult(formatToMap(node));
|
||||
}
|
||||
|
||||
@RestMapping(name = "infos", comment = "Server信息查询")
|
||||
public RetResult infos() {
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
Server server = ns.getServer();
|
||||
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
||||
}
|
||||
return new RetResult(rs);
|
||||
}
|
||||
|
||||
@RestMapping(name = "changeAddress", comment = "更改Server的监听地址和端口")
|
||||
public RetResult changeAddress(@RestParam(name = "#port:") final int oldport,
|
||||
@RestParam(name = "#newhost:") final String newhost, @RestParam(name = "#newport:") final int newport) {
|
||||
if (oldport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
||||
if (newport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport).findFirst().orElse(null);
|
||||
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
||||
final Server server = node.getServer();
|
||||
InetSocketAddress newAddr = new InetSocketAddress(newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
||||
try {
|
||||
server.changeAddress(application, newAddr);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeaddress error");
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
private Map<String, Object> formatToMap(NodeServer node) {
|
||||
Server server = node.getServer();
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
String protocol = server.getNetprotocol();
|
||||
if (node instanceof NodeSncpServer) {
|
||||
protocol += "/SNCP";
|
||||
} else if (node instanceof NodeWatchServer) {
|
||||
protocol += "/WATCH";
|
||||
} else if (node instanceof NodeHttpServer) {
|
||||
protocol += "/HTTP";
|
||||
} else {
|
||||
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
||||
protocol += "/" + np.value();
|
||||
}
|
||||
rs.put("name", server.getName());
|
||||
rs.put("protocol", protocol);
|
||||
rs.put("address", server.getSocketAddress());
|
||||
rs.put("backlog", server.getBacklog());
|
||||
rs.put("bufferCapacity", server.getBufferCapacity());
|
||||
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
||||
rs.put("charset", server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
||||
rs.put("maxbody", server.getMaxbody());
|
||||
rs.put("maxconns", server.getMaxconns());
|
||||
rs.put("serverStartTime", server.getServerStartTime());
|
||||
rs.put("responsePoolSize", server.getResponsePoolSize());
|
||||
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
||||
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
||||
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
||||
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
||||
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.Server;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
import org.redkale.util.Comment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "server", catalog = "watch", repair = false)
|
||||
public class ServerWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("不存在的Server节点")
|
||||
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
||||
|
||||
@Comment("更改Server监听地址端口失败")
|
||||
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "info", comment = "单个Server信息查询")
|
||||
public RetResult info(@RestParam(name = "#port:") final int port) {
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port).findFirst().orElse(null);
|
||||
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
||||
return new RetResult(formatToMap(node));
|
||||
}
|
||||
|
||||
@RestMapping(name = "infos", comment = "Server信息查询")
|
||||
public RetResult infos() {
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
Server server = ns.getServer();
|
||||
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
||||
}
|
||||
return new RetResult(rs);
|
||||
}
|
||||
|
||||
@RestMapping(name = "changeAddress", comment = "更改Server的监听地址和端口")
|
||||
public RetResult changeAddress(@RestParam(name = "#port:") final int oldport,
|
||||
@RestParam(name = "#newhost:") final String newhost, @RestParam(name = "#newport:") final int newport) {
|
||||
if (oldport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
||||
if (newport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport).findFirst().orElse(null);
|
||||
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
||||
final Server server = node.getServer();
|
||||
InetSocketAddress newAddr = new InetSocketAddress(newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
||||
try {
|
||||
server.changeAddress(application, newAddr);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeaddress error");
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
private Map<String, Object> formatToMap(NodeServer node) {
|
||||
Server server = node.getServer();
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
String protocol = server.getNetprotocol();
|
||||
if (node instanceof NodeSncpServer) {
|
||||
protocol += "/SNCP";
|
||||
} else if (node instanceof NodeWatchServer) {
|
||||
protocol += "/WATCH";
|
||||
} else if (node instanceof NodeHttpServer) {
|
||||
protocol += "/HTTP";
|
||||
} else {
|
||||
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
||||
protocol += "/" + np.value();
|
||||
}
|
||||
rs.put("name", server.getName());
|
||||
rs.put("protocol", protocol);
|
||||
rs.put("address", server.getSocketAddress());
|
||||
rs.put("backlog", server.getBacklog());
|
||||
rs.put("bufferCapacity", server.getBufferCapacity());
|
||||
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
||||
rs.put("charset", server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
||||
rs.put("maxbody", server.getMaxbody());
|
||||
rs.put("maxconns", server.getMaxconns());
|
||||
rs.put("serverStartTime", server.getServerStartTime());
|
||||
rs.put("responsePoolSize", server.getResponsePoolSize());
|
||||
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
||||
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
||||
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
||||
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
||||
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,199 +1,199 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "service", catalog = "watch", repair = false)
|
||||
public class ServiceWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("没有找到目标Service")
|
||||
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "setField", auth = false, comment = "设置Service中指定字段的内容")
|
||||
public RetResult setField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "field", comment = "字段名") String field,
|
||||
@RestParam(name = "value", comment = "字段值") String value) {
|
||||
if (name == null) name = "";
|
||||
if (type == null) type = "";
|
||||
if (field == null) field = "";
|
||||
type = type.trim();
|
||||
field = field.trim();
|
||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
try {
|
||||
Field fieldObj = null;
|
||||
do {
|
||||
try {
|
||||
fieldObj = clazz.getDeclaredField(field);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) t = e;
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||
fieldObj.setAccessible(true);
|
||||
fieldObj.set(dest, JsonConvert.root().convertFrom(fieldObj.getGenericType(), value));
|
||||
return RetResult.success();
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "getField", auth = false, comment = "查询Service中指定字段的内容")
|
||||
public RetResult getField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "field", comment = "字段名") String field) {
|
||||
if (name == null) name = "";
|
||||
if (type == null) type = "";
|
||||
if (field == null) field = "";
|
||||
type = type.trim();
|
||||
field = field.trim();
|
||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
try {
|
||||
Field fieldObj = null;
|
||||
do {
|
||||
try {
|
||||
fieldObj = clazz.getDeclaredField(field);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) t = e;
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||
fieldObj.setAccessible(true);
|
||||
return new RetResult(fieldObj.get(dest));
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "runMethod", auth = false, comment = "调用Service中指定方法")
|
||||
public RetResult runMethod(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "method", comment = "Service的方法名") String method,
|
||||
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
||||
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
||||
if (name == null) name = "";
|
||||
if (type == null) type = "";
|
||||
if (method == null) method = "";
|
||||
type = type.trim();
|
||||
method = method.trim();
|
||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
if (method.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
final int paramcount = params == null ? 0 : params.size();
|
||||
if (paramtypes != null && paramcount != paramtypes.size()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
||||
try {
|
||||
Method methodObj = null;
|
||||
do {
|
||||
try {
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
||||
boolean flag = true;
|
||||
if (paramtypes != null) {
|
||||
Class[] pts = m.getParameterTypes();
|
||||
for (int i = 0; i < pts.length; i++) {
|
||||
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
methodObj = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (methodObj != null) break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) t = e;
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (methodObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t)) + ")");
|
||||
methodObj.setAccessible(true);
|
||||
if (paramcount < 1) return new RetResult(methodObj.invoke(dest));
|
||||
Object[] paramObjs = new Object[paramcount];
|
||||
Type[] pts = methodObj.getGenericParameterTypes();
|
||||
for (int i = 0; i < paramObjs.length; i++) {
|
||||
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
||||
}
|
||||
return new RetResult(methodObj.invoke(dest, paramObjs));
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
protected Object findService(String name, String type) {
|
||||
Object dest = null;
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
ResourceFactory resFactory = ns.getResourceFactory();
|
||||
List list = resFactory.query((n, s) -> name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
||||
if (list == null || list.isEmpty()) continue;
|
||||
dest = list.get(0);
|
||||
}
|
||||
if (dest == null) return new RetResult(RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
||||
return dest;
|
||||
}
|
||||
|
||||
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
|
||||
public RetResult loadService(@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "reloadService", auth = false, comment = "重新加载Service")
|
||||
public RetResult reloadService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "stopService", auth = false, comment = "动态停止Service")
|
||||
public RetResult stopService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "findService", auth = false, comment = "查找Service")
|
||||
public RetResult find(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "service", catalog = "watch", repair = false)
|
||||
public class ServiceWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("没有找到目标Service")
|
||||
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "setField", auth = false, comment = "设置Service中指定字段的内容")
|
||||
public RetResult setField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "field", comment = "字段名") String field,
|
||||
@RestParam(name = "value", comment = "字段值") String value) {
|
||||
if (name == null) name = "";
|
||||
if (type == null) type = "";
|
||||
if (field == null) field = "";
|
||||
type = type.trim();
|
||||
field = field.trim();
|
||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
try {
|
||||
Field fieldObj = null;
|
||||
do {
|
||||
try {
|
||||
fieldObj = clazz.getDeclaredField(field);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) t = e;
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||
fieldObj.setAccessible(true);
|
||||
fieldObj.set(dest, JsonConvert.root().convertFrom(fieldObj.getGenericType(), value));
|
||||
return RetResult.success();
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "getField", auth = false, comment = "查询Service中指定字段的内容")
|
||||
public RetResult getField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "field", comment = "字段名") String field) {
|
||||
if (name == null) name = "";
|
||||
if (type == null) type = "";
|
||||
if (field == null) field = "";
|
||||
type = type.trim();
|
||||
field = field.trim();
|
||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
try {
|
||||
Field fieldObj = null;
|
||||
do {
|
||||
try {
|
||||
fieldObj = clazz.getDeclaredField(field);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) t = e;
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||
fieldObj.setAccessible(true);
|
||||
return new RetResult(fieldObj.get(dest));
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "runMethod", auth = false, comment = "调用Service中指定方法")
|
||||
public RetResult runMethod(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "method", comment = "Service的方法名") String method,
|
||||
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
||||
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
||||
if (name == null) name = "";
|
||||
if (type == null) type = "";
|
||||
if (method == null) method = "";
|
||||
type = type.trim();
|
||||
method = method.trim();
|
||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
if (method.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
final int paramcount = params == null ? 0 : params.size();
|
||||
if (paramtypes != null && paramcount != paramtypes.size()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
||||
try {
|
||||
Method methodObj = null;
|
||||
do {
|
||||
try {
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
||||
boolean flag = true;
|
||||
if (paramtypes != null) {
|
||||
Class[] pts = m.getParameterTypes();
|
||||
for (int i = 0; i < pts.length; i++) {
|
||||
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
methodObj = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (methodObj != null) break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) t = e;
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (methodObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t)) + ")");
|
||||
methodObj.setAccessible(true);
|
||||
if (paramcount < 1) return new RetResult(methodObj.invoke(dest));
|
||||
Object[] paramObjs = new Object[paramcount];
|
||||
Type[] pts = methodObj.getGenericParameterTypes();
|
||||
for (int i = 0; i < paramObjs.length; i++) {
|
||||
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
||||
}
|
||||
return new RetResult(methodObj.invoke(dest, paramObjs));
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
protected Object findService(String name, String type) {
|
||||
Object dest = null;
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
ResourceFactory resFactory = ns.getResourceFactory();
|
||||
List list = resFactory.query((n, s) -> name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
||||
if (list == null || list.isEmpty()) continue;
|
||||
dest = list.get(0);
|
||||
}
|
||||
if (dest == null) return new RetResult(RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
||||
return dest;
|
||||
}
|
||||
|
||||
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
|
||||
public RetResult loadService(@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "reloadService", auth = false, comment = "重新加载Service")
|
||||
public RetResult reloadService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "stopService", auth = false, comment = "动态停止Service")
|
||||
public RetResult stopService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "findService", auth = false, comment = "查找Service")
|
||||
public RetResult find(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
//待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.Application;
|
||||
import org.redkale.net.TransportFactory;
|
||||
import org.redkale.net.http.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "servlet", catalog = "watch", repair = false)
|
||||
public class ServletWatchService extends AbstractWatchService {
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@Resource
|
||||
protected TransportFactory transportFactory;
|
||||
//
|
||||
// @RestMapping(name = "loadServlet", auth = false, comment = "动态增加Servlet")
|
||||
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||
// //待开发
|
||||
// return RetResult.success();
|
||||
// }
|
||||
//
|
||||
// @RestMapping(name = "stopServlet", auth = false, comment = "动态停止Servlet")
|
||||
// public RetResult stopServlet(String type) {
|
||||
// //待开发
|
||||
// return RetResult.success();
|
||||
// }
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.Application;
|
||||
import org.redkale.net.TransportFactory;
|
||||
import org.redkale.net.http.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "servlet", catalog = "watch", repair = false)
|
||||
public class ServletWatchService extends AbstractWatchService {
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@Resource
|
||||
protected TransportFactory transportFactory;
|
||||
//
|
||||
// @RestMapping(name = "loadServlet", auth = false, comment = "动态增加Servlet")
|
||||
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||
// //待开发
|
||||
// return RetResult.success();
|
||||
// }
|
||||
//
|
||||
// @RestMapping(name = "stopServlet", auth = false, comment = "动态停止Servlet")
|
||||
// public RetResult stopServlet(String type) {
|
||||
// //待开发
|
||||
// return RetResult.success();
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,140 +1,140 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.AsynchronousSocketChannel;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.Application;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "transport", catalog = "watch", repair = false)
|
||||
public class TransportWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("不存在的Group节点")
|
||||
public static final int RET_TRANSPORT_GROUP_NOT_EXISTS = 1606_0001;
|
||||
|
||||
@Comment("非法的Node节点IP地址")
|
||||
public static final int RET_TRANSPORT_ADDR_ILLEGAL = 1606_0002;
|
||||
|
||||
@Comment("Node节点IP地址已存在")
|
||||
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@Resource
|
||||
protected TransportFactory transportFactory;
|
||||
|
||||
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
|
||||
public List<TransportGroupInfo> listNodes() {
|
||||
return transportFactory.getGroupInfos();
|
||||
}
|
||||
|
||||
@RestMapping(name = "addnode", auth = false, comment = "动态增加指定Group的Node节点")
|
||||
public RetResult addNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
||||
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
||||
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
||||
InetSocketAddress address;
|
||||
try {
|
||||
address = new InetSocketAddress(addr, port);
|
||||
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
|
||||
channel.connect(address).get(2, TimeUnit.SECONDS); //连接超时2秒
|
||||
channel.close();
|
||||
} catch (Exception e) {
|
||||
return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is illegal or cannot connect");
|
||||
}
|
||||
if (transportFactory.findGroupName(address) != null) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is exists");
|
||||
synchronized (this) {
|
||||
if (transportFactory.findGroupInfo(group) == null) {
|
||||
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||
}
|
||||
transportFactory.addGroupInfo(group, address);
|
||||
for (Service service : transportFactory.getServices()) {
|
||||
if (!Sncp.isSncpDyn(service)) continue;
|
||||
SncpClient client = Sncp.getSncpClient(service);
|
||||
if (Sncp.isRemote(service)) {
|
||||
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
||||
client.getRemoteGroupTransport().addRemoteAddresses(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
DefaultAnyValue node = DefaultAnyValue.create("addr", addr).addValue("port", port);
|
||||
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
||||
if (group.equals(groupconf.getValue("name"))) {
|
||||
((DefaultAnyValue) groupconf).addValue("node", node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//application.restoreConfig();
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "removenode", auth = false, comment = "动态删除指定Group的Node节点")
|
||||
public RetResult removeNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
||||
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
||||
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
||||
if (group == null) return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||
final InetSocketAddress address = new InetSocketAddress(addr, port);
|
||||
if (!group.equals(transportFactory.findGroupName(address))) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") not belong to group(" + group + ")");
|
||||
synchronized (this) {
|
||||
if (transportFactory.findGroupInfo(group) == null) {
|
||||
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||
}
|
||||
transportFactory.removeGroupInfo(group, address);
|
||||
for (Service service : transportFactory.getServices()) {
|
||||
if (!Sncp.isSncpDyn(service)) continue;
|
||||
SncpClient client = Sncp.getSncpClient(service);
|
||||
if (Sncp.isRemote(service)) {
|
||||
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
||||
client.getRemoteGroupTransport().removeRemoteAddresses(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
||||
if (group.equals(groupconf.getValue("name"))) {
|
||||
((DefaultAnyValue) groupconf).removeValue("node", DefaultAnyValue.create("addr", addr).addValue("port", port));
|
||||
break;
|
||||
}
|
||||
}
|
||||
//application.restoreConfig();
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||
public RetResult test1() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||
public RetResult test2() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||
public RetResult test3() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||
public RetResult test4() {
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.AsynchronousSocketChannel;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.Application;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "transport", catalog = "watch", repair = false)
|
||||
public class TransportWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("不存在的Group节点")
|
||||
public static final int RET_TRANSPORT_GROUP_NOT_EXISTS = 1606_0001;
|
||||
|
||||
@Comment("非法的Node节点IP地址")
|
||||
public static final int RET_TRANSPORT_ADDR_ILLEGAL = 1606_0002;
|
||||
|
||||
@Comment("Node节点IP地址已存在")
|
||||
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@Resource
|
||||
protected TransportFactory transportFactory;
|
||||
|
||||
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
|
||||
public List<TransportGroupInfo> listNodes() {
|
||||
return transportFactory.getGroupInfos();
|
||||
}
|
||||
|
||||
@RestMapping(name = "addnode", auth = false, comment = "动态增加指定Group的Node节点")
|
||||
public RetResult addNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
||||
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
||||
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
||||
InetSocketAddress address;
|
||||
try {
|
||||
address = new InetSocketAddress(addr, port);
|
||||
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
|
||||
channel.connect(address).get(2, TimeUnit.SECONDS); //连接超时2秒
|
||||
channel.close();
|
||||
} catch (Exception e) {
|
||||
return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is illegal or cannot connect");
|
||||
}
|
||||
if (transportFactory.findGroupName(address) != null) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is exists");
|
||||
synchronized (this) {
|
||||
if (transportFactory.findGroupInfo(group) == null) {
|
||||
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||
}
|
||||
transportFactory.addGroupInfo(group, address);
|
||||
for (Service service : transportFactory.getServices()) {
|
||||
if (!Sncp.isSncpDyn(service)) continue;
|
||||
SncpClient client = Sncp.getSncpClient(service);
|
||||
if (Sncp.isRemote(service)) {
|
||||
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
||||
client.getRemoteGroupTransport().addRemoteAddresses(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
DefaultAnyValue node = DefaultAnyValue.create("addr", addr).addValue("port", port);
|
||||
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
||||
if (group.equals(groupconf.getValue("name"))) {
|
||||
((DefaultAnyValue) groupconf).addValue("node", node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//application.restoreConfig();
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "removenode", auth = false, comment = "动态删除指定Group的Node节点")
|
||||
public RetResult removeNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
||||
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
||||
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
||||
if (group == null) return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||
final InetSocketAddress address = new InetSocketAddress(addr, port);
|
||||
if (!group.equals(transportFactory.findGroupName(address))) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") not belong to group(" + group + ")");
|
||||
synchronized (this) {
|
||||
if (transportFactory.findGroupInfo(group) == null) {
|
||||
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||
}
|
||||
transportFactory.removeGroupInfo(group, address);
|
||||
for (Service service : transportFactory.getServices()) {
|
||||
if (!Sncp.isSncpDyn(service)) continue;
|
||||
SncpClient client = Sncp.getSncpClient(service);
|
||||
if (Sncp.isRemote(service)) {
|
||||
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
||||
client.getRemoteGroupTransport().removeRemoteAddresses(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
||||
if (group.equals(groupconf.getValue("name"))) {
|
||||
((DefaultAnyValue) groupconf).removeValue("node", DefaultAnyValue.create("addr", addr).addValue("port", port));
|
||||
break;
|
||||
}
|
||||
}
|
||||
//application.restoreConfig();
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||
public RetResult test1() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||
public RetResult test2() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||
public RetResult test3() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||
public RetResult test4() {
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,327 +1,327 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.source.CacheSource;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 使用CacheSource实现的第三方服务发现管理接口cluster
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class CacheClusterAgent extends ClusterAgent implements Resourcable {
|
||||
|
||||
@Resource(name = "$")
|
||||
private CacheSource source;
|
||||
|
||||
private String sourceName;
|
||||
|
||||
protected int ttls = 10; //定时检查的秒数
|
||||
|
||||
protected ScheduledThreadPoolExecutor scheduler;
|
||||
|
||||
//可能被HttpMessageClient用到的服务 key: servicename
|
||||
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> httpAddressMap = new ConcurrentHashMap<>();
|
||||
|
||||
//可能被mqtp用到的服务 key: servicename
|
||||
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> mqtpAddressMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void init(AnyValue config) {
|
||||
super.init(config);
|
||||
this.sourceName = getSourceName();
|
||||
|
||||
AnyValue[] properties = config.getAnyValues("property");
|
||||
for (AnyValue property : properties) {
|
||||
if ("ttls".equalsIgnoreCase(property.getValue("name"))) {
|
||||
this.ttls = Integer.parseInt(property.getValue("value", "").trim());
|
||||
if (this.ttls < 5) this.ttls = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(AnyValue config) {
|
||||
if (scheduler != null) scheduler.shutdownNow();
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
AnyValue[] properties = config.getAnyValues("property");
|
||||
for (AnyValue property : properties) {
|
||||
if ("source".equalsIgnoreCase(property.getValue("name"))
|
||||
&& property.getValue("value") != null) {
|
||||
this.sourceName = property.getValue("value");
|
||||
return this.sourceName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
@Override //ServiceLoader时判断配置是否符合当前实现类
|
||||
public boolean acceptsConf(AnyValue config) {
|
||||
if (config == null) return false;
|
||||
AnyValue[] properties = config.getAnyValues("property");
|
||||
if (properties == null || properties.length == 0) return false;
|
||||
for (AnyValue property : properties) {
|
||||
if ("source".equalsIgnoreCase(property.getValue("name"))
|
||||
&& property.getValue("value") != null) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (this.scheduler == null) {
|
||||
this.scheduler = new ScheduledThreadPoolExecutor(4, (Runnable r) -> {
|
||||
final Thread t = new Thread(r, "Redkale-" + CacheClusterAgent.class.getSimpleName() + "-Task-Thread");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
|
||||
this.scheduler.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
checkApplicationHealth();
|
||||
checkHttpAddressHealth();
|
||||
loadMqtpAddressHealth();
|
||||
localEntrys.values().stream().filter(e -> !e.canceled).forEach(entry -> {
|
||||
checkLocalHealth(entry);
|
||||
});
|
||||
remoteEntrys.values().stream().filter(entry -> "SNCP".equalsIgnoreCase(entry.protocol)).forEach(entry -> {
|
||||
updateSncpTransport(entry);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "scheduleAtFixedRate check error", e);
|
||||
}
|
||||
}, Math.max(2000, ttls * 1000), Math.max(2000, ttls * 1000), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadMqtpAddressHealth() {
|
||||
List<String> keys = source.queryKeysStartsWith("cluster.mqtp:");
|
||||
keys.forEach(servicename -> {
|
||||
try {
|
||||
this.mqtpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "loadMqtpAddressHealth check " + servicename + " error", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void checkHttpAddressHealth() {
|
||||
try {
|
||||
this.httpAddressMap.keySet().stream().forEach(servicename -> {
|
||||
try {
|
||||
this.httpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "checkHttpAddressHealth check " + servicename + " error", e);
|
||||
}
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "checkHttpAddressHealth check error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkLocalHealth(final ClusterEntry entry) {
|
||||
AddressEntry newaddr = new AddressEntry();
|
||||
newaddr.addr = entry.address;
|
||||
newaddr.nodeid = this.nodeid;
|
||||
newaddr.time = System.currentTimeMillis();
|
||||
source.hset(entry.checkname, entry.checkid, AddressEntry.class, newaddr);
|
||||
}
|
||||
|
||||
@Override //获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
||||
public CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname) {
|
||||
final Map<String, Collection<InetSocketAddress>> rsmap = new ConcurrentHashMap<>();
|
||||
final String servicenamprefix = generateHttpServiceName(protocol, module, null) + ":";
|
||||
mqtpAddressMap.keySet().stream().filter(k -> k.startsWith(servicenamprefix))
|
||||
.forEach(sn -> rsmap.put(sn.substring(servicenamprefix.length()), mqtpAddressMap.get(sn)));
|
||||
return CompletableFuture.completedFuture(rsmap);
|
||||
}
|
||||
|
||||
@Override //获取HTTP远程服务的可用ip列表
|
||||
public CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
|
||||
final String servicename = generateHttpServiceName(protocol, module, resname);
|
||||
Collection<InetSocketAddress> rs = httpAddressMap.get(servicename);
|
||||
if (rs != null) return CompletableFuture.completedFuture(rs);
|
||||
return queryAddress(servicename).thenApply(t -> {
|
||||
httpAddressMap.put(servicename, t);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<Collection<InetSocketAddress>> queryAddress(final ClusterEntry entry) {
|
||||
return queryAddress(entry.servicename);
|
||||
}
|
||||
|
||||
private CompletableFuture<Collection<InetSocketAddress>> queryAddress(final String servicename) {
|
||||
final CompletableFuture<Map<String, AddressEntry>> future = source.hmapAsync(servicename, AddressEntry.class, 0, 10000);
|
||||
return future.thenApply(map -> {
|
||||
final Set<InetSocketAddress> set = new HashSet<>();
|
||||
map.forEach((n, v) -> {
|
||||
if (v != null && (System.currentTimeMillis() - v.time) / 1000 < ttls) set.add(v.addr);
|
||||
});
|
||||
return set;
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean isApplicationHealth() {
|
||||
String servicename = generateApplicationServiceName();
|
||||
String serviceid = generateApplicationServiceId();
|
||||
AddressEntry entry = (AddressEntry) source.hget(servicename, serviceid, AddressEntry.class);
|
||||
return entry != null && (System.currentTimeMillis() - entry.time) / 1000 < ttls;
|
||||
}
|
||||
|
||||
protected void checkApplicationHealth() {
|
||||
String checkname = generateApplicationServiceName();
|
||||
String checkid = generateApplicationCheckId();
|
||||
AddressEntry entry = new AddressEntry();
|
||||
entry.addr = this.appAddress;
|
||||
entry.nodeid = this.nodeid;
|
||||
entry.time = System.currentTimeMillis();
|
||||
source.hset(checkname, checkid, AddressEntry.class, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Application application) {
|
||||
if (isApplicationHealth()) throw new RuntimeException("application.nodeid=" + nodeid + " exists in cluster");
|
||||
deregister(application);
|
||||
|
||||
String serviceid = generateApplicationServiceId();
|
||||
String servicename = generateApplicationServiceName();
|
||||
AddressEntry entry = new AddressEntry();
|
||||
entry.addr = this.appAddress;
|
||||
entry.nodeid = this.nodeid;
|
||||
entry.time = System.currentTimeMillis();
|
||||
source.hset(servicename, serviceid, AddressEntry.class, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregister(Application application) {
|
||||
String servicename = generateApplicationServiceName();
|
||||
source.remove(servicename);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClusterEntry register(NodeServer ns, String protocol, Service service) {
|
||||
deregister(ns, protocol, service, false);
|
||||
//
|
||||
ClusterEntry clusterEntry = new ClusterEntry(ns, protocol, service);
|
||||
AddressEntry entry = new AddressEntry();
|
||||
entry.addr = clusterEntry.address;
|
||||
entry.nodeid = this.nodeid;
|
||||
entry.time = System.currentTimeMillis();
|
||||
source.hset(clusterEntry.servicename, clusterEntry.serviceid, AddressEntry.class, entry);
|
||||
return clusterEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deregister(NodeServer ns, String protocol, Service service) {
|
||||
deregister(ns, protocol, service, true);
|
||||
}
|
||||
|
||||
protected void deregister(NodeServer ns, String protocol, Service service, boolean realcanceled) {
|
||||
String servicename = generateServiceName(ns, protocol, service);
|
||||
String serviceid = generateServiceId(ns, protocol, service);
|
||||
ClusterEntry currEntry = null;
|
||||
for (final ClusterEntry entry : localEntrys.values()) {
|
||||
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
||||
currEntry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currEntry == null) {
|
||||
for (final ClusterEntry entry : remoteEntrys.values()) {
|
||||
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
||||
currEntry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
source.hremove(servicename, serviceid);
|
||||
if (realcanceled && currEntry != null) currEntry.canceled = true;
|
||||
if (!"mqtp".equals(protocol) && currEntry != null && currEntry.submqtp) {
|
||||
deregister(ns, "mqtp", service, realcanceled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateApplicationServiceName() {
|
||||
return "cluster." + super.generateApplicationServiceName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
||||
return "cluster." + super.generateServiceName(ns, protocol, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateHttpServiceName(String protocol, String module, String resname) {
|
||||
return "cluster." + super.generateHttpServiceName(protocol, module, resname);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateApplicationCheckName() {
|
||||
return generateApplicationServiceName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateApplicationCheckId() {
|
||||
return generateApplicationServiceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
||||
return generateServiceName(ns, protocol, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
||||
return generateServiceId(ns, protocol, service);
|
||||
}
|
||||
|
||||
public static class AddressEntry {
|
||||
|
||||
public InetSocketAddress addr;
|
||||
|
||||
public int nodeid;
|
||||
|
||||
public long time;
|
||||
|
||||
public AddressEntry() {
|
||||
}
|
||||
|
||||
public AddressEntry refresh() {
|
||||
this.time = System.currentTimeMillis();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.source.CacheSource;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 使用CacheSource实现的第三方服务发现管理接口cluster
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class CacheClusterAgent extends ClusterAgent implements Resourcable {
|
||||
|
||||
@Resource(name = "$")
|
||||
private CacheSource source;
|
||||
|
||||
private String sourceName;
|
||||
|
||||
protected int ttls = 10; //定时检查的秒数
|
||||
|
||||
protected ScheduledThreadPoolExecutor scheduler;
|
||||
|
||||
//可能被HttpMessageClient用到的服务 key: servicename
|
||||
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> httpAddressMap = new ConcurrentHashMap<>();
|
||||
|
||||
//可能被mqtp用到的服务 key: servicename
|
||||
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> mqtpAddressMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void init(AnyValue config) {
|
||||
super.init(config);
|
||||
this.sourceName = getSourceName();
|
||||
|
||||
AnyValue[] properties = config.getAnyValues("property");
|
||||
for (AnyValue property : properties) {
|
||||
if ("ttls".equalsIgnoreCase(property.getValue("name"))) {
|
||||
this.ttls = Integer.parseInt(property.getValue("value", "").trim());
|
||||
if (this.ttls < 5) this.ttls = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(AnyValue config) {
|
||||
if (scheduler != null) scheduler.shutdownNow();
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
AnyValue[] properties = config.getAnyValues("property");
|
||||
for (AnyValue property : properties) {
|
||||
if ("source".equalsIgnoreCase(property.getValue("name"))
|
||||
&& property.getValue("value") != null) {
|
||||
this.sourceName = property.getValue("value");
|
||||
return this.sourceName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
@Override //ServiceLoader时判断配置是否符合当前实现类
|
||||
public boolean acceptsConf(AnyValue config) {
|
||||
if (config == null) return false;
|
||||
AnyValue[] properties = config.getAnyValues("property");
|
||||
if (properties == null || properties.length == 0) return false;
|
||||
for (AnyValue property : properties) {
|
||||
if ("source".equalsIgnoreCase(property.getValue("name"))
|
||||
&& property.getValue("value") != null) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (this.scheduler == null) {
|
||||
this.scheduler = new ScheduledThreadPoolExecutor(4, (Runnable r) -> {
|
||||
final Thread t = new Thread(r, "Redkale-" + CacheClusterAgent.class.getSimpleName() + "-Task-Thread");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
|
||||
this.scheduler.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
checkApplicationHealth();
|
||||
checkHttpAddressHealth();
|
||||
loadMqtpAddressHealth();
|
||||
localEntrys.values().stream().filter(e -> !e.canceled).forEach(entry -> {
|
||||
checkLocalHealth(entry);
|
||||
});
|
||||
remoteEntrys.values().stream().filter(entry -> "SNCP".equalsIgnoreCase(entry.protocol)).forEach(entry -> {
|
||||
updateSncpTransport(entry);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "scheduleAtFixedRate check error", e);
|
||||
}
|
||||
}, Math.max(2000, ttls * 1000), Math.max(2000, ttls * 1000), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadMqtpAddressHealth() {
|
||||
List<String> keys = source.queryKeysStartsWith("cluster.mqtp:");
|
||||
keys.forEach(servicename -> {
|
||||
try {
|
||||
this.mqtpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "loadMqtpAddressHealth check " + servicename + " error", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void checkHttpAddressHealth() {
|
||||
try {
|
||||
this.httpAddressMap.keySet().stream().forEach(servicename -> {
|
||||
try {
|
||||
this.httpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "checkHttpAddressHealth check " + servicename + " error", e);
|
||||
}
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "checkHttpAddressHealth check error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkLocalHealth(final ClusterEntry entry) {
|
||||
AddressEntry newaddr = new AddressEntry();
|
||||
newaddr.addr = entry.address;
|
||||
newaddr.nodeid = this.nodeid;
|
||||
newaddr.time = System.currentTimeMillis();
|
||||
source.hset(entry.checkname, entry.checkid, AddressEntry.class, newaddr);
|
||||
}
|
||||
|
||||
@Override //获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
||||
public CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname) {
|
||||
final Map<String, Collection<InetSocketAddress>> rsmap = new ConcurrentHashMap<>();
|
||||
final String servicenamprefix = generateHttpServiceName(protocol, module, null) + ":";
|
||||
mqtpAddressMap.keySet().stream().filter(k -> k.startsWith(servicenamprefix))
|
||||
.forEach(sn -> rsmap.put(sn.substring(servicenamprefix.length()), mqtpAddressMap.get(sn)));
|
||||
return CompletableFuture.completedFuture(rsmap);
|
||||
}
|
||||
|
||||
@Override //获取HTTP远程服务的可用ip列表
|
||||
public CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
|
||||
final String servicename = generateHttpServiceName(protocol, module, resname);
|
||||
Collection<InetSocketAddress> rs = httpAddressMap.get(servicename);
|
||||
if (rs != null) return CompletableFuture.completedFuture(rs);
|
||||
return queryAddress(servicename).thenApply(t -> {
|
||||
httpAddressMap.put(servicename, t);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<Collection<InetSocketAddress>> queryAddress(final ClusterEntry entry) {
|
||||
return queryAddress(entry.servicename);
|
||||
}
|
||||
|
||||
private CompletableFuture<Collection<InetSocketAddress>> queryAddress(final String servicename) {
|
||||
final CompletableFuture<Map<String, AddressEntry>> future = source.hmapAsync(servicename, AddressEntry.class, 0, 10000);
|
||||
return future.thenApply(map -> {
|
||||
final Set<InetSocketAddress> set = new HashSet<>();
|
||||
map.forEach((n, v) -> {
|
||||
if (v != null && (System.currentTimeMillis() - v.time) / 1000 < ttls) set.add(v.addr);
|
||||
});
|
||||
return set;
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean isApplicationHealth() {
|
||||
String servicename = generateApplicationServiceName();
|
||||
String serviceid = generateApplicationServiceId();
|
||||
AddressEntry entry = (AddressEntry) source.hget(servicename, serviceid, AddressEntry.class);
|
||||
return entry != null && (System.currentTimeMillis() - entry.time) / 1000 < ttls;
|
||||
}
|
||||
|
||||
protected void checkApplicationHealth() {
|
||||
String checkname = generateApplicationServiceName();
|
||||
String checkid = generateApplicationCheckId();
|
||||
AddressEntry entry = new AddressEntry();
|
||||
entry.addr = this.appAddress;
|
||||
entry.nodeid = this.nodeid;
|
||||
entry.time = System.currentTimeMillis();
|
||||
source.hset(checkname, checkid, AddressEntry.class, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Application application) {
|
||||
if (isApplicationHealth()) throw new RuntimeException("application.nodeid=" + nodeid + " exists in cluster");
|
||||
deregister(application);
|
||||
|
||||
String serviceid = generateApplicationServiceId();
|
||||
String servicename = generateApplicationServiceName();
|
||||
AddressEntry entry = new AddressEntry();
|
||||
entry.addr = this.appAddress;
|
||||
entry.nodeid = this.nodeid;
|
||||
entry.time = System.currentTimeMillis();
|
||||
source.hset(servicename, serviceid, AddressEntry.class, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregister(Application application) {
|
||||
String servicename = generateApplicationServiceName();
|
||||
source.remove(servicename);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClusterEntry register(NodeServer ns, String protocol, Service service) {
|
||||
deregister(ns, protocol, service, false);
|
||||
//
|
||||
ClusterEntry clusterEntry = new ClusterEntry(ns, protocol, service);
|
||||
AddressEntry entry = new AddressEntry();
|
||||
entry.addr = clusterEntry.address;
|
||||
entry.nodeid = this.nodeid;
|
||||
entry.time = System.currentTimeMillis();
|
||||
source.hset(clusterEntry.servicename, clusterEntry.serviceid, AddressEntry.class, entry);
|
||||
return clusterEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deregister(NodeServer ns, String protocol, Service service) {
|
||||
deregister(ns, protocol, service, true);
|
||||
}
|
||||
|
||||
protected void deregister(NodeServer ns, String protocol, Service service, boolean realcanceled) {
|
||||
String servicename = generateServiceName(ns, protocol, service);
|
||||
String serviceid = generateServiceId(ns, protocol, service);
|
||||
ClusterEntry currEntry = null;
|
||||
for (final ClusterEntry entry : localEntrys.values()) {
|
||||
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
||||
currEntry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currEntry == null) {
|
||||
for (final ClusterEntry entry : remoteEntrys.values()) {
|
||||
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
||||
currEntry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
source.hremove(servicename, serviceid);
|
||||
if (realcanceled && currEntry != null) currEntry.canceled = true;
|
||||
if (!"mqtp".equals(protocol) && currEntry != null && currEntry.submqtp) {
|
||||
deregister(ns, "mqtp", service, realcanceled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateApplicationServiceName() {
|
||||
return "cluster." + super.generateApplicationServiceName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
||||
return "cluster." + super.generateServiceName(ns, protocol, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateHttpServiceName(String protocol, String module, String resname) {
|
||||
return "cluster." + super.generateHttpServiceName(protocol, module, resname);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateApplicationCheckName() {
|
||||
return generateApplicationServiceName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateApplicationCheckId() {
|
||||
return generateApplicationServiceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
||||
return generateServiceName(ns, protocol, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
||||
return generateServiceId(ns, protocol, service);
|
||||
}
|
||||
|
||||
public static class AddressEntry {
|
||||
|
||||
public InetSocketAddress addr;
|
||||
|
||||
public int nodeid;
|
||||
|
||||
public long time;
|
||||
|
||||
public AddressEntry() {
|
||||
}
|
||||
|
||||
public AddressEntry refresh() {
|
||||
this.time = System.currentTimeMillis();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,342 +1,342 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import static org.redkale.boot.Application.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.mq.MessageMultiConsumer;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 第三方服务发现管理接口cluster
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public abstract class ClusterAgent {
|
||||
|
||||
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||
|
||||
@Resource(name = RESNAME_APP_NODEID)
|
||||
protected int nodeid;
|
||||
|
||||
@Resource(name = RESNAME_APP_NAME)
|
||||
protected String appName = "";
|
||||
|
||||
@Resource(name = RESNAME_APP_ADDR)
|
||||
protected InetSocketAddress appAddress;
|
||||
|
||||
protected String name;
|
||||
|
||||
protected boolean waits;
|
||||
|
||||
protected String[] protocols; //必须全大写
|
||||
|
||||
protected int[] ports;
|
||||
|
||||
protected AnyValue config;
|
||||
|
||||
protected TransportFactory transportFactory;
|
||||
|
||||
protected final ConcurrentHashMap<String, ClusterEntry> localEntrys = new ConcurrentHashMap<>();
|
||||
|
||||
protected final ConcurrentHashMap<String, ClusterEntry> remoteEntrys = new ConcurrentHashMap<>();
|
||||
|
||||
public void init(AnyValue config) {
|
||||
this.config = config;
|
||||
this.name = config.getValue("name", "");
|
||||
this.waits = config.getBoolValue("waits", false);
|
||||
{
|
||||
String ps = config.getValue("protocols", "").toUpperCase();
|
||||
if (ps == null || ps.isEmpty()) ps = "SNCP;HTTP";
|
||||
this.protocols = ps.split(";");
|
||||
}
|
||||
String ts = config.getValue("ports", "");
|
||||
if (ts != null && !ts.isEmpty()) {
|
||||
String[] its = ts.split(";");
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (String str : its) {
|
||||
if (str.trim().isEmpty()) continue;
|
||||
list.add(Integer.parseInt(str.trim()));
|
||||
}
|
||||
if (!list.isEmpty()) this.ports = list.stream().mapToInt(x -> x).toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy(AnyValue config) {
|
||||
}
|
||||
|
||||
//ServiceLoader时判断配置是否符合当前实现类
|
||||
public abstract boolean acceptsConf(AnyValue config);
|
||||
|
||||
public boolean containsProtocol(String protocol) {
|
||||
if (protocol == null || protocol.isEmpty()) return false;
|
||||
return protocols == null || Utility.contains(protocols, protocol.toUpperCase());
|
||||
}
|
||||
|
||||
public boolean containsPort(int port) {
|
||||
if (ports == null || ports.length == 0) return true;
|
||||
return Utility.contains(ports, port);
|
||||
}
|
||||
|
||||
public abstract void register(Application application);
|
||||
|
||||
public abstract void deregister(Application application);
|
||||
|
||||
//注册服务, 在NodeService调用Service.init方法之前调用
|
||||
public void register(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
||||
if (localServices.isEmpty()) return;
|
||||
//注册本地模式
|
||||
for (Service service : localServices) {
|
||||
if (!canRegister(protocol, service)) continue;
|
||||
ClusterEntry htentry = register(ns, protocol, service);
|
||||
localEntrys.put(htentry.serviceid, htentry);
|
||||
if (protocol.toLowerCase().startsWith("http")) {
|
||||
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
||||
if (mmc != null) {
|
||||
ClusterEntry mqentry = register(ns, "mqtp", service);
|
||||
localEntrys.put(mqentry.serviceid, mqentry);
|
||||
htentry.submqtp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//远程模式加载IP列表, 只支持SNCP协议
|
||||
if (ns.isSNCP()) {
|
||||
for (Service service : remoteServices) {
|
||||
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
|
||||
updateSncpTransport(entry);
|
||||
remoteEntrys.put(entry.serviceid, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//注销服务, 在NodeService调用Service.destroy 方法之前调用
|
||||
public void deregister(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
||||
//注销本地模式 远程模式不注册
|
||||
for (Service service : localServices) {
|
||||
if (!canRegister(protocol, service)) continue;
|
||||
deregister(ns, protocol, service);
|
||||
}
|
||||
afterDeregister(ns, protocol);
|
||||
}
|
||||
|
||||
protected boolean canRegister(String protocol, Service service) {
|
||||
if ("SNCP".equalsIgnoreCase(protocol) && service.getClass().getAnnotation(Local.class) != null) return false;
|
||||
AutoLoad al = service.getClass().getAnnotation(AutoLoad.class);
|
||||
if (al != null && !al.value() && service.getClass().getAnnotation(Local.class) != null) return false;
|
||||
if (service instanceof WebSocketNode) {
|
||||
if (((WebSocketNode) service).getLocalWebSocketEngine() == null) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
}
|
||||
|
||||
protected void afterDeregister(NodeServer ns, String protocol) {
|
||||
if (!this.waits) return;
|
||||
int s = intervalCheckSeconds();
|
||||
if (s > 0) { //暂停,弥补其他依赖本进程服务的周期偏差
|
||||
try {
|
||||
Thread.sleep(s * 1000);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
logger.info(this.getClass().getSimpleName() + " wait for " + s * 1000 + "ms after deregister");
|
||||
}
|
||||
}
|
||||
|
||||
public int intervalCheckSeconds() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
//获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
||||
public abstract CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname);
|
||||
|
||||
//获取HTTP远程服务的可用ip列表
|
||||
public abstract CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname);
|
||||
|
||||
//获取远程服务的可用ip列表
|
||||
protected abstract CompletableFuture<Collection<InetSocketAddress>> queryAddress(ClusterEntry entry);
|
||||
|
||||
//注册服务
|
||||
protected abstract ClusterEntry register(NodeServer ns, String protocol, Service service);
|
||||
|
||||
//注销服务
|
||||
protected abstract void deregister(NodeServer ns, String protocol, Service service);
|
||||
|
||||
//格式: protocol:classtype-resourcename
|
||||
protected void updateSncpTransport(ClusterEntry entry) {
|
||||
Service service = entry.serviceref.get();
|
||||
if (service == null) return;
|
||||
Collection<InetSocketAddress> addrs = ClusterAgent.this.queryAddress(entry).join();
|
||||
Sncp.updateTransport(service, transportFactory, Sncp.getResourceType(service).getName() + "-" + Sncp.getResourceName(service), entry.netprotocol, entry.address, null, addrs);
|
||||
}
|
||||
|
||||
protected String generateApplicationServiceName() {
|
||||
return "application" + (appName == null || appName.isEmpty() ? "" : ("." + appName)) + ".node" + this.nodeid;
|
||||
}
|
||||
|
||||
protected String generateApplicationServiceId() { //与servicename相同
|
||||
return generateApplicationServiceName();
|
||||
}
|
||||
|
||||
protected String generateApplicationCheckName() {
|
||||
return "check-" + generateApplicationServiceName();
|
||||
}
|
||||
|
||||
protected String generateApplicationCheckId() {
|
||||
return "check-" + generateApplicationServiceId();
|
||||
}
|
||||
|
||||
//也会提供给HttpMessageClusterAgent适用
|
||||
public String generateHttpServiceName(String protocol, String module, String resname) {
|
||||
return protocol.toLowerCase() + ":" + module + (resname == null || resname.isEmpty() ? "" : ("-" + resname));
|
||||
}
|
||||
|
||||
//格式: protocol:classtype-resourcename
|
||||
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
||||
if (protocol.toLowerCase().startsWith("http")) { //HTTP使用RestService.name方式是为了与MessageClient中的module保持一致, 因为HTTP依靠的url中的module,无法知道Service类名
|
||||
String resname = Sncp.getResourceName(service);
|
||||
String module = Rest.getRestModule(service).toLowerCase();
|
||||
return protocol.toLowerCase() + ":" + module + (resname.isEmpty() ? "" : ("-" + resname));
|
||||
}
|
||||
if ("mqtp".equalsIgnoreCase(protocol)) {
|
||||
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
||||
String selfmodule = Rest.getRestModule(service).toLowerCase();
|
||||
return protocol.toLowerCase() + ":" + mmc.module() + ":" + selfmodule;
|
||||
}
|
||||
if (!Sncp.isSncpDyn(service)) return protocol.toLowerCase() + ":" + service.getClass().getName();
|
||||
String resname = Sncp.getResourceName(service);
|
||||
return protocol.toLowerCase() + ":" + Sncp.getResourceType(service).getName() + (resname.isEmpty() ? "" : ("-" + resname));
|
||||
}
|
||||
|
||||
//格式: protocol:classtype-resourcename:nodeid
|
||||
protected String generateServiceId(NodeServer ns, String protocol, Service service) {
|
||||
return generateServiceName(ns, protocol, service) + ":" + this.nodeid;
|
||||
}
|
||||
|
||||
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
||||
return "check-" + generateServiceName(ns, protocol, service);
|
||||
}
|
||||
|
||||
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
||||
return "check-" + generateServiceId(ns, protocol, service);
|
||||
}
|
||||
|
||||
protected ConcurrentHashMap<String, ClusterEntry> getLocalEntrys() {
|
||||
return localEntrys;
|
||||
}
|
||||
|
||||
protected ConcurrentHashMap<String, ClusterEntry> getRemoteEntrys() {
|
||||
return remoteEntrys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
|
||||
public TransportFactory getTransportFactory() {
|
||||
return transportFactory;
|
||||
}
|
||||
|
||||
public void setTransportFactory(TransportFactory transportFactory) {
|
||||
this.transportFactory = transportFactory;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String[] getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
public void setProtocols(String[] protocols) {
|
||||
this.protocols = protocols;
|
||||
}
|
||||
|
||||
public int[] getPorts() {
|
||||
return ports;
|
||||
}
|
||||
|
||||
public void setPorts(int[] ports) {
|
||||
this.ports = ports;
|
||||
}
|
||||
|
||||
public AnyValue getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(AnyValue config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public class ClusterEntry {
|
||||
|
||||
public String serviceid;
|
||||
|
||||
public String servicename;
|
||||
|
||||
public String checkid;
|
||||
|
||||
public String checkname;
|
||||
|
||||
public String protocol;
|
||||
|
||||
public String netprotocol;
|
||||
|
||||
public WeakReference<Service> serviceref;
|
||||
|
||||
public InetSocketAddress address;
|
||||
|
||||
public boolean canceled;
|
||||
|
||||
public boolean submqtp;
|
||||
|
||||
public ClusterEntry(NodeServer ns, String protocol, Service service) {
|
||||
this.serviceid = generateServiceId(ns, protocol, service);
|
||||
this.servicename = generateServiceName(ns, protocol, service);
|
||||
this.checkid = generateCheckId(ns, protocol, service);
|
||||
this.checkname = generateCheckName(ns, protocol, service);
|
||||
this.protocol = protocol;
|
||||
InetSocketAddress addr = ns.getSocketAddress();
|
||||
String host = addr.getHostString();
|
||||
if ("0.0.0.0".equals(host)) {
|
||||
host = appAddress.getHostString();
|
||||
addr = new InetSocketAddress(host, addr.getPort());
|
||||
}
|
||||
this.address = addr;
|
||||
this.serviceref = new WeakReference(service);
|
||||
Server server = ns.getServer();
|
||||
this.netprotocol = server instanceof SncpServer ? ((SncpServer) server).getNetprotocol() : Transport.DEFAULT_NETPROTOCOL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.boot.*;
|
||||
import static org.redkale.boot.Application.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.mq.MessageMultiConsumer;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 第三方服务发现管理接口cluster
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public abstract class ClusterAgent {
|
||||
|
||||
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||
|
||||
@Resource(name = RESNAME_APP_NODEID)
|
||||
protected int nodeid;
|
||||
|
||||
@Resource(name = RESNAME_APP_NAME)
|
||||
protected String appName = "";
|
||||
|
||||
@Resource(name = RESNAME_APP_ADDR)
|
||||
protected InetSocketAddress appAddress;
|
||||
|
||||
protected String name;
|
||||
|
||||
protected boolean waits;
|
||||
|
||||
protected String[] protocols; //必须全大写
|
||||
|
||||
protected int[] ports;
|
||||
|
||||
protected AnyValue config;
|
||||
|
||||
protected TransportFactory transportFactory;
|
||||
|
||||
protected final ConcurrentHashMap<String, ClusterEntry> localEntrys = new ConcurrentHashMap<>();
|
||||
|
||||
protected final ConcurrentHashMap<String, ClusterEntry> remoteEntrys = new ConcurrentHashMap<>();
|
||||
|
||||
public void init(AnyValue config) {
|
||||
this.config = config;
|
||||
this.name = config.getValue("name", "");
|
||||
this.waits = config.getBoolValue("waits", false);
|
||||
{
|
||||
String ps = config.getValue("protocols", "").toUpperCase();
|
||||
if (ps == null || ps.isEmpty()) ps = "SNCP;HTTP";
|
||||
this.protocols = ps.split(";");
|
||||
}
|
||||
String ts = config.getValue("ports", "");
|
||||
if (ts != null && !ts.isEmpty()) {
|
||||
String[] its = ts.split(";");
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (String str : its) {
|
||||
if (str.trim().isEmpty()) continue;
|
||||
list.add(Integer.parseInt(str.trim()));
|
||||
}
|
||||
if (!list.isEmpty()) this.ports = list.stream().mapToInt(x -> x).toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy(AnyValue config) {
|
||||
}
|
||||
|
||||
//ServiceLoader时判断配置是否符合当前实现类
|
||||
public abstract boolean acceptsConf(AnyValue config);
|
||||
|
||||
public boolean containsProtocol(String protocol) {
|
||||
if (protocol == null || protocol.isEmpty()) return false;
|
||||
return protocols == null || Utility.contains(protocols, protocol.toUpperCase());
|
||||
}
|
||||
|
||||
public boolean containsPort(int port) {
|
||||
if (ports == null || ports.length == 0) return true;
|
||||
return Utility.contains(ports, port);
|
||||
}
|
||||
|
||||
public abstract void register(Application application);
|
||||
|
||||
public abstract void deregister(Application application);
|
||||
|
||||
//注册服务, 在NodeService调用Service.init方法之前调用
|
||||
public void register(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
||||
if (localServices.isEmpty()) return;
|
||||
//注册本地模式
|
||||
for (Service service : localServices) {
|
||||
if (!canRegister(protocol, service)) continue;
|
||||
ClusterEntry htentry = register(ns, protocol, service);
|
||||
localEntrys.put(htentry.serviceid, htentry);
|
||||
if (protocol.toLowerCase().startsWith("http")) {
|
||||
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
||||
if (mmc != null) {
|
||||
ClusterEntry mqentry = register(ns, "mqtp", service);
|
||||
localEntrys.put(mqentry.serviceid, mqentry);
|
||||
htentry.submqtp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//远程模式加载IP列表, 只支持SNCP协议
|
||||
if (ns.isSNCP()) {
|
||||
for (Service service : remoteServices) {
|
||||
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
|
||||
updateSncpTransport(entry);
|
||||
remoteEntrys.put(entry.serviceid, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//注销服务, 在NodeService调用Service.destroy 方法之前调用
|
||||
public void deregister(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
||||
//注销本地模式 远程模式不注册
|
||||
for (Service service : localServices) {
|
||||
if (!canRegister(protocol, service)) continue;
|
||||
deregister(ns, protocol, service);
|
||||
}
|
||||
afterDeregister(ns, protocol);
|
||||
}
|
||||
|
||||
protected boolean canRegister(String protocol, Service service) {
|
||||
if ("SNCP".equalsIgnoreCase(protocol) && service.getClass().getAnnotation(Local.class) != null) return false;
|
||||
AutoLoad al = service.getClass().getAnnotation(AutoLoad.class);
|
||||
if (al != null && !al.value() && service.getClass().getAnnotation(Local.class) != null) return false;
|
||||
if (service instanceof WebSocketNode) {
|
||||
if (((WebSocketNode) service).getLocalWebSocketEngine() == null) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
}
|
||||
|
||||
protected void afterDeregister(NodeServer ns, String protocol) {
|
||||
if (!this.waits) return;
|
||||
int s = intervalCheckSeconds();
|
||||
if (s > 0) { //暂停,弥补其他依赖本进程服务的周期偏差
|
||||
try {
|
||||
Thread.sleep(s * 1000);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
logger.info(this.getClass().getSimpleName() + " wait for " + s * 1000 + "ms after deregister");
|
||||
}
|
||||
}
|
||||
|
||||
public int intervalCheckSeconds() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
//获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
||||
public abstract CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname);
|
||||
|
||||
//获取HTTP远程服务的可用ip列表
|
||||
public abstract CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname);
|
||||
|
||||
//获取远程服务的可用ip列表
|
||||
protected abstract CompletableFuture<Collection<InetSocketAddress>> queryAddress(ClusterEntry entry);
|
||||
|
||||
//注册服务
|
||||
protected abstract ClusterEntry register(NodeServer ns, String protocol, Service service);
|
||||
|
||||
//注销服务
|
||||
protected abstract void deregister(NodeServer ns, String protocol, Service service);
|
||||
|
||||
//格式: protocol:classtype-resourcename
|
||||
protected void updateSncpTransport(ClusterEntry entry) {
|
||||
Service service = entry.serviceref.get();
|
||||
if (service == null) return;
|
||||
Collection<InetSocketAddress> addrs = ClusterAgent.this.queryAddress(entry).join();
|
||||
Sncp.updateTransport(service, transportFactory, Sncp.getResourceType(service).getName() + "-" + Sncp.getResourceName(service), entry.netprotocol, entry.address, null, addrs);
|
||||
}
|
||||
|
||||
protected String generateApplicationServiceName() {
|
||||
return "application" + (appName == null || appName.isEmpty() ? "" : ("." + appName)) + ".node" + this.nodeid;
|
||||
}
|
||||
|
||||
protected String generateApplicationServiceId() { //与servicename相同
|
||||
return generateApplicationServiceName();
|
||||
}
|
||||
|
||||
protected String generateApplicationCheckName() {
|
||||
return "check-" + generateApplicationServiceName();
|
||||
}
|
||||
|
||||
protected String generateApplicationCheckId() {
|
||||
return "check-" + generateApplicationServiceId();
|
||||
}
|
||||
|
||||
//也会提供给HttpMessageClusterAgent适用
|
||||
public String generateHttpServiceName(String protocol, String module, String resname) {
|
||||
return protocol.toLowerCase() + ":" + module + (resname == null || resname.isEmpty() ? "" : ("-" + resname));
|
||||
}
|
||||
|
||||
//格式: protocol:classtype-resourcename
|
||||
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
||||
if (protocol.toLowerCase().startsWith("http")) { //HTTP使用RestService.name方式是为了与MessageClient中的module保持一致, 因为HTTP依靠的url中的module,无法知道Service类名
|
||||
String resname = Sncp.getResourceName(service);
|
||||
String module = Rest.getRestModule(service).toLowerCase();
|
||||
return protocol.toLowerCase() + ":" + module + (resname.isEmpty() ? "" : ("-" + resname));
|
||||
}
|
||||
if ("mqtp".equalsIgnoreCase(protocol)) {
|
||||
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
||||
String selfmodule = Rest.getRestModule(service).toLowerCase();
|
||||
return protocol.toLowerCase() + ":" + mmc.module() + ":" + selfmodule;
|
||||
}
|
||||
if (!Sncp.isSncpDyn(service)) return protocol.toLowerCase() + ":" + service.getClass().getName();
|
||||
String resname = Sncp.getResourceName(service);
|
||||
return protocol.toLowerCase() + ":" + Sncp.getResourceType(service).getName() + (resname.isEmpty() ? "" : ("-" + resname));
|
||||
}
|
||||
|
||||
//格式: protocol:classtype-resourcename:nodeid
|
||||
protected String generateServiceId(NodeServer ns, String protocol, Service service) {
|
||||
return generateServiceName(ns, protocol, service) + ":" + this.nodeid;
|
||||
}
|
||||
|
||||
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
||||
return "check-" + generateServiceName(ns, protocol, service);
|
||||
}
|
||||
|
||||
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
||||
return "check-" + generateServiceId(ns, protocol, service);
|
||||
}
|
||||
|
||||
protected ConcurrentHashMap<String, ClusterEntry> getLocalEntrys() {
|
||||
return localEntrys;
|
||||
}
|
||||
|
||||
protected ConcurrentHashMap<String, ClusterEntry> getRemoteEntrys() {
|
||||
return remoteEntrys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
|
||||
public TransportFactory getTransportFactory() {
|
||||
return transportFactory;
|
||||
}
|
||||
|
||||
public void setTransportFactory(TransportFactory transportFactory) {
|
||||
this.transportFactory = transportFactory;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String[] getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
public void setProtocols(String[] protocols) {
|
||||
this.protocols = protocols;
|
||||
}
|
||||
|
||||
public int[] getPorts() {
|
||||
return ports;
|
||||
}
|
||||
|
||||
public void setPorts(int[] ports) {
|
||||
this.ports = ports;
|
||||
}
|
||||
|
||||
public AnyValue getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(AnyValue config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public class ClusterEntry {
|
||||
|
||||
public String serviceid;
|
||||
|
||||
public String servicename;
|
||||
|
||||
public String checkid;
|
||||
|
||||
public String checkname;
|
||||
|
||||
public String protocol;
|
||||
|
||||
public String netprotocol;
|
||||
|
||||
public WeakReference<Service> serviceref;
|
||||
|
||||
public InetSocketAddress address;
|
||||
|
||||
public boolean canceled;
|
||||
|
||||
public boolean submqtp;
|
||||
|
||||
public ClusterEntry(NodeServer ns, String protocol, Service service) {
|
||||
this.serviceid = generateServiceId(ns, protocol, service);
|
||||
this.servicename = generateServiceName(ns, protocol, service);
|
||||
this.checkid = generateCheckId(ns, protocol, service);
|
||||
this.checkname = generateCheckName(ns, protocol, service);
|
||||
this.protocol = protocol;
|
||||
InetSocketAddress addr = ns.getSocketAddress();
|
||||
String host = addr.getHostString();
|
||||
if ("0.0.0.0".equals(host)) {
|
||||
host = appAddress.getHostString();
|
||||
addr = new InetSocketAddress(host, addr.getPort());
|
||||
}
|
||||
this.address = addr;
|
||||
this.serviceref = new WeakReference(service);
|
||||
Server server = ns.getServer();
|
||||
this.netprotocol = server instanceof SncpServer ? ((SncpServer) server).getNetprotocol() : Transport.DEFAULT_NETPROTOCOL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* 自定义的ClusterAgent加载器
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public interface ClusterAgentProvider {
|
||||
|
||||
public boolean acceptsConf(AnyValue config);
|
||||
|
||||
public Class<? extends ClusterAgent> agentClass();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* 自定义的ClusterAgent加载器
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public interface ClusterAgentProvider {
|
||||
|
||||
public boolean acceptsConf(AnyValue config);
|
||||
|
||||
public Class<? extends ClusterAgent> agentClass();
|
||||
}
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.convert.Reader.ValueType;
|
||||
import static org.redkale.convert.Reader.ValueType.MAP;
|
||||
|
||||
/**
|
||||
* 对不明类型的对象进行反序列化。 <br>
|
||||
* <b>注意: 目前只支持文本格式</b> <br>
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class AnyDecoder implements Decodeable<Reader, Object> {
|
||||
|
||||
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {
|
||||
}.getType();
|
||||
|
||||
private static final Type mapObjectType = new TypeToken<Map<String, Object>>() {
|
||||
}.getType();
|
||||
|
||||
private static final Creator<ArrayList> collectionCreator = Creator.create(ArrayList.class);
|
||||
|
||||
private static final Creator<HashMap> mapCreator = Creator.create(HashMap.class);
|
||||
|
||||
protected final Decodeable<Reader, String> stringDecoder;
|
||||
|
||||
protected final CollectionDecoder collectionDecoder;
|
||||
|
||||
protected final MapDecoder mapDecoder;
|
||||
|
||||
public AnyDecoder(final ConvertFactory factory) {
|
||||
this.stringDecoder = factory.loadDecoder(String.class);
|
||||
this.collectionDecoder = new CollectionDecoder(factory, collectionObjectType, Object.class, collectionCreator, this);
|
||||
this.mapDecoder = new MapDecoder(factory, mapObjectType, String.class, Object.class, mapCreator, stringDecoder, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertFrom(Reader in) {
|
||||
ValueType vt = in.readType();
|
||||
if (vt == null) return null;
|
||||
switch (vt) {
|
||||
case ARRAY:
|
||||
return this.collectionDecoder.convertFrom(in);
|
||||
case MAP:
|
||||
return this.mapDecoder.convertFrom(in);
|
||||
}
|
||||
return this.stringDecoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return void.class;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.convert.Reader.ValueType;
|
||||
import static org.redkale.convert.Reader.ValueType.MAP;
|
||||
|
||||
/**
|
||||
* 对不明类型的对象进行反序列化。 <br>
|
||||
* <b>注意: 目前只支持文本格式</b> <br>
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class AnyDecoder implements Decodeable<Reader, Object> {
|
||||
|
||||
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {
|
||||
}.getType();
|
||||
|
||||
private static final Type mapObjectType = new TypeToken<Map<String, Object>>() {
|
||||
}.getType();
|
||||
|
||||
private static final Creator<ArrayList> collectionCreator = Creator.create(ArrayList.class);
|
||||
|
||||
private static final Creator<HashMap> mapCreator = Creator.create(HashMap.class);
|
||||
|
||||
protected final Decodeable<Reader, String> stringDecoder;
|
||||
|
||||
protected final CollectionDecoder collectionDecoder;
|
||||
|
||||
protected final MapDecoder mapDecoder;
|
||||
|
||||
public AnyDecoder(final ConvertFactory factory) {
|
||||
this.stringDecoder = factory.loadDecoder(String.class);
|
||||
this.collectionDecoder = new CollectionDecoder(factory, collectionObjectType, Object.class, collectionCreator, this);
|
||||
this.mapDecoder = new MapDecoder(factory, mapObjectType, String.class, Object.class, mapCreator, stringDecoder, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertFrom(Reader in) {
|
||||
ValueType vt = in.readType();
|
||||
if (vt == null) return null;
|
||||
switch (vt) {
|
||||
case ARRAY:
|
||||
return this.collectionDecoder.convertFrom(in);
|
||||
case MAP:
|
||||
return this.mapDecoder.convertFrom(in);
|
||||
}
|
||||
return this.stringDecoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return void.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的泛型类型
|
||||
*/
|
||||
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
|
||||
|
||||
final ConvertFactory factory;
|
||||
|
||||
AnyEncoder(ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertTo(final Writer out, final T value) {
|
||||
if (value == null) {
|
||||
out.writeClassName(null);
|
||||
out.writeNull();
|
||||
} else {
|
||||
Class clazz = value.getClass();
|
||||
if (clazz == Object.class) {
|
||||
out.writeObjectB(value);
|
||||
out.writeObjectE(value);
|
||||
return;
|
||||
}
|
||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clazz));
|
||||
factory.loadEncoder(clazz).convertTo(out, value);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertMapTo(final Writer out, final Object... values) {
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
} else {
|
||||
int count = values.length - values.length % 2;
|
||||
if (out.writeMapB(count / 2, (Encodeable) this, (Encodeable) this, values) < 0) {
|
||||
for (int i = 0; i < count; i += 2) {
|
||||
if (i > 0) out.writeArrayMark();
|
||||
this.convertTo(out, (T) values[i]);
|
||||
out.writeMapMark();
|
||||
Object val = values[i + 1];
|
||||
if (val instanceof CompletableFuture) {
|
||||
this.convertTo(out, (T) ((CompletableFuture) val).join());
|
||||
} else {
|
||||
this.convertTo(out, (T) val);
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeMapE();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的泛型类型
|
||||
*/
|
||||
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
|
||||
|
||||
final ConvertFactory factory;
|
||||
|
||||
AnyEncoder(ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertTo(final Writer out, final T value) {
|
||||
if (value == null) {
|
||||
out.writeClassName(null);
|
||||
out.writeNull();
|
||||
} else {
|
||||
Class clazz = value.getClass();
|
||||
if (clazz == Object.class) {
|
||||
out.writeObjectB(value);
|
||||
out.writeObjectE(value);
|
||||
return;
|
||||
}
|
||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clazz));
|
||||
factory.loadEncoder(clazz).convertTo(out, value);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertMapTo(final Writer out, final Object... values) {
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
} else {
|
||||
int count = values.length - values.length % 2;
|
||||
if (out.writeMapB(count / 2, (Encodeable) this, (Encodeable) this, values) < 0) {
|
||||
for (int i = 0; i < count; i += 2) {
|
||||
if (i > 0) out.writeArrayMark();
|
||||
this.convertTo(out, (T) values[i]);
|
||||
out.writeMapMark();
|
||||
Object val = values[i + 1];
|
||||
if (val instanceof CompletableFuture) {
|
||||
this.convertTo(out, (T) ((CompletableFuture) val).join());
|
||||
} else {
|
||||
this.convertTo(out, (T) val);
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeMapE();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* AnyValue的Decoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class AnyValueDecoder<R extends Reader> implements Decodeable<R, AnyValue> {
|
||||
|
||||
protected final ConvertFactory factory;
|
||||
|
||||
public AnyValueDecoder(final ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnyValue convertFrom(R in) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return AnyValue.class;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* AnyValue的Decoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class AnyValueDecoder<R extends Reader> implements Decodeable<R, AnyValue> {
|
||||
|
||||
protected final ConvertFactory factory;
|
||||
|
||||
public AnyValueDecoder(final ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnyValue convertFrom(R in) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return AnyValue.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* AnyValue的Encoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class AnyValueEncoder<W extends Writer> implements Encodeable<W, AnyValue> {
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, AnyValue value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return AnyValue.class;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* AnyValue的Encoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class AnyValueEncoder<W extends Writer> implements Encodeable<W, AnyValue> {
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, AnyValue value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return AnyValue.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,144 +1,144 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 数组的反序列化操作类 <br>
|
||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的数组元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected final Class componentClass;
|
||||
|
||||
protected final Decodeable<Reader, T> componentDecoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
}
|
||||
if (this.componentType instanceof ParameterizedType) {
|
||||
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
||||
} else {
|
||||
this.componentClass = (Class) this.componentType;
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T[] convertFrom(Reader in) {
|
||||
return convertFrom(in, null);
|
||||
}
|
||||
|
||||
public T[] convertFrom(Reader in, DeMember member) {
|
||||
byte[] typevals = new byte[1];
|
||||
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (this.componentDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||
final List<T> result = new ArrayList();
|
||||
boolean first = true;
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int startPosition = in.position();
|
||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||
Reader itemReader = getItemReader(in, member, first);
|
||||
if (itemReader == null) break;
|
||||
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
result.add(localdecoder.convertFrom(in));
|
||||
}
|
||||
}
|
||||
in.readArrayE();
|
||||
T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size());
|
||||
return result.toArray(rs);
|
||||
}
|
||||
|
||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||
return in.hasNext(startPosition, contentLength);
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||
if (in == null) return null;
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.componentDecoder + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, T> getComponentDecoder() {
|
||||
return componentDecoder;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 数组的反序列化操作类 <br>
|
||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的数组元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected final Class componentClass;
|
||||
|
||||
protected final Decodeable<Reader, T> componentDecoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
}
|
||||
if (this.componentType instanceof ParameterizedType) {
|
||||
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
||||
} else {
|
||||
this.componentClass = (Class) this.componentType;
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T[] convertFrom(Reader in) {
|
||||
return convertFrom(in, null);
|
||||
}
|
||||
|
||||
public T[] convertFrom(Reader in, DeMember member) {
|
||||
byte[] typevals = new byte[1];
|
||||
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (this.componentDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||
final List<T> result = new ArrayList();
|
||||
boolean first = true;
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int startPosition = in.position();
|
||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||
Reader itemReader = getItemReader(in, member, first);
|
||||
if (itemReader == null) break;
|
||||
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
result.add(localdecoder.convertFrom(in));
|
||||
}
|
||||
}
|
||||
in.readArrayE();
|
||||
T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size());
|
||||
return result.toArray(rs);
|
||||
}
|
||||
|
||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||
return in.hasNext(startPosition, contentLength);
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||
if (in == null) return null;
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.componentDecoder + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, T> getComponentDecoder() {
|
||||
return componentDecoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,133 +1,133 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* 数组的序列化操作类 <br>
|
||||
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的数组元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected final Encodeable anyEncoder;
|
||||
|
||||
protected final Encodeable<Writer, Object> componentEncoder;
|
||||
|
||||
protected final boolean subtypefinal;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.componentEncoder = factory.loadEncoder(this.componentType);
|
||||
this.anyEncoder = factory.getAnyEncoder();
|
||||
this.subtypefinal = (this.componentType instanceof Class) && Modifier.isFinal(((Class) this.componentType).getModifiers());
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, T[] value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, T[] value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
int iMax = value.length - 1;
|
||||
if (iMax == -1) {
|
||||
out.writeArrayB(0, this, componentEncoder, value);
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.componentEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
|
||||
if (subtypefinal) {
|
||||
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
||||
for (int i = 0;; i++) {
|
||||
writeMemberValue(out, member, itemEncoder, value[i], i);
|
||||
if (i == iMax) break;
|
||||
out.writeArrayMark();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
||||
final Type comp = this.componentType;
|
||||
for (int i = 0;; i++) {
|
||||
Object v = value[i];
|
||||
writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? itemEncoder : anyEncoder), v, i);
|
||||
if (i == iMax) break;
|
||||
out.writeArrayMark();
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, int index) {
|
||||
encoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||
return componentEncoder;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* 数组的序列化操作类 <br>
|
||||
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的数组元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected final Encodeable anyEncoder;
|
||||
|
||||
protected final Encodeable<Writer, Object> componentEncoder;
|
||||
|
||||
protected final boolean subtypefinal;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.componentEncoder = factory.loadEncoder(this.componentType);
|
||||
this.anyEncoder = factory.getAnyEncoder();
|
||||
this.subtypefinal = (this.componentType instanceof Class) && Modifier.isFinal(((Class) this.componentType).getModifiers());
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, T[] value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, T[] value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
int iMax = value.length - 1;
|
||||
if (iMax == -1) {
|
||||
out.writeArrayB(0, this, componentEncoder, value);
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.componentEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
|
||||
if (subtypefinal) {
|
||||
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
||||
for (int i = 0;; i++) {
|
||||
writeMemberValue(out, member, itemEncoder, value[i], i);
|
||||
if (i == iMax) break;
|
||||
out.writeArrayMark();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
||||
final Type comp = this.componentType;
|
||||
for (int i = 0;; i++) {
|
||||
Object v = value[i];
|
||||
writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? itemEncoder : anyEncoder), v, i);
|
||||
if (i == iMax) break;
|
||||
out.writeArrayMark();
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, int index) {
|
||||
encoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||
return componentEncoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 二进制序列化/反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
*/
|
||||
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||
|
||||
protected BinaryConvert(ConvertFactory<R, W> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isBinary() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract byte[] convertTo(final Object value);
|
||||
|
||||
public abstract byte[] convertTo(final Type type, final Object value);
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 二进制序列化/反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
*/
|
||||
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||
|
||||
protected BinaryConvert(ConvertFactory<R, W> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isBinary() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract byte[] convertTo(final Object value);
|
||||
|
||||
public abstract byte[] convertTo(final Type type, final Object value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,149 +1,149 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Collection的反序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected Creator<Collection<T>> creator;
|
||||
|
||||
protected final Decodeable<Reader, T> componentDecoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.componentType = pt.getActualTypeArguments()[0];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||
} else if (factory.isReversible()) {
|
||||
this.componentType = Object.class;
|
||||
this.creator = factory.loadCreator(type instanceof Class ? (Class) type : Collection.class);
|
||||
factory.register(type, this);
|
||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||
} else {
|
||||
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//仅供类似JsonAnyDecoder这种动态创建使用, 不得调用 factory.register
|
||||
public CollectionDecoder(final ConvertFactory factory, Type type, Type componentType,
|
||||
Creator<Collection<T>> creator, final Decodeable<Reader, T> componentDecoder) {
|
||||
Objects.requireNonNull(componentDecoder);
|
||||
this.type = type;
|
||||
this.componentType = componentType;
|
||||
this.creator = creator;
|
||||
this.componentDecoder = componentDecoder;
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> convertFrom(Reader in) {
|
||||
return convertFrom(in, null);
|
||||
}
|
||||
|
||||
public Collection<T> convertFrom(Reader in, DeMember member) {
|
||||
byte[] typevals = new byte[1];
|
||||
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (this.componentDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||
final Collection<T> result = this.creator.create();
|
||||
boolean first = true;
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int startPosition = in.position();
|
||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||
Reader itemReader = getItemReader(in, member, first);
|
||||
if (itemReader == null) break;
|
||||
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
result.add(localdecoder.convertFrom(in));
|
||||
}
|
||||
}
|
||||
in.readArrayE();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||
return in.hasNext(startPosition, contentLength);
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||
if (in == null) return null;
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, T> getComponentDecoder() {
|
||||
return componentDecoder;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Collection的反序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected Creator<Collection<T>> creator;
|
||||
|
||||
protected final Decodeable<Reader, T> componentDecoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.componentType = pt.getActualTypeArguments()[0];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||
} else if (factory.isReversible()) {
|
||||
this.componentType = Object.class;
|
||||
this.creator = factory.loadCreator(type instanceof Class ? (Class) type : Collection.class);
|
||||
factory.register(type, this);
|
||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||
} else {
|
||||
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//仅供类似JsonAnyDecoder这种动态创建使用, 不得调用 factory.register
|
||||
public CollectionDecoder(final ConvertFactory factory, Type type, Type componentType,
|
||||
Creator<Collection<T>> creator, final Decodeable<Reader, T> componentDecoder) {
|
||||
Objects.requireNonNull(componentDecoder);
|
||||
this.type = type;
|
||||
this.componentType = componentType;
|
||||
this.creator = creator;
|
||||
this.componentDecoder = componentDecoder;
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> convertFrom(Reader in) {
|
||||
return convertFrom(in, null);
|
||||
}
|
||||
|
||||
public Collection<T> convertFrom(Reader in, DeMember member) {
|
||||
byte[] typevals = new byte[1];
|
||||
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (this.componentDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||
final Collection<T> result = this.creator.create();
|
||||
boolean first = true;
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int startPosition = in.position();
|
||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||
Reader itemReader = getItemReader(in, member, first);
|
||||
if (itemReader == null) break;
|
||||
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
result.add(localdecoder.convertFrom(in));
|
||||
}
|
||||
}
|
||||
in.readArrayE();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||
return in.hasNext(startPosition, contentLength);
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||
if (in == null) return null;
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, T> getComponentDecoder() {
|
||||
return componentDecoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Collection的序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的集合元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Encodeable<Writer, Object> componentEncoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (t instanceof TypeVariable) {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
} else {
|
||||
this.componentEncoder = factory.loadEncoder(t);
|
||||
}
|
||||
} else {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, Collection<T> value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, Collection<T> value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (value.isEmpty()) {
|
||||
out.writeArrayB(0, this, componentEncoder, value);
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.componentEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out.writeArrayB(value.size(), this, componentEncoder, value) < 0) {
|
||||
boolean first = true;
|
||||
for (Object v : value) {
|
||||
if (!first) out.writeArrayMark();
|
||||
writeMemberValue(out, member, v, first);
|
||||
if (first) first = false;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
||||
componentEncoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "{componentType:" + this.type + ", encoder:" + this.componentEncoder + "}";
|
||||
}
|
||||
|
||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||
return componentEncoder;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentEncoder == null ? null : componentEncoder.getType();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Collection的序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的集合元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Encodeable<Writer, Object> componentEncoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (t instanceof TypeVariable) {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
} else {
|
||||
this.componentEncoder = factory.loadEncoder(t);
|
||||
}
|
||||
} else {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, Collection<T> value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, Collection<T> value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (value.isEmpty()) {
|
||||
out.writeArrayB(0, this, componentEncoder, value);
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.componentEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out.writeArrayB(value.size(), this, componentEncoder, value) < 0) {
|
||||
boolean first = true;
|
||||
for (Object v : value) {
|
||||
if (!first) out.writeArrayMark();
|
||||
writeMemberValue(out, member, v, first);
|
||||
if (first) first = false;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
||||
componentEncoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "{componentType:" + this.type + ", encoder:" + this.componentEncoder + "}";
|
||||
}
|
||||
|
||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||
return componentEncoder;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentEncoder == null ? null : componentEncoder.getType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 序列化/反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
*/
|
||||
public abstract class Convert<R extends Reader, W extends Writer> {
|
||||
|
||||
protected final ConvertFactory<R, W> factory;
|
||||
|
||||
protected Convert(ConvertFactory<R, W> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public ConvertFactory<R, W> getFactory() {
|
||||
return this.factory;
|
||||
}
|
||||
|
||||
protected <S extends W> S configWrite(S writer) {
|
||||
return writer;
|
||||
}
|
||||
|
||||
protected <S extends W> S fieldFunc(S writer, BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||
writer.objFieldFunc = objFieldFunc;
|
||||
writer.objExtFunc = objExtFunc;
|
||||
return writer;
|
||||
}
|
||||
|
||||
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc);
|
||||
|
||||
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc);
|
||||
|
||||
public abstract boolean isBinary();
|
||||
|
||||
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
|
||||
|
||||
//@since 2.2.0
|
||||
public abstract <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int length);
|
||||
|
||||
public abstract <T> T convertFrom(final Type type, final ByteBuffer... buffers);
|
||||
|
||||
public abstract <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers);
|
||||
|
||||
public abstract void convertTo(final W writer, final Object value);
|
||||
|
||||
public abstract void convertTo(final W writer, final Type type, final Object value);
|
||||
|
||||
public abstract byte[] convertToBytes(final Object value);
|
||||
|
||||
public abstract byte[] convertToBytes(final Type type, final Object value);
|
||||
|
||||
public abstract void convertToBytes(final Object value, final ConvertBytesHandler handler);
|
||||
|
||||
public abstract void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler);
|
||||
|
||||
public abstract void convertToBytes(final ByteArray array, final Object value);
|
||||
|
||||
public abstract void convertToBytes(final ByteArray array, final Type type, final Object value);
|
||||
|
||||
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value);
|
||||
|
||||
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value);
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 序列化/反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
*/
|
||||
public abstract class Convert<R extends Reader, W extends Writer> {
|
||||
|
||||
protected final ConvertFactory<R, W> factory;
|
||||
|
||||
protected Convert(ConvertFactory<R, W> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public ConvertFactory<R, W> getFactory() {
|
||||
return this.factory;
|
||||
}
|
||||
|
||||
protected <S extends W> S configWrite(S writer) {
|
||||
return writer;
|
||||
}
|
||||
|
||||
protected <S extends W> S fieldFunc(S writer, BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||
writer.objFieldFunc = objFieldFunc;
|
||||
writer.objExtFunc = objExtFunc;
|
||||
return writer;
|
||||
}
|
||||
|
||||
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc);
|
||||
|
||||
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc);
|
||||
|
||||
public abstract boolean isBinary();
|
||||
|
||||
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
|
||||
|
||||
//@since 2.2.0
|
||||
public abstract <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int length);
|
||||
|
||||
public abstract <T> T convertFrom(final Type type, final ByteBuffer... buffers);
|
||||
|
||||
public abstract <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers);
|
||||
|
||||
public abstract void convertTo(final W writer, final Object value);
|
||||
|
||||
public abstract void convertTo(final W writer, final Type type, final Object value);
|
||||
|
||||
public abstract byte[] convertToBytes(final Object value);
|
||||
|
||||
public abstract byte[] convertToBytes(final Type type, final Object value);
|
||||
|
||||
public abstract void convertToBytes(final Object value, final ConvertBytesHandler handler);
|
||||
|
||||
public abstract void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler);
|
||||
|
||||
public abstract void convertToBytes(final ByteArray array, final Object value);
|
||||
|
||||
public abstract void convertToBytes(final ByteArray array, final Type type, final Object value);
|
||||
|
||||
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value);
|
||||
|
||||
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
*
|
||||
* convertToBytes系列的方法的回调
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public interface ConvertBytesHandler {
|
||||
|
||||
<A> void completed(byte[] bs, int offset, int length, Consumer<A> callback, A attachment);
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
*
|
||||
* convertToBytes系列的方法的回调
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public interface ConvertBytesHandler {
|
||||
|
||||
<A> void completed(byte[] bs, int offset, int length, Consumer<A> callback, A attachment);
|
||||
}
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
/**
|
||||
* 依附在setter、getter方法、字段进行简单的配置
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(ConvertColumn.ConvertColumns.class)
|
||||
public @interface ConvertColumn {
|
||||
|
||||
/**
|
||||
* 给字段取个别名
|
||||
*
|
||||
* @return 字段别名
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* 给字段取个序号ID,值小靠前
|
||||
*
|
||||
* @return 字段排序ID
|
||||
*/
|
||||
int index() default 0;
|
||||
|
||||
/**
|
||||
* 解析/序列化时是否屏蔽该字段
|
||||
*
|
||||
* @return 是否屏蔽该字段
|
||||
*/
|
||||
boolean ignore() default false;
|
||||
|
||||
/**
|
||||
* 解析/序列化定制化的TYPE
|
||||
*
|
||||
* @return JSON or BSON or ALL
|
||||
*/
|
||||
ConvertType type() default ConvertType.ALL;
|
||||
|
||||
/**
|
||||
* ConvertColumn 的多用类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public static @interface ConvertColumns {
|
||||
|
||||
ConvertColumn[] value();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
/**
|
||||
* 依附在setter、getter方法、字段进行简单的配置
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(ConvertColumn.ConvertColumns.class)
|
||||
public @interface ConvertColumn {
|
||||
|
||||
/**
|
||||
* 给字段取个别名
|
||||
*
|
||||
* @return 字段别名
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* 给字段取个序号ID,值小靠前
|
||||
*
|
||||
* @return 字段排序ID
|
||||
*/
|
||||
int index() default 0;
|
||||
|
||||
/**
|
||||
* 解析/序列化时是否屏蔽该字段
|
||||
*
|
||||
* @return 是否屏蔽该字段
|
||||
*/
|
||||
boolean ignore() default false;
|
||||
|
||||
/**
|
||||
* 解析/序列化定制化的TYPE
|
||||
*
|
||||
* @return JSON or BSON or ALL
|
||||
*/
|
||||
ConvertType type() default ConvertType.ALL;
|
||||
|
||||
/**
|
||||
* ConvertColumn 的多用类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public static @interface ConvertColumns {
|
||||
|
||||
ConvertColumn[] value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* ConvertColumn 对应的实体类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public final class ConvertColumnEntry {
|
||||
|
||||
private int index;
|
||||
|
||||
private String name = "";
|
||||
|
||||
private boolean ignore;
|
||||
|
||||
private ConvertType convertType;
|
||||
|
||||
public ConvertColumnEntry() {
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(ConvertColumn column) {
|
||||
if (column == null) return;
|
||||
this.name = column.name();
|
||||
this.index = column.index();
|
||||
this.ignore = column.ignore();
|
||||
this.convertType = column.type();
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name) {
|
||||
this(name, false);
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name, boolean ignore) {
|
||||
this.name = name;
|
||||
this.ignore = ignore;
|
||||
this.convertType = ConvertType.ALL;
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) {
|
||||
this.name = name;
|
||||
this.ignore = ignore;
|
||||
this.convertType = convertType;
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name, int index, boolean ignore, ConvertType convertType) {
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.ignore = ignore;
|
||||
this.convertType = convertType;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name == null ? "" : name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean ignore() {
|
||||
return ignore;
|
||||
}
|
||||
|
||||
public void setIgnore(boolean ignore) {
|
||||
this.ignore = ignore;
|
||||
}
|
||||
|
||||
public ConvertType type() {
|
||||
return convertType == null ? ConvertType.ALL : convertType;
|
||||
}
|
||||
|
||||
public void setConvertType(ConvertType convertType) {
|
||||
this.convertType = convertType;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConvertColumnEntry{" + "index=" + index + ", name=" + name + ", ignore=" + ignore + ", convertType=" + convertType + '}';
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* ConvertColumn 对应的实体类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public final class ConvertColumnEntry {
|
||||
|
||||
private int index;
|
||||
|
||||
private String name = "";
|
||||
|
||||
private boolean ignore;
|
||||
|
||||
private ConvertType convertType;
|
||||
|
||||
public ConvertColumnEntry() {
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(ConvertColumn column) {
|
||||
if (column == null) return;
|
||||
this.name = column.name();
|
||||
this.index = column.index();
|
||||
this.ignore = column.ignore();
|
||||
this.convertType = column.type();
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name) {
|
||||
this(name, false);
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name, boolean ignore) {
|
||||
this.name = name;
|
||||
this.ignore = ignore;
|
||||
this.convertType = ConvertType.ALL;
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) {
|
||||
this.name = name;
|
||||
this.ignore = ignore;
|
||||
this.convertType = convertType;
|
||||
}
|
||||
|
||||
public ConvertColumnEntry(String name, int index, boolean ignore, ConvertType convertType) {
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.ignore = ignore;
|
||||
this.convertType = convertType;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name == null ? "" : name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean ignore() {
|
||||
return ignore;
|
||||
}
|
||||
|
||||
public void setIgnore(boolean ignore) {
|
||||
this.ignore = ignore;
|
||||
}
|
||||
|
||||
public ConvertType type() {
|
||||
return convertType == null ? ConvertType.ALL : convertType;
|
||||
}
|
||||
|
||||
public void setConvertType(ConvertType convertType) {
|
||||
this.convertType = convertType;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConvertColumnEntry{" + "index=" + index + ", name=" + name + ", ignore=" + ignore + ", convertType=" + convertType + '}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* 序列化时永久禁用该字段, 与ConvertColumn.ignore()的区别在于: ConvertDisabled不能通过ConvertEntity来解禁
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ConvertDisabled {
|
||||
|
||||
/**
|
||||
* 解析/序列化定制化的TYPE
|
||||
*
|
||||
* @return JSON or BSON or ALL
|
||||
*/
|
||||
ConvertType type() default ConvertType.ALL;
|
||||
|
||||
/**
|
||||
* ConvertDisabled 的多用类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public static @interface ConvertDisableds {
|
||||
|
||||
ConvertDisabled[] value();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* 序列化时永久禁用该字段, 与ConvertColumn.ignore()的区别在于: ConvertDisabled不能通过ConvertEntity来解禁
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ConvertDisabled {
|
||||
|
||||
/**
|
||||
* 解析/序列化定制化的TYPE
|
||||
*
|
||||
* @return JSON or BSON or ALL
|
||||
*/
|
||||
ConvertType type() default ConvertType.ALL;
|
||||
|
||||
/**
|
||||
* ConvertDisabled 的多用类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public static @interface ConvertDisableds {
|
||||
|
||||
ConvertDisabled[] value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 用于类名的别名, 该值必须是全局唯一 <br>
|
||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ConvertEntity {
|
||||
|
||||
/**
|
||||
* 别名值
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 用于类名的别名, 该值必须是全局唯一 <br>
|
||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ConvertEntity {
|
||||
|
||||
/**
|
||||
* 别名值
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* 序列化自定义异常类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ConvertException extends RuntimeException {
|
||||
|
||||
public ConvertException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ConvertException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public ConvertException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ConvertException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* 序列化自定义异常类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ConvertException extends RuntimeException {
|
||||
|
||||
public ConvertException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ConvertException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public ConvertException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ConvertException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,102 +1,102 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
* newConvert参数中的Function返回结果的数据类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ConvertField implements Serializable {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected Type type;
|
||||
|
||||
protected int position;
|
||||
|
||||
protected Object value;
|
||||
|
||||
public ConvertField() {
|
||||
}
|
||||
|
||||
public ConvertField(String name, Object value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ConvertField(String name, int position, Object value) {
|
||||
this.name = name;
|
||||
this.position = position;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ConvertField(String name, Type type, Object value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ConvertField(String name, Type type, int position, Object value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.position = position;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ConvertField[] ofArray(Object... items) {
|
||||
int len = items.length / 2;
|
||||
ConvertField[] rs = new ConvertField[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rs[i] = new ConvertField(items[i * 2].toString(), items[i * 2 + 1]);
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
* newConvert参数中的Function返回结果的数据类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ConvertField implements Serializable {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected Type type;
|
||||
|
||||
protected int position;
|
||||
|
||||
protected Object value;
|
||||
|
||||
public ConvertField() {
|
||||
}
|
||||
|
||||
public ConvertField(String name, Object value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ConvertField(String name, int position, Object value) {
|
||||
this.name = name;
|
||||
this.position = position;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ConvertField(String name, Type type, Object value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ConvertField(String name, Type type, int position, Object value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.position = position;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ConvertField[] ofArray(Object... items) {
|
||||
int len = items.length / 2;
|
||||
ConvertField[] rs = new ConvertField[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rs[i] = new ConvertField(items[i * 2].toString(), items[i * 2 + 1]);
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* Mask接口
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface ConvertMask {
|
||||
|
||||
default byte mask(byte value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default byte unmask(byte value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* Mask接口
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface ConvertMask {
|
||||
|
||||
default byte mask(byte value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default byte unmask(byte value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* Convert的扩展实现类加载器
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public interface ConvertProvider {
|
||||
|
||||
public ConvertType type();
|
||||
|
||||
public Convert convert();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* Convert的扩展实现类加载器
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public interface ConvertProvider {
|
||||
|
||||
public ConvertType type();
|
||||
|
||||
public Convert convert();
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* 序列化时标记String字段的值是否为无转义字符且长度不超过255的字符串
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.3.0
|
||||
*
|
||||
*/
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ConvertSmallString {
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* 序列化时标记String字段的值是否为无转义字符且长度不超过255的字符串
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*
|
||||
* @since 2.3.0
|
||||
*
|
||||
*/
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ConvertSmallString {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* 序列化类型枚举,结合@ConvertColumn使用
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public enum ConvertType {
|
||||
|
||||
JSON(1),
|
||||
BSON(2),
|
||||
PROTOBUF(64),
|
||||
PROTOBUF_JSON(64 + 1),
|
||||
DIY(256),
|
||||
ALL(1023);
|
||||
|
||||
private final int value;
|
||||
|
||||
private ConvertType(int v) {
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean contains(ConvertType type) {
|
||||
if (type == null) return false;
|
||||
return this.value >= type.value && (this.value & type.value) > 0;
|
||||
}
|
||||
|
||||
public static ConvertType find(int value) {
|
||||
for (ConvertType t : ConvertType.values()) {
|
||||
if (value == t.value) return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* 序列化类型枚举,结合@ConvertColumn使用
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public enum ConvertType {
|
||||
|
||||
JSON(1),
|
||||
BSON(2),
|
||||
PROTOBUF(64),
|
||||
PROTOBUF_JSON(64 + 1),
|
||||
DIY(256),
|
||||
ALL(1023);
|
||||
|
||||
private final int value;
|
||||
|
||||
private ConvertType(int v) {
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean contains(ConvertType type) {
|
||||
if (type == null) return false;
|
||||
return this.value >= type.value && (this.value & type.value) > 0;
|
||||
}
|
||||
|
||||
public static ConvertType find(int value) {
|
||||
for (ConvertType t : ConvertType.values()) {
|
||||
if (value == t.value) return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,137 +1,137 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import org.redkale.util.Attribute;
|
||||
|
||||
/**
|
||||
* 字段的反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <T> 字段依附的类
|
||||
* @param <F> 字段的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class DeMember<R extends Reader, T, F> {
|
||||
|
||||
final Field field; //对应类成员的Field, 也可能为null
|
||||
|
||||
final Method method; //对应类成员的Method也可能为null
|
||||
|
||||
protected int index;
|
||||
|
||||
protected int position; //从1开始
|
||||
|
||||
protected int tag; //主要给protobuf使用
|
||||
|
||||
protected final Attribute<T, F> attribute;
|
||||
|
||||
protected Decodeable<R, F> decoder;
|
||||
|
||||
public DeMember(final Attribute<T, F> attribute, Field field, Method method) {
|
||||
this.attribute = attribute;
|
||||
this.field = field;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public DeMember(Attribute<T, F> attribute, Decodeable<R, F> decoder, Field field, Method method) {
|
||||
this(attribute, field, method);
|
||||
this.decoder = decoder;
|
||||
}
|
||||
|
||||
public static <R extends Reader, T, F> DeMember<R, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new DeMember<>(Attribute.create(field), factory.loadDecoder(field.getGenericType()), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <R extends Reader, T, F> DeMember<R, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname, final Class<F> fieldtype) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new DeMember<>(Attribute.create(clazz, fieldname, fieldtype), factory.loadDecoder(fieldtype), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <R extends Reader, T, F> DeMember<R, T, F> create(final Attribute<T, F> attribute, final ConvertFactory factory, final Class<F> fieldtype) {
|
||||
return new DeMember<>(attribute, factory.loadDecoder(fieldtype), null, null);
|
||||
}
|
||||
|
||||
public final boolean accepts(String name) {
|
||||
return attribute.field().equals(name);
|
||||
}
|
||||
|
||||
public final void read(R in, T obj) {
|
||||
this.attribute.set(obj, decoder.convertFrom(in));
|
||||
}
|
||||
|
||||
public final F read(R in) {
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
public Attribute<T, F> getAttribute() {
|
||||
return this.attribute;
|
||||
}
|
||||
|
||||
public Decodeable<R, F> getDecoder() {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public int getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public int compareTo(boolean fieldSort, DeMember<R, T, F> o) {
|
||||
if (o == null) return -1;
|
||||
if (this.position != o.position) return (this.position == 0 ? Integer.MAX_VALUE : this.position) - (o.position == 0 ? Integer.MAX_VALUE : o.position);
|
||||
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
||||
if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
|
||||
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof DeMember)) return false;
|
||||
DeMember other = (DeMember) obj;
|
||||
return compareTo(true, other) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.attribute.field().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeMember{" + "attribute=" + attribute.field() + ", position=" + position + ", tag=" + tag + ", decoder=" + (decoder == null ? null : decoder.getClass().getName()) + '}';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import org.redkale.util.Attribute;
|
||||
|
||||
/**
|
||||
* 字段的反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <T> 字段依附的类
|
||||
* @param <F> 字段的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class DeMember<R extends Reader, T, F> {
|
||||
|
||||
final Field field; //对应类成员的Field, 也可能为null
|
||||
|
||||
final Method method; //对应类成员的Method也可能为null
|
||||
|
||||
protected int index;
|
||||
|
||||
protected int position; //从1开始
|
||||
|
||||
protected int tag; //主要给protobuf使用
|
||||
|
||||
protected final Attribute<T, F> attribute;
|
||||
|
||||
protected Decodeable<R, F> decoder;
|
||||
|
||||
public DeMember(final Attribute<T, F> attribute, Field field, Method method) {
|
||||
this.attribute = attribute;
|
||||
this.field = field;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public DeMember(Attribute<T, F> attribute, Decodeable<R, F> decoder, Field field, Method method) {
|
||||
this(attribute, field, method);
|
||||
this.decoder = decoder;
|
||||
}
|
||||
|
||||
public static <R extends Reader, T, F> DeMember<R, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new DeMember<>(Attribute.create(field), factory.loadDecoder(field.getGenericType()), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <R extends Reader, T, F> DeMember<R, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname, final Class<F> fieldtype) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new DeMember<>(Attribute.create(clazz, fieldname, fieldtype), factory.loadDecoder(fieldtype), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <R extends Reader, T, F> DeMember<R, T, F> create(final Attribute<T, F> attribute, final ConvertFactory factory, final Class<F> fieldtype) {
|
||||
return new DeMember<>(attribute, factory.loadDecoder(fieldtype), null, null);
|
||||
}
|
||||
|
||||
public final boolean accepts(String name) {
|
||||
return attribute.field().equals(name);
|
||||
}
|
||||
|
||||
public final void read(R in, T obj) {
|
||||
this.attribute.set(obj, decoder.convertFrom(in));
|
||||
}
|
||||
|
||||
public final F read(R in) {
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
public Attribute<T, F> getAttribute() {
|
||||
return this.attribute;
|
||||
}
|
||||
|
||||
public Decodeable<R, F> getDecoder() {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public int getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public int compareTo(boolean fieldSort, DeMember<R, T, F> o) {
|
||||
if (o == null) return -1;
|
||||
if (this.position != o.position) return (this.position == 0 ? Integer.MAX_VALUE : this.position) - (o.position == 0 ? Integer.MAX_VALUE : o.position);
|
||||
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
||||
if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
|
||||
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof DeMember)) return false;
|
||||
DeMember other = (DeMember) obj;
|
||||
return compareTo(true, other) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.attribute.field().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeMember{" + "attribute=" + attribute.field() + ", position=" + position + ", tag=" + tag + ", decoder=" + (decoder == null ? null : decoder.getClass().getName()) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <T> 反解析的数据类型
|
||||
*/
|
||||
public interface Decodeable<R extends Reader, T> {
|
||||
|
||||
public T convertFrom(final R in);
|
||||
|
||||
/**
|
||||
* 泛型映射接口
|
||||
*
|
||||
* @return 反解析的数据类型
|
||||
*/
|
||||
public Type getType();
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <T> 反解析的数据类型
|
||||
*/
|
||||
public interface Decodeable<R extends Reader, T> {
|
||||
|
||||
public T convertFrom(final R in);
|
||||
|
||||
/**
|
||||
* 泛型映射接口
|
||||
*
|
||||
* @return 反解析的数据类型
|
||||
*/
|
||||
public Type getType();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,156 +1,156 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import org.redkale.util.Attribute;
|
||||
|
||||
/**
|
||||
* 字段的序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 字段依附的类
|
||||
* @param <F> 字段的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class EnMember<W extends Writer, T, F> {
|
||||
|
||||
final Attribute<T, F> attribute;
|
||||
|
||||
final Encodeable<W, F> encoder;
|
||||
|
||||
final boolean string;
|
||||
|
||||
//final boolean isnumber;
|
||||
final boolean bool;
|
||||
|
||||
final char[] jsonFieldNameChars;
|
||||
|
||||
final byte[] jsonFieldNameBytes;
|
||||
|
||||
final Field field; //对应类成员的Field也可能为null
|
||||
|
||||
final Method method; //对应类成员的Method也可能为null
|
||||
|
||||
protected int index;
|
||||
|
||||
protected int position; //从1开始
|
||||
|
||||
protected int tag; //主要给protobuf使用
|
||||
|
||||
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder, Field field, Method method) {
|
||||
this.attribute = attribute;
|
||||
this.encoder = encoder;
|
||||
this.field = field;
|
||||
this.method = method;
|
||||
Class t = attribute.type();
|
||||
this.string = CharSequence.class.isAssignableFrom(t);
|
||||
this.bool = t == Boolean.class || t == boolean.class;
|
||||
this.jsonFieldNameChars = ('"' + attribute.field() + "\":").toCharArray();
|
||||
this.jsonFieldNameBytes = ('"' + attribute.field() + "\":").getBytes();
|
||||
//this.isnumber = Number.class.isAssignableFrom(t) || (!this.isbool && t.isPrimitive());
|
||||
}
|
||||
|
||||
public static <W extends Writer, T, F> EnMember<W, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new EnMember<>(Attribute.create(field), factory.loadEncoder(field.getGenericType()), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <W extends Writer, T, F> EnMember<W, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname, final Class<F> fieldtype) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new EnMember<>(Attribute.create(clazz, fieldname, fieldtype), factory.loadEncoder(fieldtype), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <W extends Writer, T, F> EnMember<W, T, F> create(final Attribute<T, F> attribute, final ConvertFactory factory, final Class<F> fieldtype) {
|
||||
return new EnMember<>(attribute, factory.loadEncoder(fieldtype), null, null);
|
||||
}
|
||||
|
||||
public final boolean accepts(String name) {
|
||||
return attribute.field().equals(name);
|
||||
}
|
||||
|
||||
public Attribute<T, F> getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public char[] getJsonFieldNameChars() {
|
||||
return jsonFieldNameChars;
|
||||
}
|
||||
|
||||
public byte[] getJsonFieldNameBytes() {
|
||||
return jsonFieldNameBytes;
|
||||
}
|
||||
|
||||
public Encodeable<W, F> getEncoder() {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
public boolean isStringType() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public boolean isBoolType() {
|
||||
return bool;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public int getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public int compareTo(boolean fieldSort, EnMember<W, T, F> o) {
|
||||
if (o == null) return -1;
|
||||
if (this.position != o.position) return (this.position == 0 ? Integer.MAX_VALUE : this.position) - (o.position == 0 ? Integer.MAX_VALUE : o.position);
|
||||
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
||||
if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
|
||||
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof EnMember)) return false;
|
||||
EnMember other = (EnMember) obj;
|
||||
return compareTo(true, other) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.attribute.field().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnMember{" + "attribute=" + attribute.field() + ", position=" + position + ", encoder=" + (encoder == null ? null : encoder.getClass().getName()) + '}';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import org.redkale.util.Attribute;
|
||||
|
||||
/**
|
||||
* 字段的序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 字段依附的类
|
||||
* @param <F> 字段的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class EnMember<W extends Writer, T, F> {
|
||||
|
||||
final Attribute<T, F> attribute;
|
||||
|
||||
final Encodeable<W, F> encoder;
|
||||
|
||||
final boolean string;
|
||||
|
||||
//final boolean isnumber;
|
||||
final boolean bool;
|
||||
|
||||
final char[] jsonFieldNameChars;
|
||||
|
||||
final byte[] jsonFieldNameBytes;
|
||||
|
||||
final Field field; //对应类成员的Field也可能为null
|
||||
|
||||
final Method method; //对应类成员的Method也可能为null
|
||||
|
||||
protected int index;
|
||||
|
||||
protected int position; //从1开始
|
||||
|
||||
protected int tag; //主要给protobuf使用
|
||||
|
||||
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder, Field field, Method method) {
|
||||
this.attribute = attribute;
|
||||
this.encoder = encoder;
|
||||
this.field = field;
|
||||
this.method = method;
|
||||
Class t = attribute.type();
|
||||
this.string = CharSequence.class.isAssignableFrom(t);
|
||||
this.bool = t == Boolean.class || t == boolean.class;
|
||||
this.jsonFieldNameChars = ('"' + attribute.field() + "\":").toCharArray();
|
||||
this.jsonFieldNameBytes = ('"' + attribute.field() + "\":").getBytes();
|
||||
//this.isnumber = Number.class.isAssignableFrom(t) || (!this.isbool && t.isPrimitive());
|
||||
}
|
||||
|
||||
public static <W extends Writer, T, F> EnMember<W, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new EnMember<>(Attribute.create(field), factory.loadEncoder(field.getGenericType()), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <W extends Writer, T, F> EnMember<W, T, F> create(final ConvertFactory factory, final Class<T> clazz, final String fieldname, final Class<F> fieldtype) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldname);
|
||||
return new EnMember<>(Attribute.create(clazz, fieldname, fieldtype), factory.loadEncoder(fieldtype), field, null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <W extends Writer, T, F> EnMember<W, T, F> create(final Attribute<T, F> attribute, final ConvertFactory factory, final Class<F> fieldtype) {
|
||||
return new EnMember<>(attribute, factory.loadEncoder(fieldtype), null, null);
|
||||
}
|
||||
|
||||
public final boolean accepts(String name) {
|
||||
return attribute.field().equals(name);
|
||||
}
|
||||
|
||||
public Attribute<T, F> getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public char[] getJsonFieldNameChars() {
|
||||
return jsonFieldNameChars;
|
||||
}
|
||||
|
||||
public byte[] getJsonFieldNameBytes() {
|
||||
return jsonFieldNameBytes;
|
||||
}
|
||||
|
||||
public Encodeable<W, F> getEncoder() {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
public boolean isStringType() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public boolean isBoolType() {
|
||||
return bool;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public int getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public int compareTo(boolean fieldSort, EnMember<W, T, F> o) {
|
||||
if (o == null) return -1;
|
||||
if (this.position != o.position) return (this.position == 0 ? Integer.MAX_VALUE : this.position) - (o.position == 0 ? Integer.MAX_VALUE : o.position);
|
||||
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
||||
if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
|
||||
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof EnMember)) return false;
|
||||
EnMember other = (EnMember) obj;
|
||||
return compareTo(true, other) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.attribute.field().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnMember{" + "attribute=" + attribute.field() + ", position=" + position + ", encoder=" + (encoder == null ? null : encoder.getClass().getName()) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 序列化的数据类型
|
||||
*/
|
||||
public interface Encodeable<W extends Writer, T> {
|
||||
|
||||
public void convertTo(final W out, T value);
|
||||
|
||||
/**
|
||||
* 泛型映射接口
|
||||
*
|
||||
* @return 返回序列化对象类的数据类型
|
||||
*/
|
||||
public Type getType();
|
||||
|
||||
//是否需要检查Writer.specify
|
||||
default boolean specifyable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 序列化的数据类型
|
||||
*/
|
||||
public interface Encodeable<W extends Writer, T> {
|
||||
|
||||
public void convertTo(final W out, T value);
|
||||
|
||||
/**
|
||||
* 泛型映射接口
|
||||
*
|
||||
* @return 返回序列化对象类的数据类型
|
||||
*/
|
||||
public Type getType();
|
||||
|
||||
//是否需要检查Writer.specify
|
||||
default boolean specifyable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,189 +1,189 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Map的反序列化操作类 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type keyType;
|
||||
|
||||
protected final Type valueType;
|
||||
|
||||
protected Creator<Map<K, V>> creator;
|
||||
|
||||
protected final Decodeable<Reader, K> keyDecoder;
|
||||
|
||||
protected final Decodeable<Reader, V> valueDecoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public MapDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type == java.util.Properties.class) {
|
||||
this.keyType = String.class;
|
||||
this.valueType = String.class;
|
||||
this.creator = factory.loadCreator(java.util.Properties.class);
|
||||
factory.register(type, this);
|
||||
this.keyDecoder = factory.loadDecoder(String.class);
|
||||
this.valueDecoder = factory.loadDecoder(String.class);
|
||||
} else if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.keyType = pt.getActualTypeArguments()[0];
|
||||
this.valueType = pt.getActualTypeArguments()[1];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||
} else if (factory.isReversible()) {
|
||||
this.keyType = Object.class;
|
||||
this.valueType = Object.class;
|
||||
this.creator = factory.loadCreator((Class) type);
|
||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||
} else {
|
||||
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//仅供类似JsonAnyDecoder这种动态创建使用, 不得调用 factory.register
|
||||
public MapDecoder(final ConvertFactory factory, Type type, Type keyType, Type valueType,
|
||||
Creator<Map<K, V>> creator, final Decodeable<Reader, K> keyDecoder, Decodeable<Reader, V> valueDecoder) {
|
||||
Objects.requireNonNull(keyDecoder);
|
||||
Objects.requireNonNull(valueDecoder);
|
||||
this.type = type;
|
||||
this.keyType = keyType;
|
||||
this.valueType = valueType;
|
||||
this.creator = creator;
|
||||
this.keyDecoder = keyDecoder;
|
||||
this.valueDecoder = valueDecoder;
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> convertFrom(Reader in) {
|
||||
return convertFrom(in, null);
|
||||
}
|
||||
|
||||
public Map<K, V> convertFrom(Reader in, DeMember member) {
|
||||
if (this.keyDecoder == null || this.valueDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] typevals = new byte[2];
|
||||
int len = in.readMapB(member, typevals, this.keyDecoder, this.valueDecoder);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(member, null);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
final Map<K, V> result = this.creator.create();
|
||||
boolean first = true;
|
||||
Decodeable<Reader, K> kdecoder = getKeyDecoder(this.keyDecoder, typevals);
|
||||
Decodeable<Reader, V> vdecoder = getValueDecoder(this.valueDecoder, typevals);
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int startPosition = in.position();
|
||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||
Reader entryReader = getEntryReader(in, member, first);
|
||||
if (entryReader == null) break;
|
||||
K key = readKeyMember(entryReader, member, kdecoder, first);
|
||||
entryReader.readBlank();
|
||||
V value = readValueMember(entryReader, member, vdecoder, first);
|
||||
result.put(key, value);
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
K key = readKeyMember(in, member, kdecoder, first);
|
||||
in.readBlank();
|
||||
V value = readValueMember(in, member, vdecoder, first);
|
||||
result.put(key, value);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
in.readMapE();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||
return in.hasNext(startPosition, contentLength);
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Reader getEntryReader(Reader in, DeMember member, boolean first) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected K readKeyMember(Reader in, DeMember member, Decodeable<Reader, K> decoder, boolean first) {
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
protected V readValueMember(Reader in, DeMember member, Decodeable<Reader, V> decoder, boolean first) {
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Type getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
|
||||
public Type getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, K> getKeyDecoder() {
|
||||
return keyDecoder;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, V> getValueDecoder() {
|
||||
return valueDecoder;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Map的反序列化操作类 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Type keyType;
|
||||
|
||||
protected final Type valueType;
|
||||
|
||||
protected Creator<Map<K, V>> creator;
|
||||
|
||||
protected final Decodeable<Reader, K> keyDecoder;
|
||||
|
||||
protected final Decodeable<Reader, V> valueDecoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public MapDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type == java.util.Properties.class) {
|
||||
this.keyType = String.class;
|
||||
this.valueType = String.class;
|
||||
this.creator = factory.loadCreator(java.util.Properties.class);
|
||||
factory.register(type, this);
|
||||
this.keyDecoder = factory.loadDecoder(String.class);
|
||||
this.valueDecoder = factory.loadDecoder(String.class);
|
||||
} else if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.keyType = pt.getActualTypeArguments()[0];
|
||||
this.valueType = pt.getActualTypeArguments()[1];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||
} else if (factory.isReversible()) {
|
||||
this.keyType = Object.class;
|
||||
this.valueType = Object.class;
|
||||
this.creator = factory.loadCreator((Class) type);
|
||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||
} else {
|
||||
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//仅供类似JsonAnyDecoder这种动态创建使用, 不得调用 factory.register
|
||||
public MapDecoder(final ConvertFactory factory, Type type, Type keyType, Type valueType,
|
||||
Creator<Map<K, V>> creator, final Decodeable<Reader, K> keyDecoder, Decodeable<Reader, V> valueDecoder) {
|
||||
Objects.requireNonNull(keyDecoder);
|
||||
Objects.requireNonNull(valueDecoder);
|
||||
this.type = type;
|
||||
this.keyType = keyType;
|
||||
this.valueType = valueType;
|
||||
this.creator = creator;
|
||||
this.keyDecoder = keyDecoder;
|
||||
this.valueDecoder = valueDecoder;
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> convertFrom(Reader in) {
|
||||
return convertFrom(in, null);
|
||||
}
|
||||
|
||||
public Map<K, V> convertFrom(Reader in, DeMember member) {
|
||||
if (this.keyDecoder == null || this.valueDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] typevals = new byte[2];
|
||||
int len = in.readMapB(member, typevals, this.keyDecoder, this.valueDecoder);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(member, null);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
final Map<K, V> result = this.creator.create();
|
||||
boolean first = true;
|
||||
Decodeable<Reader, K> kdecoder = getKeyDecoder(this.keyDecoder, typevals);
|
||||
Decodeable<Reader, V> vdecoder = getValueDecoder(this.valueDecoder, typevals);
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int startPosition = in.position();
|
||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||
Reader entryReader = getEntryReader(in, member, first);
|
||||
if (entryReader == null) break;
|
||||
K key = readKeyMember(entryReader, member, kdecoder, first);
|
||||
entryReader.readBlank();
|
||||
V value = readValueMember(entryReader, member, vdecoder, first);
|
||||
result.put(key, value);
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
K key = readKeyMember(in, member, kdecoder, first);
|
||||
in.readBlank();
|
||||
V value = readValueMember(in, member, vdecoder, first);
|
||||
result.put(key, value);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
in.readMapE();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||
return in.hasNext(startPosition, contentLength);
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
protected Reader getEntryReader(Reader in, DeMember member, boolean first) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected K readKeyMember(Reader in, DeMember member, Decodeable<Reader, K> decoder, boolean first) {
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
protected V readValueMember(Reader in, DeMember member, Decodeable<Reader, V> decoder, boolean first) {
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Type getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
|
||||
public Type getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, K> getKeyDecoder() {
|
||||
return keyDecoder;
|
||||
}
|
||||
|
||||
public Decodeable<Reader, V> getValueDecoder() {
|
||||
return valueDecoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,115 +1,115 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map的序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Encodeable<Writer, K> keyEncoder;
|
||||
|
||||
protected final Encodeable<Writer, V> valueEncoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public MapEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
||||
this.keyEncoder = factory.loadEncoder(pt[0]);
|
||||
this.valueEncoder = factory.loadEncoder(pt[1]);
|
||||
} else {
|
||||
this.keyEncoder = factory.getAnyEncoder();
|
||||
this.valueEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, Map<K, V> value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, Map<K, V> value) {
|
||||
final Map<K, V> values = value;
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.keyEncoder == null || this.valueEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out.writeMapB(values.size(), (Encodeable) keyEncoder, (Encodeable) valueEncoder, value) < 0) {
|
||||
boolean first = true;
|
||||
for (Map.Entry<K, V> en : values.entrySet()) {
|
||||
if (!first) out.writeArrayMark();
|
||||
writeMemberValue(out, member, en.getKey(), en.getValue(), first);
|
||||
if (first) first = false;
|
||||
}
|
||||
}
|
||||
out.writeMapE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, K key, V value, boolean first) {
|
||||
keyEncoder.convertTo(out, key);
|
||||
out.writeMapMark();
|
||||
valueEncoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getKeyType() {
|
||||
return keyEncoder == null ? null : keyEncoder.getType();
|
||||
}
|
||||
|
||||
public Type getValueType() {
|
||||
return valueEncoder == null ? null : valueEncoder.getType();
|
||||
}
|
||||
|
||||
public Encodeable<Writer, K> getKeyEncoder() {
|
||||
return keyEncoder;
|
||||
}
|
||||
|
||||
public Encodeable<Writer, V> getValueEncoder() {
|
||||
return valueEncoder;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map的序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Encodeable<Writer, K> keyEncoder;
|
||||
|
||||
protected final Encodeable<Writer, V> valueEncoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public MapEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
||||
this.keyEncoder = factory.loadEncoder(pt[0]);
|
||||
this.valueEncoder = factory.loadEncoder(pt[1]);
|
||||
} else {
|
||||
this.keyEncoder = factory.getAnyEncoder();
|
||||
this.valueEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, Map<K, V> value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, Map<K, V> value) {
|
||||
final Map<K, V> values = value;
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.keyEncoder == null || this.valueEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out.writeMapB(values.size(), (Encodeable) keyEncoder, (Encodeable) valueEncoder, value) < 0) {
|
||||
boolean first = true;
|
||||
for (Map.Entry<K, V> en : values.entrySet()) {
|
||||
if (!first) out.writeArrayMark();
|
||||
writeMemberValue(out, member, en.getKey(), en.getValue(), first);
|
||||
if (first) first = false;
|
||||
}
|
||||
}
|
||||
out.writeMapE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, K key, V value, boolean first) {
|
||||
keyEncoder.convertTo(out, key);
|
||||
out.writeMapMark();
|
||||
valueEncoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getKeyType() {
|
||||
return keyEncoder == null ? null : keyEncoder.getType();
|
||||
}
|
||||
|
||||
public Type getValueType() {
|
||||
return valueEncoder == null ? null : valueEncoder.getType();
|
||||
}
|
||||
|
||||
public Encodeable<Writer, K> getKeyEncoder() {
|
||||
return keyEncoder;
|
||||
}
|
||||
|
||||
public Encodeable<Writer, V> getValueEncoder() {
|
||||
return valueEncoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,359 +1,359 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import org.redkale.convert.ext.StringSimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 自定义对象的反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <T> 反解析的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Class typeClass;
|
||||
|
||||
protected Creator<T> creator;
|
||||
|
||||
protected DeMember<R, T, ?>[] creatorConstructorMembers = null;
|
||||
|
||||
protected DeMember[] members;
|
||||
|
||||
protected ConvertFactory factory;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
protected ObjectDecoder(Type type) {
|
||||
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.typeClass = (Class) pt.getRawType();
|
||||
} else if (type instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) type;
|
||||
Type[] ts = tv.getBounds();
|
||||
if (ts.length == 1 && ts[0] instanceof Class) {
|
||||
this.typeClass = (Class) ts[0];
|
||||
} else {
|
||||
throw new ConvertException("[" + type + "] is no a class or ParameterizedType");
|
||||
}
|
||||
} else {
|
||||
this.typeClass = (Class) type;
|
||||
}
|
||||
this.members = new DeMember[0];
|
||||
}
|
||||
|
||||
public void init(final ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
try {
|
||||
if (type == Object.class) {
|
||||
this.creatorConstructorMembers = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Class clazz = null;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pts = (ParameterizedType) type;
|
||||
clazz = (Class) (pts).getRawType();
|
||||
} else if (type instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) type;
|
||||
Type[] ts = tv.getBounds();
|
||||
if (ts.length == 1 && ts[0] instanceof Class) {
|
||||
clazz = (Class) ts[0];
|
||||
} else {
|
||||
throw new ConvertException("[" + type + "] is no a class or TypeVariable");
|
||||
}
|
||||
} else if (!(type instanceof Class)) {
|
||||
throw new ConvertException("[" + type + "] is no a class");
|
||||
} else {
|
||||
clazz = (Class) type;
|
||||
}
|
||||
if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) {
|
||||
this.creator = factory.loadCreator(clazz);
|
||||
if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz);
|
||||
}
|
||||
final Set<DeMember> list = new LinkedHashSet();
|
||||
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
||||
try {
|
||||
ConvertColumnEntry ref;
|
||||
RedkaleClassLoader.putReflectionPublicFields(clazz.getName());
|
||||
for (final Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
if (factory.isConvertDisabled(field)) continue;
|
||||
ref = factory.findRef(clazz, field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
ConvertSmallString small = field.getAnnotation(ConvertSmallString.class);
|
||||
Decodeable<R, ?> fieldCoder;
|
||||
if (small != null && field.getType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, field.getName());
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
||||
fieldCoder = factory.loadDecoder(t);
|
||||
}
|
||||
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, field, null, null), fieldCoder, field, null);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
final boolean reversible = factory.isReversible();
|
||||
RedkaleClassLoader.putReflectionPublicMethods(clazz.getName());
|
||||
for (final Method method : clazz.getMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
if (method.getReturnType() != void.class) continue;
|
||||
if (method.getParameterCount() != 1) continue;
|
||||
if (method.getName().length() < 4) continue;
|
||||
if (!method.getName().startsWith("set")) continue;
|
||||
if (factory.isConvertDisabled(method)) continue;
|
||||
if (reversible && (cps == null || !ObjectEncoder.contains(cps, ConvertFactory.readGetSetFieldName(method)))) {
|
||||
boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class;
|
||||
try {
|
||||
Method getter = clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get"));
|
||||
if (getter.getReturnType() != method.getParameterTypes()[0]) continue;
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
String fieldname = ConvertFactory.readGetSetFieldName(method);
|
||||
Field f = null;
|
||||
try {
|
||||
f = clazz.getDeclaredField(fieldname);
|
||||
if (f.getType() != method.getParameterTypes()[0]) continue;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (f == null) {
|
||||
boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class;
|
||||
try {
|
||||
Method getter = clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get"));
|
||||
if (getter.getReturnType() != method.getParameterTypes()[0]) continue;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ref = factory.findRef(clazz, method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
|
||||
ConvertSmallString small = method.getAnnotation(ConvertSmallString.class);
|
||||
Decodeable<R, ?> fieldCoder;
|
||||
if (small != null && method.getReturnType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericParameterTypes()[0], this.type), this.type);
|
||||
fieldCoder = factory.loadDecoder(t);
|
||||
}
|
||||
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, null, null, method), fieldCoder, ConvertFactory.readGetSetField(method), method);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
||||
for (final String constructorField : cps) {
|
||||
boolean flag = false;
|
||||
for (DeMember m : list) {
|
||||
if (m.attribute.field().equals(constructorField)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) continue;
|
||||
//不存在setter方法
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(constructorField);
|
||||
Type t = TypeToken.createClassType(f.getGenericType(), this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, f, null, null), factory.loadDecoder(t), f, null));
|
||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||
char[] fs = constructorField.toCharArray();
|
||||
fs[0] = Character.toUpperCase(fs[0]);
|
||||
String mn = new String(fs);
|
||||
Method getter;
|
||||
try {
|
||||
getter = clazz.getMethod("get" + mn);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
getter = clazz.getMethod("is" + mn);
|
||||
}
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(getter.getGenericParameterTypes()[0], this.type), this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, null, getter, null), factory.loadDecoder(t), ConvertFactory.readGetSetField(getter), getter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DeMember> sorts = new ArrayList<>(list);
|
||||
Collections.sort(sorts, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
Set<Integer> pos = new HashSet<>();
|
||||
for (DeMember member : sorts) {
|
||||
if (member.index > 0) pos.add(member.index);
|
||||
}
|
||||
int pidx = 0;
|
||||
for (DeMember member : sorts) {
|
||||
if (member.index > 0) {
|
||||
member.position = member.index;
|
||||
} else {
|
||||
while (pos.contains(++pidx));
|
||||
member.position = pidx;
|
||||
}
|
||||
initForEachDeMember(factory, member);
|
||||
}
|
||||
|
||||
this.members = list.toArray(new DeMember[list.size()]);
|
||||
Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
|
||||
if (cps != null) {
|
||||
final String[] fields = cps;
|
||||
final DeMember<R, T, ?>[] ms = new DeMember[fields.length];
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
for (DeMember m : this.members) {
|
||||
if (m.attribute.field().equals(fields[i])) {
|
||||
ms[i] = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.creatorConstructorMembers = ms;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new ConvertException(ex);
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initForEachDeMember(ConvertFactory factory, DeMember member) {
|
||||
}
|
||||
|
||||
protected void setTag(DeMember member, int tag) {
|
||||
member.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2]
|
||||
*
|
||||
* @param in 输入流
|
||||
*
|
||||
* @return 反解析后的对象结果
|
||||
*/
|
||||
@Override
|
||||
public T convertFrom(final R in) {
|
||||
R objin = objectReader(in);
|
||||
final String clazz = objin.readObjectB(typeClass);
|
||||
if (clazz == null) return null;
|
||||
if (!clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntityAlias(clazz)).convertFrom(objin);
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.creator == null) {
|
||||
if (typeClass.isInterface() || Modifier.isAbstract(typeClass.getModifiers())) {
|
||||
throw new ConvertException("[" + typeClass + "] is a interface or abstract class, cannot create it's Creator.");
|
||||
}
|
||||
}
|
||||
if (this.creatorConstructorMembers == null) { //空构造函数
|
||||
final T result = this.creator == null ? null : this.creator.create();
|
||||
boolean first = true;
|
||||
while (hasNext(objin, first)) {
|
||||
DeMember member = objin.readFieldName(members);
|
||||
objin.readBlank();
|
||||
if (member == null) {
|
||||
objin.skipValue(); //跳过不存在的属性的值
|
||||
} else {
|
||||
readMemberValue(objin, member, result, first);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
objin.readObjectE(typeClass);
|
||||
return result;
|
||||
} else { //带参数的构造函数
|
||||
final DeMember<R, T, ?>[] fields = this.creatorConstructorMembers;
|
||||
final Object[] constructorParams = new Object[fields.length];
|
||||
final Object[][] otherParams = new Object[this.members.length][2];
|
||||
int oc = 0;
|
||||
boolean first = true;
|
||||
while (hasNext(objin, first)) {
|
||||
DeMember member = objin.readFieldName(members);
|
||||
objin.readBlank();
|
||||
if (member == null) {
|
||||
objin.skipValue(); //跳过不存在的属性的值
|
||||
} else {
|
||||
Object val = readMemberValue(objin, member, first);
|
||||
boolean flag = true;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
if (member == fields[i]) {
|
||||
constructorParams[i] = val;
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) otherParams[oc++] = new Object[]{member.attribute, val};
|
||||
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
objin.readObjectE(typeClass);
|
||||
if (this.creator == null) return null;
|
||||
final T result = this.creator.create(constructorParams);
|
||||
for (int i = 0; i < oc; i++) {
|
||||
((Attribute) otherParams[i][0]).set(result, otherParams[i][1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
protected R objectReader(R in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected boolean hasNext(R in, boolean first) {
|
||||
return in.hasNext();
|
||||
}
|
||||
|
||||
protected Object readMemberValue(R in, DeMember member, boolean first) {
|
||||
return member.read(in);
|
||||
}
|
||||
|
||||
protected void readMemberValue(R in, DeMember member, T result, boolean first) {
|
||||
member.read(in, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public DeMember[] getMembers() {
|
||||
return Arrays.copyOf(members, members.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import org.redkale.convert.ext.StringSimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 自定义对象的反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <T> 反解析的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Class typeClass;
|
||||
|
||||
protected Creator<T> creator;
|
||||
|
||||
protected DeMember<R, T, ?>[] creatorConstructorMembers = null;
|
||||
|
||||
protected DeMember[] members;
|
||||
|
||||
protected ConvertFactory factory;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
protected ObjectDecoder(Type type) {
|
||||
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.typeClass = (Class) pt.getRawType();
|
||||
} else if (type instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) type;
|
||||
Type[] ts = tv.getBounds();
|
||||
if (ts.length == 1 && ts[0] instanceof Class) {
|
||||
this.typeClass = (Class) ts[0];
|
||||
} else {
|
||||
throw new ConvertException("[" + type + "] is no a class or ParameterizedType");
|
||||
}
|
||||
} else {
|
||||
this.typeClass = (Class) type;
|
||||
}
|
||||
this.members = new DeMember[0];
|
||||
}
|
||||
|
||||
public void init(final ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
try {
|
||||
if (type == Object.class) {
|
||||
this.creatorConstructorMembers = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Class clazz = null;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pts = (ParameterizedType) type;
|
||||
clazz = (Class) (pts).getRawType();
|
||||
} else if (type instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) type;
|
||||
Type[] ts = tv.getBounds();
|
||||
if (ts.length == 1 && ts[0] instanceof Class) {
|
||||
clazz = (Class) ts[0];
|
||||
} else {
|
||||
throw new ConvertException("[" + type + "] is no a class or TypeVariable");
|
||||
}
|
||||
} else if (!(type instanceof Class)) {
|
||||
throw new ConvertException("[" + type + "] is no a class");
|
||||
} else {
|
||||
clazz = (Class) type;
|
||||
}
|
||||
if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) {
|
||||
this.creator = factory.loadCreator(clazz);
|
||||
if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz);
|
||||
}
|
||||
final Set<DeMember> list = new LinkedHashSet();
|
||||
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
||||
try {
|
||||
ConvertColumnEntry ref;
|
||||
RedkaleClassLoader.putReflectionPublicFields(clazz.getName());
|
||||
for (final Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
if (factory.isConvertDisabled(field)) continue;
|
||||
ref = factory.findRef(clazz, field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
ConvertSmallString small = field.getAnnotation(ConvertSmallString.class);
|
||||
Decodeable<R, ?> fieldCoder;
|
||||
if (small != null && field.getType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, field.getName());
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
||||
fieldCoder = factory.loadDecoder(t);
|
||||
}
|
||||
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, field, null, null), fieldCoder, field, null);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
final boolean reversible = factory.isReversible();
|
||||
RedkaleClassLoader.putReflectionPublicMethods(clazz.getName());
|
||||
for (final Method method : clazz.getMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
if (method.getReturnType() != void.class) continue;
|
||||
if (method.getParameterCount() != 1) continue;
|
||||
if (method.getName().length() < 4) continue;
|
||||
if (!method.getName().startsWith("set")) continue;
|
||||
if (factory.isConvertDisabled(method)) continue;
|
||||
if (reversible && (cps == null || !ObjectEncoder.contains(cps, ConvertFactory.readGetSetFieldName(method)))) {
|
||||
boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class;
|
||||
try {
|
||||
Method getter = clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get"));
|
||||
if (getter.getReturnType() != method.getParameterTypes()[0]) continue;
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
String fieldname = ConvertFactory.readGetSetFieldName(method);
|
||||
Field f = null;
|
||||
try {
|
||||
f = clazz.getDeclaredField(fieldname);
|
||||
if (f.getType() != method.getParameterTypes()[0]) continue;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (f == null) {
|
||||
boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class;
|
||||
try {
|
||||
Method getter = clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get"));
|
||||
if (getter.getReturnType() != method.getParameterTypes()[0]) continue;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ref = factory.findRef(clazz, method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
|
||||
ConvertSmallString small = method.getAnnotation(ConvertSmallString.class);
|
||||
Decodeable<R, ?> fieldCoder;
|
||||
if (small != null && method.getReturnType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericParameterTypes()[0], this.type), this.type);
|
||||
fieldCoder = factory.loadDecoder(t);
|
||||
}
|
||||
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, null, null, method), fieldCoder, ConvertFactory.readGetSetField(method), method);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
||||
for (final String constructorField : cps) {
|
||||
boolean flag = false;
|
||||
for (DeMember m : list) {
|
||||
if (m.attribute.field().equals(constructorField)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) continue;
|
||||
//不存在setter方法
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(constructorField);
|
||||
Type t = TypeToken.createClassType(f.getGenericType(), this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, f, null, null), factory.loadDecoder(t), f, null));
|
||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||
char[] fs = constructorField.toCharArray();
|
||||
fs[0] = Character.toUpperCase(fs[0]);
|
||||
String mn = new String(fs);
|
||||
Method getter;
|
||||
try {
|
||||
getter = clazz.getMethod("get" + mn);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
getter = clazz.getMethod("is" + mn);
|
||||
}
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(getter.getGenericParameterTypes()[0], this.type), this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, type, clazz, null, getter, null), factory.loadDecoder(t), ConvertFactory.readGetSetField(getter), getter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DeMember> sorts = new ArrayList<>(list);
|
||||
Collections.sort(sorts, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
Set<Integer> pos = new HashSet<>();
|
||||
for (DeMember member : sorts) {
|
||||
if (member.index > 0) pos.add(member.index);
|
||||
}
|
||||
int pidx = 0;
|
||||
for (DeMember member : sorts) {
|
||||
if (member.index > 0) {
|
||||
member.position = member.index;
|
||||
} else {
|
||||
while (pos.contains(++pidx));
|
||||
member.position = pidx;
|
||||
}
|
||||
initForEachDeMember(factory, member);
|
||||
}
|
||||
|
||||
this.members = list.toArray(new DeMember[list.size()]);
|
||||
Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
|
||||
if (cps != null) {
|
||||
final String[] fields = cps;
|
||||
final DeMember<R, T, ?>[] ms = new DeMember[fields.length];
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
for (DeMember m : this.members) {
|
||||
if (m.attribute.field().equals(fields[i])) {
|
||||
ms[i] = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.creatorConstructorMembers = ms;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new ConvertException(ex);
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initForEachDeMember(ConvertFactory factory, DeMember member) {
|
||||
}
|
||||
|
||||
protected void setTag(DeMember member, int tag) {
|
||||
member.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2]
|
||||
*
|
||||
* @param in 输入流
|
||||
*
|
||||
* @return 反解析后的对象结果
|
||||
*/
|
||||
@Override
|
||||
public T convertFrom(final R in) {
|
||||
R objin = objectReader(in);
|
||||
final String clazz = objin.readObjectB(typeClass);
|
||||
if (clazz == null) return null;
|
||||
if (!clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntityAlias(clazz)).convertFrom(objin);
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.creator == null) {
|
||||
if (typeClass.isInterface() || Modifier.isAbstract(typeClass.getModifiers())) {
|
||||
throw new ConvertException("[" + typeClass + "] is a interface or abstract class, cannot create it's Creator.");
|
||||
}
|
||||
}
|
||||
if (this.creatorConstructorMembers == null) { //空构造函数
|
||||
final T result = this.creator == null ? null : this.creator.create();
|
||||
boolean first = true;
|
||||
while (hasNext(objin, first)) {
|
||||
DeMember member = objin.readFieldName(members);
|
||||
objin.readBlank();
|
||||
if (member == null) {
|
||||
objin.skipValue(); //跳过不存在的属性的值
|
||||
} else {
|
||||
readMemberValue(objin, member, result, first);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
objin.readObjectE(typeClass);
|
||||
return result;
|
||||
} else { //带参数的构造函数
|
||||
final DeMember<R, T, ?>[] fields = this.creatorConstructorMembers;
|
||||
final Object[] constructorParams = new Object[fields.length];
|
||||
final Object[][] otherParams = new Object[this.members.length][2];
|
||||
int oc = 0;
|
||||
boolean first = true;
|
||||
while (hasNext(objin, first)) {
|
||||
DeMember member = objin.readFieldName(members);
|
||||
objin.readBlank();
|
||||
if (member == null) {
|
||||
objin.skipValue(); //跳过不存在的属性的值
|
||||
} else {
|
||||
Object val = readMemberValue(objin, member, first);
|
||||
boolean flag = true;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
if (member == fields[i]) {
|
||||
constructorParams[i] = val;
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) otherParams[oc++] = new Object[]{member.attribute, val};
|
||||
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
objin.readObjectE(typeClass);
|
||||
if (this.creator == null) return null;
|
||||
final T result = this.creator.create(constructorParams);
|
||||
for (int i = 0; i < oc; i++) {
|
||||
((Attribute) otherParams[i][0]).set(result, otherParams[i][1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
protected R objectReader(R in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected boolean hasNext(R in, boolean first) {
|
||||
return in.hasNext();
|
||||
}
|
||||
|
||||
protected Object readMemberValue(R in, DeMember member, boolean first) {
|
||||
return member.read(in);
|
||||
}
|
||||
|
||||
protected void readMemberValue(R in, DeMember member, T result, boolean first) {
|
||||
member.read(in, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public DeMember[] getMembers() {
|
||||
return Arrays.copyOf(members, members.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,378 +1,378 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import org.redkale.convert.ext.StringSimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 自定义对象的序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 序列化的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
||||
|
||||
static final Type[] TYPEZERO = new Type[0];
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Class typeClass;
|
||||
|
||||
protected EnMember[] members;
|
||||
|
||||
protected ConvertFactory factory;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
protected ObjectEncoder(Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.typeClass = (Class) pt.getRawType();
|
||||
} else if (type instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) type;
|
||||
Type[] ts = tv.getBounds();
|
||||
if (ts.length == 1 && ts[0] instanceof Class) {
|
||||
this.typeClass = (Class) ts[0];
|
||||
} else {
|
||||
throw new ConvertException("[" + type + "] is no a class or ParameterizedType");
|
||||
}
|
||||
} else {
|
||||
this.typeClass = (Class) type;
|
||||
}
|
||||
this.members = new EnMember[0];
|
||||
}
|
||||
|
||||
public void init(final ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
try {
|
||||
if (type == Object.class) return;
|
||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
||||
final Class clazz = this.typeClass;
|
||||
final Set<EnMember> list = new LinkedHashSet();
|
||||
final boolean reversible = factory.isReversible();
|
||||
Creator creator = null;
|
||||
try {
|
||||
creator = factory.loadCreator(this.typeClass);
|
||||
} catch (RuntimeException e) {
|
||||
if (reversible && !Modifier.isAbstract(this.typeClass.getModifiers())) throw e;
|
||||
}
|
||||
final String[] cps = creator == null ? null : ObjectEncoder.findConstructorProperties(creator);
|
||||
try {
|
||||
ConvertColumnEntry ref;
|
||||
|
||||
RedkaleClassLoader.putReflectionPublicFields(clazz.getName());
|
||||
for (final Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
if (factory.isConvertDisabled(field)) continue;
|
||||
ref = factory.findRef(clazz, field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
ConvertSmallString small = field.getAnnotation(ConvertSmallString.class);
|
||||
Encodeable<W, ?> fieldCoder;
|
||||
if (small != null && field.getType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, field.getName());
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
||||
fieldCoder = factory.loadEncoder(t);
|
||||
}
|
||||
EnMember member = new EnMember(createAttribute(factory, type, clazz, field, null, null), fieldCoder, field, null);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
|
||||
RedkaleClassLoader.putReflectionPublicMethods(clazz.getName());
|
||||
for (final Method method : clazz.getMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
if (method.getName().equals("getClass")) continue;
|
||||
if (method.getReturnType() == void.class) continue;
|
||||
if (method.getParameterCount() != 0) continue;
|
||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get") && !Utility.isRecordGetter(clazz, method)) continue;
|
||||
if (factory.isConvertDisabled(method)) continue;
|
||||
String convertname = ConvertFactory.readGetSetFieldName(method);
|
||||
if (reversible && (cps == null || !contains(cps, convertname))) {
|
||||
boolean is = method.getName().startsWith("is");
|
||||
try {
|
||||
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ref = factory.findRef(clazz, method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
ConvertSmallString small = method.getAnnotation(ConvertSmallString.class);
|
||||
if (small == null) {
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(convertname);
|
||||
if (f != null) small = f.getAnnotation(ConvertSmallString.class);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
Encodeable<W, ?> fieldCoder;
|
||||
if (small != null && method.getReturnType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericReturnType(), this.type), this.type);
|
||||
fieldCoder = factory.loadEncoder(t);
|
||||
}
|
||||
EnMember member = new EnMember(createAttribute(factory, type, clazz, null, method, null), fieldCoder, ConvertFactory.readGetSetField(method), method);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
List<EnMember> sorts = new ArrayList<>(list);
|
||||
if (cps != null) {
|
||||
Set<EnMember> dissorts = new LinkedHashSet<>(list);
|
||||
for (final String constructorField : cps) { //reversible模式下需要确保DeMember与EnMember的个数和顺序保持一致,不然postition会不一致导致反序列化对应的字段顺序不同
|
||||
boolean flag = false;
|
||||
for (EnMember m : dissorts) {
|
||||
if (m.attribute.field().equals(constructorField)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) continue;
|
||||
//不存在setter方法
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(constructorField);
|
||||
Type t = TypeToken.createClassType(f.getGenericType(), this.type);
|
||||
try {
|
||||
dissorts.add(new EnMember(createAttribute(factory, type, clazz, f, null, null), null, f, null)); //虚构
|
||||
} catch (RuntimeException e) {
|
||||
}
|
||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||
char[] fs = constructorField.toCharArray();
|
||||
fs[0] = Character.toUpperCase(fs[0]);
|
||||
String mn = new String(fs);
|
||||
Method getter;
|
||||
try {
|
||||
getter = clazz.getMethod("get" + mn);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
getter = clazz.getMethod("is" + mn);
|
||||
}
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(getter.getGenericParameterTypes()[0], this.type), this.type);
|
||||
try {
|
||||
dissorts.add(new EnMember(createAttribute(factory, type, clazz, null, getter, null), null, null, null)); //虚构
|
||||
} catch (RuntimeException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dissorts.size() != list.size()) sorts = new ArrayList<>(dissorts);
|
||||
}
|
||||
Collections.sort(sorts, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
Set<Integer> pos = new HashSet<>();
|
||||
for (EnMember member : sorts) {
|
||||
if (member.index > 0) pos.add(member.index);
|
||||
}
|
||||
int pidx = 0;
|
||||
for (EnMember member : sorts) {
|
||||
if (member.index > 0) {
|
||||
member.position = member.index;
|
||||
} else {
|
||||
while (pos.contains(++pidx));
|
||||
member.position = pidx;
|
||||
}
|
||||
initForEachEnMember(factory, member);
|
||||
}
|
||||
|
||||
this.members = list.toArray(new EnMember[list.size()]);
|
||||
Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new ConvertException("ObjectEncoder init type=" + this.type + " error", ex);
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initForEachEnMember(ConvertFactory factory, EnMember member) {
|
||||
}
|
||||
|
||||
protected void setTag(EnMember member, int tag) {
|
||||
member.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, T value) {
|
||||
if (value == null) {
|
||||
out.writeObjectNull(null);
|
||||
return;
|
||||
}
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value.getClass() != this.typeClass && !this.type.equals(out.specify())) {
|
||||
final Class clz = value.getClass();
|
||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
|
||||
factory.loadEncoder(clz).convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
W objout = objectWriter(out, value);
|
||||
if (objout.writeObjectB(value) < 0) {
|
||||
int maxPosition = 0;
|
||||
for (EnMember member : members) {
|
||||
maxPosition = member.getPosition();
|
||||
objout.writeObjectField(member, value);
|
||||
}
|
||||
if (objout.objExtFunc != null) {
|
||||
ConvertField[] extFields = objout.objExtFunc.apply(value);
|
||||
if (extFields != null) {
|
||||
Encodeable<W, ?> anyEncoder = factory.getAnyEncoder();
|
||||
for (ConvertField en : extFields) {
|
||||
if (en == null) continue;
|
||||
maxPosition++;
|
||||
objout.writeObjectField(en.getName(), en.getType(), Math.max(en.getPosition(), maxPosition), anyEncoder, en.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
objout.writeObjectE(value);
|
||||
}
|
||||
|
||||
protected W objectWriter(W out, T value) {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Class getTypeClass() {
|
||||
return this.typeClass;
|
||||
}
|
||||
|
||||
public EnMember[] getMembers() {
|
||||
return Arrays.copyOf(members, members.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||
}
|
||||
|
||||
//
|
||||
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
||||
// if (type instanceof Class) { //e.g. String
|
||||
// return type;
|
||||
// } else if (type instanceof ParameterizedType) { //e.g. Map<String, String>
|
||||
// final ParameterizedType pt = (ParameterizedType) type;
|
||||
// Type[] paramTypes = pt.getActualTypeArguments();
|
||||
// final Type[] newTypes = new Type[paramTypes.length];
|
||||
// int count = 0;
|
||||
// for (int i = 0; i < newTypes.length; i++) {
|
||||
// newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
||||
// if (paramTypes[i] == newTypes[i]) count++;
|
||||
// }
|
||||
// if (count == paramTypes.length) return pt;
|
||||
// return new ParameterizedType() {
|
||||
//
|
||||
// @Override
|
||||
// public Type[] getActualTypeArguments() {
|
||||
// return newTypes;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Type getRawType() {
|
||||
// return pt.getRawType();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Type getOwnerType() {
|
||||
// return pt.getOwnerType();
|
||||
// }
|
||||
//
|
||||
// };
|
||||
// }
|
||||
// if (realGenericTypes == null) return type;
|
||||
// if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
||||
// final WildcardType wt = (WildcardType) type;
|
||||
// for (Type f : wt.getUpperBounds()) {
|
||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
// if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
||||
// }
|
||||
// }
|
||||
// } else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
// if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
||||
// }
|
||||
// }
|
||||
// return type;
|
||||
// }
|
||||
static boolean contains(String[] values, String value) {
|
||||
for (String str : values) {
|
||||
if (str.equals(value)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static String[] findConstructorProperties(Creator creator) {
|
||||
if (creator == null) return null;
|
||||
try {
|
||||
ConstructorParameters cps = creator.getClass().getMethod("create", Object[].class).getAnnotation(ConstructorParameters.class);
|
||||
return cps == null ? null : cps.value();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Attribute createAttribute(final ConvertFactory factory, final Type realType, Class clazz, final Field field, final Method getter, final Method setter) {
|
||||
String fieldalias;
|
||||
if (field != null) { // public field
|
||||
ConvertColumnEntry ref = factory.findRef(clazz, field);
|
||||
fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name();
|
||||
} else if (getter != null) {
|
||||
ConvertColumnEntry ref = factory.findRef(clazz, getter);
|
||||
String mfieldname = ConvertFactory.readGetSetFieldName(getter);
|
||||
if (ref == null) {
|
||||
try {
|
||||
ref = factory.findRef(clazz, clazz.getDeclaredField(mfieldname));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
|
||||
} else { // setter != null
|
||||
ConvertColumnEntry ref = factory.findRef(clazz, setter);
|
||||
String mfieldname = ConvertFactory.readGetSetFieldName(setter);
|
||||
if (ref == null) {
|
||||
try {
|
||||
ref = factory.findRef(clazz, clazz.getDeclaredField(mfieldname));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
|
||||
}
|
||||
|
||||
return Attribute.create(realType, clazz, fieldalias, null, field, getter, setter, null);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import org.redkale.convert.ext.StringSimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 自定义对象的序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 序列化的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
||||
|
||||
static final Type[] TYPEZERO = new Type[0];
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Class typeClass;
|
||||
|
||||
protected EnMember[] members;
|
||||
|
||||
protected ConvertFactory factory;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
protected ObjectEncoder(Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.typeClass = (Class) pt.getRawType();
|
||||
} else if (type instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) type;
|
||||
Type[] ts = tv.getBounds();
|
||||
if (ts.length == 1 && ts[0] instanceof Class) {
|
||||
this.typeClass = (Class) ts[0];
|
||||
} else {
|
||||
throw new ConvertException("[" + type + "] is no a class or ParameterizedType");
|
||||
}
|
||||
} else {
|
||||
this.typeClass = (Class) type;
|
||||
}
|
||||
this.members = new EnMember[0];
|
||||
}
|
||||
|
||||
public void init(final ConvertFactory factory) {
|
||||
this.factory = factory;
|
||||
try {
|
||||
if (type == Object.class) return;
|
||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
||||
final Class clazz = this.typeClass;
|
||||
final Set<EnMember> list = new LinkedHashSet();
|
||||
final boolean reversible = factory.isReversible();
|
||||
Creator creator = null;
|
||||
try {
|
||||
creator = factory.loadCreator(this.typeClass);
|
||||
} catch (RuntimeException e) {
|
||||
if (reversible && !Modifier.isAbstract(this.typeClass.getModifiers())) throw e;
|
||||
}
|
||||
final String[] cps = creator == null ? null : ObjectEncoder.findConstructorProperties(creator);
|
||||
try {
|
||||
ConvertColumnEntry ref;
|
||||
|
||||
RedkaleClassLoader.putReflectionPublicFields(clazz.getName());
|
||||
for (final Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
if (factory.isConvertDisabled(field)) continue;
|
||||
ref = factory.findRef(clazz, field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
ConvertSmallString small = field.getAnnotation(ConvertSmallString.class);
|
||||
Encodeable<W, ?> fieldCoder;
|
||||
if (small != null && field.getType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, field.getName());
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
||||
fieldCoder = factory.loadEncoder(t);
|
||||
}
|
||||
EnMember member = new EnMember(createAttribute(factory, type, clazz, field, null, null), fieldCoder, field, null);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
|
||||
RedkaleClassLoader.putReflectionPublicMethods(clazz.getName());
|
||||
for (final Method method : clazz.getMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
if (method.getName().equals("getClass")) continue;
|
||||
if (method.getReturnType() == void.class) continue;
|
||||
if (method.getParameterCount() != 0) continue;
|
||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get") && !Utility.isRecordGetter(clazz, method)) continue;
|
||||
if (factory.isConvertDisabled(method)) continue;
|
||||
String convertname = ConvertFactory.readGetSetFieldName(method);
|
||||
if (reversible && (cps == null || !contains(cps, convertname))) {
|
||||
boolean is = method.getName().startsWith("is");
|
||||
try {
|
||||
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ref = factory.findRef(clazz, method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
ConvertSmallString small = method.getAnnotation(ConvertSmallString.class);
|
||||
if (small == null) {
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(convertname);
|
||||
if (f != null) small = f.getAnnotation(ConvertSmallString.class);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
Encodeable<W, ?> fieldCoder;
|
||||
if (small != null && method.getReturnType() == String.class) {
|
||||
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
|
||||
} else {
|
||||
fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
|
||||
}
|
||||
if (fieldCoder == null) {
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericReturnType(), this.type), this.type);
|
||||
fieldCoder = factory.loadEncoder(t);
|
||||
}
|
||||
EnMember member = new EnMember(createAttribute(factory, type, clazz, null, method, null), fieldCoder, ConvertFactory.readGetSetField(method), method);
|
||||
if (ref != null) member.index = ref.getIndex();
|
||||
list.add(member);
|
||||
}
|
||||
List<EnMember> sorts = new ArrayList<>(list);
|
||||
if (cps != null) {
|
||||
Set<EnMember> dissorts = new LinkedHashSet<>(list);
|
||||
for (final String constructorField : cps) { //reversible模式下需要确保DeMember与EnMember的个数和顺序保持一致,不然postition会不一致导致反序列化对应的字段顺序不同
|
||||
boolean flag = false;
|
||||
for (EnMember m : dissorts) {
|
||||
if (m.attribute.field().equals(constructorField)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) continue;
|
||||
//不存在setter方法
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(constructorField);
|
||||
Type t = TypeToken.createClassType(f.getGenericType(), this.type);
|
||||
try {
|
||||
dissorts.add(new EnMember(createAttribute(factory, type, clazz, f, null, null), null, f, null)); //虚构
|
||||
} catch (RuntimeException e) {
|
||||
}
|
||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||
char[] fs = constructorField.toCharArray();
|
||||
fs[0] = Character.toUpperCase(fs[0]);
|
||||
String mn = new String(fs);
|
||||
Method getter;
|
||||
try {
|
||||
getter = clazz.getMethod("get" + mn);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
getter = clazz.getMethod("is" + mn);
|
||||
}
|
||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(getter.getGenericParameterTypes()[0], this.type), this.type);
|
||||
try {
|
||||
dissorts.add(new EnMember(createAttribute(factory, type, clazz, null, getter, null), null, null, null)); //虚构
|
||||
} catch (RuntimeException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dissorts.size() != list.size()) sorts = new ArrayList<>(dissorts);
|
||||
}
|
||||
Collections.sort(sorts, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
Set<Integer> pos = new HashSet<>();
|
||||
for (EnMember member : sorts) {
|
||||
if (member.index > 0) pos.add(member.index);
|
||||
}
|
||||
int pidx = 0;
|
||||
for (EnMember member : sorts) {
|
||||
if (member.index > 0) {
|
||||
member.position = member.index;
|
||||
} else {
|
||||
while (pos.contains(++pidx));
|
||||
member.position = pidx;
|
||||
}
|
||||
initForEachEnMember(factory, member);
|
||||
}
|
||||
|
||||
this.members = list.toArray(new EnMember[list.size()]);
|
||||
Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new ConvertException("ObjectEncoder init type=" + this.type + " error", ex);
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initForEachEnMember(ConvertFactory factory, EnMember member) {
|
||||
}
|
||||
|
||||
protected void setTag(EnMember member, int tag) {
|
||||
member.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, T value) {
|
||||
if (value == null) {
|
||||
out.writeObjectNull(null);
|
||||
return;
|
||||
}
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value.getClass() != this.typeClass && !this.type.equals(out.specify())) {
|
||||
final Class clz = value.getClass();
|
||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
|
||||
factory.loadEncoder(clz).convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
W objout = objectWriter(out, value);
|
||||
if (objout.writeObjectB(value) < 0) {
|
||||
int maxPosition = 0;
|
||||
for (EnMember member : members) {
|
||||
maxPosition = member.getPosition();
|
||||
objout.writeObjectField(member, value);
|
||||
}
|
||||
if (objout.objExtFunc != null) {
|
||||
ConvertField[] extFields = objout.objExtFunc.apply(value);
|
||||
if (extFields != null) {
|
||||
Encodeable<W, ?> anyEncoder = factory.getAnyEncoder();
|
||||
for (ConvertField en : extFields) {
|
||||
if (en == null) continue;
|
||||
maxPosition++;
|
||||
objout.writeObjectField(en.getName(), en.getType(), Math.max(en.getPosition(), maxPosition), anyEncoder, en.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
objout.writeObjectE(value);
|
||||
}
|
||||
|
||||
protected W objectWriter(W out, T value) {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Class getTypeClass() {
|
||||
return this.typeClass;
|
||||
}
|
||||
|
||||
public EnMember[] getMembers() {
|
||||
return Arrays.copyOf(members, members.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||
}
|
||||
|
||||
//
|
||||
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
||||
// if (type instanceof Class) { //e.g. String
|
||||
// return type;
|
||||
// } else if (type instanceof ParameterizedType) { //e.g. Map<String, String>
|
||||
// final ParameterizedType pt = (ParameterizedType) type;
|
||||
// Type[] paramTypes = pt.getActualTypeArguments();
|
||||
// final Type[] newTypes = new Type[paramTypes.length];
|
||||
// int count = 0;
|
||||
// for (int i = 0; i < newTypes.length; i++) {
|
||||
// newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
||||
// if (paramTypes[i] == newTypes[i]) count++;
|
||||
// }
|
||||
// if (count == paramTypes.length) return pt;
|
||||
// return new ParameterizedType() {
|
||||
//
|
||||
// @Override
|
||||
// public Type[] getActualTypeArguments() {
|
||||
// return newTypes;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Type getRawType() {
|
||||
// return pt.getRawType();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Type getOwnerType() {
|
||||
// return pt.getOwnerType();
|
||||
// }
|
||||
//
|
||||
// };
|
||||
// }
|
||||
// if (realGenericTypes == null) return type;
|
||||
// if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
||||
// final WildcardType wt = (WildcardType) type;
|
||||
// for (Type f : wt.getUpperBounds()) {
|
||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
// if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
||||
// }
|
||||
// }
|
||||
// } else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
// if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
||||
// }
|
||||
// }
|
||||
// return type;
|
||||
// }
|
||||
static boolean contains(String[] values, String value) {
|
||||
for (String str : values) {
|
||||
if (str.equals(value)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static String[] findConstructorProperties(Creator creator) {
|
||||
if (creator == null) return null;
|
||||
try {
|
||||
ConstructorParameters cps = creator.getClass().getMethod("create", Object[].class).getAnnotation(ConstructorParameters.class);
|
||||
return cps == null ? null : cps.value();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Attribute createAttribute(final ConvertFactory factory, final Type realType, Class clazz, final Field field, final Method getter, final Method setter) {
|
||||
String fieldalias;
|
||||
if (field != null) { // public field
|
||||
ConvertColumnEntry ref = factory.findRef(clazz, field);
|
||||
fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name();
|
||||
} else if (getter != null) {
|
||||
ConvertColumnEntry ref = factory.findRef(clazz, getter);
|
||||
String mfieldname = ConvertFactory.readGetSetFieldName(getter);
|
||||
if (ref == null) {
|
||||
try {
|
||||
ref = factory.findRef(clazz, clazz.getDeclaredField(mfieldname));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
|
||||
} else { // setter != null
|
||||
ConvertColumnEntry ref = factory.findRef(clazz, setter);
|
||||
String mfieldname = ConvertFactory.readGetSetFieldName(setter);
|
||||
if (ref == null) {
|
||||
try {
|
||||
ref = factory.findRef(clazz, clazz.getDeclaredField(mfieldname));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
|
||||
}
|
||||
|
||||
return Attribute.create(realType, clazz, fieldalias, null, field, getter, setter, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Optional 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class OptionalCoder<R extends Reader, W extends Writer, T> extends SimpledCoder<R, W, Optional<T>> {
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected final Class componentClass;
|
||||
|
||||
protected final Decodeable<Reader, T> decoder;
|
||||
|
||||
protected final Encodeable<Writer, T> encoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public OptionalCoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.componentType = pt.getActualTypeArguments()[0];
|
||||
factory.register(type, this);
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
if (this.componentType instanceof TypeVariable) {
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
this.componentClass = Object.class;
|
||||
} else {
|
||||
if (componentType instanceof ParameterizedType) {
|
||||
final ParameterizedType pt2 = (ParameterizedType) componentType;
|
||||
this.componentClass = (Class) pt2.getRawType();
|
||||
} else {
|
||||
this.componentClass = (Class) componentType;
|
||||
}
|
||||
this.encoder = factory.loadEncoder(this.componentType);
|
||||
}
|
||||
} else {
|
||||
this.componentType = Object.class;
|
||||
this.componentClass = Object.class;
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Optional<T> value) {
|
||||
if (value == null || !value.isPresent()) {
|
||||
out.writeObjectNull(null);
|
||||
return;
|
||||
}
|
||||
if (this.encoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.encoder.convertTo(out, value.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> convertFrom(R in) {
|
||||
if (this.decoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.ofNullable(this.decoder.convertFrom(in));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Optional 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class OptionalCoder<R extends Reader, W extends Writer, T> extends SimpledCoder<R, W, Optional<T>> {
|
||||
|
||||
protected final Type componentType;
|
||||
|
||||
protected final Class componentClass;
|
||||
|
||||
protected final Decodeable<Reader, T> decoder;
|
||||
|
||||
protected final Encodeable<Writer, T> encoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public OptionalCoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.componentType = pt.getActualTypeArguments()[0];
|
||||
factory.register(type, this);
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
if (this.componentType instanceof TypeVariable) {
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
this.componentClass = Object.class;
|
||||
} else {
|
||||
if (componentType instanceof ParameterizedType) {
|
||||
final ParameterizedType pt2 = (ParameterizedType) componentType;
|
||||
this.componentClass = (Class) pt2.getRawType();
|
||||
} else {
|
||||
this.componentClass = (Class) componentType;
|
||||
}
|
||||
this.encoder = factory.loadEncoder(this.componentType);
|
||||
}
|
||||
} else {
|
||||
this.componentType = Object.class;
|
||||
this.componentClass = Object.class;
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Optional<T> value) {
|
||||
if (value == null || !value.isPresent()) {
|
||||
out.writeObjectNull(null);
|
||||
return;
|
||||
}
|
||||
if (this.encoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.encoder.convertTo(out, value.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> convertFrom(R in) {
|
||||
if (this.decoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.ofNullable(this.decoder.convertFrom(in));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,234 +1,234 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* 反序列化的数据读取流
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class Reader {
|
||||
|
||||
public static enum ValueType {
|
||||
STRING, ARRAY, MAP;
|
||||
}
|
||||
|
||||
//当前对象字段名的游标
|
||||
protected int fieldIndex;
|
||||
|
||||
public static final short SIGN_NULL = -1;
|
||||
|
||||
public static final short SIGN_NOLENGTH = -2;
|
||||
|
||||
public static final short SIGN_NOLENBUTBYTES = -3; //目前只适合于protobuf的boolean[]...double[]类型
|
||||
|
||||
/**
|
||||
* 是否还存在下个元素或字段 <br>
|
||||
* 注意: 主要用于Array、Collection、Stream或Map等集合对象
|
||||
*
|
||||
* @param startPosition 起始位置
|
||||
* @param contentLength 内容大小, 不确定的传-1
|
||||
*
|
||||
* @return 是否还存在下个元素或字段
|
||||
*/
|
||||
public abstract boolean hasNext(int startPosition, int contentLength);
|
||||
|
||||
/**
|
||||
* 是否还存在下个元素或字段
|
||||
*
|
||||
*
|
||||
* @return 是否还存在下个元素或字段
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return hasNext(-1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前位置
|
||||
*
|
||||
* @return 当前位置
|
||||
*/
|
||||
public abstract int position();
|
||||
|
||||
/**
|
||||
* 读取字段值内容的字节数 <br>
|
||||
* 只有在readXXXB方法返回SIGN_NOLENBUTBYTES值才会调用此方法
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param decoder Decodeable
|
||||
*
|
||||
* @return 内容大小, 不确定返回-1
|
||||
*/
|
||||
public abstract int readMemberContentLength(DeMember member, Decodeable decoder);
|
||||
|
||||
/**
|
||||
* 跳过值(不包含值前面的字段)
|
||||
*/
|
||||
public abstract void skipValue();
|
||||
|
||||
/**
|
||||
* /跳过字段与值之间的多余内容, json就是跳过:符, map跳过:
|
||||
*/
|
||||
public abstract void readBlank();
|
||||
|
||||
/**
|
||||
* 读取下个值的类型
|
||||
*
|
||||
* @return ValueType
|
||||
*/
|
||||
public abstract ValueType readType();
|
||||
|
||||
/**
|
||||
* 读取对象的类名, 返回 null 表示对象为null, 返回空字符串表示当前class与返回的class一致,返回非空字符串表示class是当前class的子类。
|
||||
*
|
||||
* @param clazz 类名
|
||||
*
|
||||
* @return 返回字段数
|
||||
*/
|
||||
public String readObjectB(final Class clazz) {
|
||||
this.fieldIndex = 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取对象的尾端
|
||||
*
|
||||
* @param clazz 类名
|
||||
*/
|
||||
public abstract void readObjectE(final Class clazz);
|
||||
|
||||
/**
|
||||
* 读取数组的开头并返回数组的长度
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param componentDecoder Decodeable
|
||||
*
|
||||
* @return 返回数组的长度
|
||||
*/
|
||||
public abstract int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder);
|
||||
|
||||
/**
|
||||
* 读取数组的尾端
|
||||
*
|
||||
*/
|
||||
public abstract void readArrayE();
|
||||
|
||||
/**
|
||||
* 读取map的开头并返回map的size
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param keyDecoder Decodeable
|
||||
* @param valueDecoder Decodeable
|
||||
*
|
||||
* @return 返回map的size
|
||||
*/
|
||||
public abstract int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder);
|
||||
|
||||
/**
|
||||
* 读取数组的尾端
|
||||
*
|
||||
*/
|
||||
public abstract void readMapE();
|
||||
|
||||
/**
|
||||
* 根据字段读取字段对应的DeMember
|
||||
*
|
||||
* @param members DeMember的全量集合
|
||||
*
|
||||
* @return 匹配的DeMember
|
||||
*/
|
||||
public abstract DeMember readFieldName(final DeMember[] members);
|
||||
|
||||
/**
|
||||
* 读取一个boolean值
|
||||
*
|
||||
* @return boolean值
|
||||
*/
|
||||
public abstract boolean readBoolean();
|
||||
|
||||
/**
|
||||
* 读取一个byte值
|
||||
*
|
||||
* @return byte值
|
||||
*/
|
||||
public abstract byte readByte();
|
||||
|
||||
/**
|
||||
* 读取byte[]
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public abstract byte[] readByteArray();
|
||||
|
||||
/**
|
||||
* 读取一个char值
|
||||
*
|
||||
* @return char值
|
||||
*/
|
||||
public abstract char readChar();
|
||||
|
||||
/**
|
||||
* 读取一个short值
|
||||
*
|
||||
* @return short值
|
||||
*/
|
||||
public abstract short readShort();
|
||||
|
||||
/**
|
||||
* 读取一个int值
|
||||
*
|
||||
* @return int值
|
||||
*/
|
||||
public abstract int readInt();
|
||||
|
||||
/**
|
||||
* 读取一个long值
|
||||
*
|
||||
* @return long值
|
||||
*/
|
||||
public abstract long readLong();
|
||||
|
||||
/**
|
||||
* 读取一个float值
|
||||
*
|
||||
* @return float值
|
||||
*/
|
||||
public abstract float readFloat();
|
||||
|
||||
/**
|
||||
* 读取一个double值
|
||||
*
|
||||
* @return double值
|
||||
*/
|
||||
public abstract double readDouble();
|
||||
|
||||
/**
|
||||
* 读取无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等
|
||||
*
|
||||
* @return String值
|
||||
*/
|
||||
public abstract String readSmallString();
|
||||
|
||||
/**
|
||||
* 读取反解析对象的类名
|
||||
*
|
||||
* @return 类名
|
||||
*/
|
||||
public abstract String readClassName();
|
||||
|
||||
/**
|
||||
* 读取一个String值
|
||||
*
|
||||
* @return String值
|
||||
*/
|
||||
public abstract String readString();
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
/**
|
||||
* 反序列化的数据读取流
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class Reader {
|
||||
|
||||
public static enum ValueType {
|
||||
STRING, ARRAY, MAP;
|
||||
}
|
||||
|
||||
//当前对象字段名的游标
|
||||
protected int fieldIndex;
|
||||
|
||||
public static final short SIGN_NULL = -1;
|
||||
|
||||
public static final short SIGN_NOLENGTH = -2;
|
||||
|
||||
public static final short SIGN_NOLENBUTBYTES = -3; //目前只适合于protobuf的boolean[]...double[]类型
|
||||
|
||||
/**
|
||||
* 是否还存在下个元素或字段 <br>
|
||||
* 注意: 主要用于Array、Collection、Stream或Map等集合对象
|
||||
*
|
||||
* @param startPosition 起始位置
|
||||
* @param contentLength 内容大小, 不确定的传-1
|
||||
*
|
||||
* @return 是否还存在下个元素或字段
|
||||
*/
|
||||
public abstract boolean hasNext(int startPosition, int contentLength);
|
||||
|
||||
/**
|
||||
* 是否还存在下个元素或字段
|
||||
*
|
||||
*
|
||||
* @return 是否还存在下个元素或字段
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return hasNext(-1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前位置
|
||||
*
|
||||
* @return 当前位置
|
||||
*/
|
||||
public abstract int position();
|
||||
|
||||
/**
|
||||
* 读取字段值内容的字节数 <br>
|
||||
* 只有在readXXXB方法返回SIGN_NOLENBUTBYTES值才会调用此方法
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param decoder Decodeable
|
||||
*
|
||||
* @return 内容大小, 不确定返回-1
|
||||
*/
|
||||
public abstract int readMemberContentLength(DeMember member, Decodeable decoder);
|
||||
|
||||
/**
|
||||
* 跳过值(不包含值前面的字段)
|
||||
*/
|
||||
public abstract void skipValue();
|
||||
|
||||
/**
|
||||
* /跳过字段与值之间的多余内容, json就是跳过:符, map跳过:
|
||||
*/
|
||||
public abstract void readBlank();
|
||||
|
||||
/**
|
||||
* 读取下个值的类型
|
||||
*
|
||||
* @return ValueType
|
||||
*/
|
||||
public abstract ValueType readType();
|
||||
|
||||
/**
|
||||
* 读取对象的类名, 返回 null 表示对象为null, 返回空字符串表示当前class与返回的class一致,返回非空字符串表示class是当前class的子类。
|
||||
*
|
||||
* @param clazz 类名
|
||||
*
|
||||
* @return 返回字段数
|
||||
*/
|
||||
public String readObjectB(final Class clazz) {
|
||||
this.fieldIndex = 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取对象的尾端
|
||||
*
|
||||
* @param clazz 类名
|
||||
*/
|
||||
public abstract void readObjectE(final Class clazz);
|
||||
|
||||
/**
|
||||
* 读取数组的开头并返回数组的长度
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param componentDecoder Decodeable
|
||||
*
|
||||
* @return 返回数组的长度
|
||||
*/
|
||||
public abstract int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder);
|
||||
|
||||
/**
|
||||
* 读取数组的尾端
|
||||
*
|
||||
*/
|
||||
public abstract void readArrayE();
|
||||
|
||||
/**
|
||||
* 读取map的开头并返回map的size
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param keyDecoder Decodeable
|
||||
* @param valueDecoder Decodeable
|
||||
*
|
||||
* @return 返回map的size
|
||||
*/
|
||||
public abstract int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder);
|
||||
|
||||
/**
|
||||
* 读取数组的尾端
|
||||
*
|
||||
*/
|
||||
public abstract void readMapE();
|
||||
|
||||
/**
|
||||
* 根据字段读取字段对应的DeMember
|
||||
*
|
||||
* @param members DeMember的全量集合
|
||||
*
|
||||
* @return 匹配的DeMember
|
||||
*/
|
||||
public abstract DeMember readFieldName(final DeMember[] members);
|
||||
|
||||
/**
|
||||
* 读取一个boolean值
|
||||
*
|
||||
* @return boolean值
|
||||
*/
|
||||
public abstract boolean readBoolean();
|
||||
|
||||
/**
|
||||
* 读取一个byte值
|
||||
*
|
||||
* @return byte值
|
||||
*/
|
||||
public abstract byte readByte();
|
||||
|
||||
/**
|
||||
* 读取byte[]
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public abstract byte[] readByteArray();
|
||||
|
||||
/**
|
||||
* 读取一个char值
|
||||
*
|
||||
* @return char值
|
||||
*/
|
||||
public abstract char readChar();
|
||||
|
||||
/**
|
||||
* 读取一个short值
|
||||
*
|
||||
* @return short值
|
||||
*/
|
||||
public abstract short readShort();
|
||||
|
||||
/**
|
||||
* 读取一个int值
|
||||
*
|
||||
* @return int值
|
||||
*/
|
||||
public abstract int readInt();
|
||||
|
||||
/**
|
||||
* 读取一个long值
|
||||
*
|
||||
* @return long值
|
||||
*/
|
||||
public abstract long readLong();
|
||||
|
||||
/**
|
||||
* 读取一个float值
|
||||
*
|
||||
* @return float值
|
||||
*/
|
||||
public abstract float readFloat();
|
||||
|
||||
/**
|
||||
* 读取一个double值
|
||||
*
|
||||
* @return double值
|
||||
*/
|
||||
public abstract double readDouble();
|
||||
|
||||
/**
|
||||
* 读取无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等
|
||||
*
|
||||
* @return String值
|
||||
*/
|
||||
public abstract String readSmallString();
|
||||
|
||||
/**
|
||||
* 读取反解析对象的类名
|
||||
*
|
||||
* @return 类名
|
||||
*/
|
||||
public abstract String readClassName();
|
||||
|
||||
/**
|
||||
* 读取一个String值
|
||||
*
|
||||
* @return String值
|
||||
*/
|
||||
public abstract String readString();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 简易类的序列化和反序列化操作类 <br>
|
||||
* 能序列化为Boolean、Number或者字符串的类视为简易类 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 序列化/反解析的数据类型
|
||||
*/
|
||||
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
|
||||
|
||||
protected Type type;
|
||||
|
||||
@Override
|
||||
public abstract void convertTo(final W out, final T value);
|
||||
|
||||
@Override
|
||||
public abstract T convertFrom(final R in);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<T> getType() {
|
||||
if (type == null) {
|
||||
Type[] ts = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
|
||||
type = ts[ts.length - 1];
|
||||
}
|
||||
return (Class<T>) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 简易类的序列化和反序列化操作类 <br>
|
||||
* 能序列化为Boolean、Number或者字符串的类视为简易类 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
* @param <T> 序列化/反解析的数据类型
|
||||
*/
|
||||
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
|
||||
|
||||
protected Type type;
|
||||
|
||||
@Override
|
||||
public abstract void convertTo(final W out, final T value);
|
||||
|
||||
@Override
|
||||
public abstract T convertFrom(final R in);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<T> getType() {
|
||||
if (type == null) {
|
||||
Type[] ts = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
|
||||
type = ts[ts.length - 1];
|
||||
}
|
||||
return (Class<T>) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +1,107 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Stream的序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的集合元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Encodeable<Writer, Object> componentEncoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public StreamEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (t instanceof TypeVariable) {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
} else {
|
||||
this.componentEncoder = factory.loadEncoder(t);
|
||||
}
|
||||
} else {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, Stream<T> value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, Stream<T> value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
Object[] array = value.toArray();
|
||||
if (array.length == 0) {
|
||||
out.writeArrayB(0, this, componentEncoder, array);
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.componentEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out.writeArrayB(array.length, this, componentEncoder, array) < 0) {
|
||||
boolean first = true;
|
||||
for (Object v : array) {
|
||||
if (!first) out.writeArrayMark();
|
||||
writeMemberValue(out, member, v, first);
|
||||
if (first) first = false;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
||||
componentEncoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||
return componentEncoder;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentEncoder == null ? null : componentEncoder.getType();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Stream的序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的集合元素类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
||||
|
||||
protected final Type type;
|
||||
|
||||
protected final Encodeable<Writer, Object> componentEncoder;
|
||||
|
||||
protected volatile boolean inited = false;
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
public StreamEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (t instanceof TypeVariable) {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
} else {
|
||||
this.componentEncoder = factory.loadEncoder(t);
|
||||
}
|
||||
} else {
|
||||
this.componentEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(Writer out, Stream<T> value) {
|
||||
convertTo(out, null, value);
|
||||
}
|
||||
|
||||
public void convertTo(Writer out, EnMember member, Stream<T> value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
Object[] array = value.toArray();
|
||||
if (array.length == 0) {
|
||||
out.writeArrayB(0, this, componentEncoder, array);
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.componentEncoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out.writeArrayB(array.length, this, componentEncoder, array) < 0) {
|
||||
boolean first = true;
|
||||
for (Object v : array) {
|
||||
if (!first) out.writeArrayMark();
|
||||
writeMemberValue(out, member, v, first);
|
||||
if (first) first = false;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
||||
componentEncoder.convertTo(out, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||
return componentEncoder;
|
||||
}
|
||||
|
||||
public Type getComponentType() {
|
||||
return componentEncoder == null ? null : componentEncoder.getType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 文本序列化/反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
*/
|
||||
public abstract class TextConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||
|
||||
protected TextConvert(ConvertFactory<R, W> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isBinary() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract String convertTo(final Object value);
|
||||
|
||||
public abstract String convertTo(final Type type, final Object value);
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 文本序列化/反序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
* @param <W> Writer输出的子类
|
||||
*/
|
||||
public abstract class TextConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||
|
||||
protected TextConvert(ConvertFactory<R, W> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isBinary() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract String convertTo(final Object value);
|
||||
|
||||
public abstract String convertTo(final Type type, final Object value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,326 +1,326 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 序列化的数据输出流
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class Writer {
|
||||
|
||||
//当前对象输出字段名之前是否需要分隔符, JSON字段间的分隔符为,逗号
|
||||
protected boolean comma;
|
||||
|
||||
//convertTo时是否以指定Type的ObjectEncoder进行处理
|
||||
protected Type specify;
|
||||
|
||||
//对某个字段值进行动态处理
|
||||
protected BiFunction<Attribute, Object, Object> objFieldFunc;
|
||||
|
||||
//对某个对象进行动态扩展字段值处理
|
||||
protected Function<Object, ConvertField[]> objExtFunc;
|
||||
|
||||
/**
|
||||
* 设置specify
|
||||
*
|
||||
* @param value Type
|
||||
*/
|
||||
public void specify(Type value) {
|
||||
if (value instanceof GenericArrayType) {
|
||||
this.specify = ((GenericArrayType) value).getGenericComponentType();
|
||||
} else if (value instanceof Class && ((Class) value).isArray()) {
|
||||
this.specify = ((Class) value).getComponentType();
|
||||
} else {
|
||||
this.specify = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean recycle() {
|
||||
this.objFieldFunc = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回specify
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public Type specify() {
|
||||
return this.specify;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。
|
||||
*
|
||||
* @return 是否简化
|
||||
*/
|
||||
public abstract boolean tiny();
|
||||
|
||||
/**
|
||||
* 输出null值
|
||||
*/
|
||||
public abstract void writeNull();
|
||||
|
||||
/**
|
||||
* 是否需要写入类名, BSON需要, JSON不需要
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public abstract boolean needWriteClassName();
|
||||
|
||||
/**
|
||||
* 写入类名
|
||||
*
|
||||
* @param clazz 类名
|
||||
*/
|
||||
public abstract void writeClassName(String clazz);
|
||||
|
||||
/**
|
||||
* 输出一个对象前的操作
|
||||
* 注: 覆盖此方法必须要先调用父方法 super.writeObjectB(obj);
|
||||
*
|
||||
* @param obj 写入的对象
|
||||
*
|
||||
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||
*/
|
||||
public int writeObjectB(Object obj) {
|
||||
this.comma = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个为null的对象
|
||||
*
|
||||
* @param clazz 对象的类名
|
||||
*/
|
||||
public final void writeObjectNull(final Class clazz) {
|
||||
writeClassName(null);
|
||||
writeNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个对象的某个字段
|
||||
*
|
||||
* @param member 字段
|
||||
*
|
||||
* @param obj 写入的对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writeObjectField(final EnMember member, Object obj) {
|
||||
Object value;
|
||||
if (objFieldFunc == null) {
|
||||
value = member.attribute.get(obj);
|
||||
} else {
|
||||
value = objFieldFunc.apply(member.attribute, obj);
|
||||
}
|
||||
if (value == null) return;
|
||||
if (tiny()) {
|
||||
if (member.string) {
|
||||
if (((CharSequence) value).length() == 0) return;
|
||||
} else if (member.bool) {
|
||||
if (!((Boolean) value)) return;
|
||||
}
|
||||
}
|
||||
Attribute attr = member.getAttribute();
|
||||
this.writeFieldName(member, attr.field(), attr.genericType(), member.getPosition());
|
||||
member.encoder.convertTo(this, value);
|
||||
this.comma = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个对象的某个扩展字段
|
||||
*
|
||||
*
|
||||
* @param fieldName 字段名称
|
||||
* @param fieldType 字段类型
|
||||
* @param fieldPos 字段顺序
|
||||
* @param anyEncoder Encoder
|
||||
* @param value 写入的字段对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writeObjectField(final String fieldName, Type fieldType, int fieldPos, Encodeable anyEncoder, Object value) {
|
||||
if (value == null) return;
|
||||
if (fieldType == null) fieldType = value.getClass();
|
||||
if (tiny() && fieldType instanceof Class) {
|
||||
Class clazz = (Class) fieldType;
|
||||
if (CharSequence.class.isAssignableFrom(clazz)) {
|
||||
if (((CharSequence) value).length() == 0) return;
|
||||
} else if (clazz == boolean.class || clazz == Boolean.class) {
|
||||
if (!((Boolean) value)) return;
|
||||
}
|
||||
}
|
||||
this.writeFieldName(null, fieldName, fieldType, fieldPos);
|
||||
anyEncoder.convertTo(this, value);
|
||||
this.comma = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个字段名
|
||||
*
|
||||
* @param member 字段
|
||||
*/
|
||||
public final void writeFieldName(final EnMember member) {
|
||||
Attribute attr = member.getAttribute();
|
||||
this.writeFieldName(member, attr.field(), attr.genericType(), member.getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个对象后的操作
|
||||
*
|
||||
* @param obj 写入的对象
|
||||
*/
|
||||
public abstract void writeObjectE(Object obj);
|
||||
|
||||
/**
|
||||
* 输出一个数组前的操作
|
||||
*
|
||||
* @param size 数组长度
|
||||
* @param arrayEncoder Encodeable 可能是ArrayEncoder、CollectionEncoder或StreamEncoder
|
||||
* @param componentEncoder Encodeable
|
||||
* @param obj 对象, 不一定是数组、Collection对象,也可能是伪Collection对象
|
||||
*
|
||||
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||
*/
|
||||
public abstract int writeArrayB(int size, Encodeable arrayEncoder, Encodeable<Writer, Object> componentEncoder, Object obj);
|
||||
|
||||
/**
|
||||
* 输出数组元素间的间隔符
|
||||
*
|
||||
*/
|
||||
public abstract void writeArrayMark();
|
||||
|
||||
/**
|
||||
* 输出一个数组后的操作
|
||||
*
|
||||
*/
|
||||
public abstract void writeArrayE();
|
||||
|
||||
/**
|
||||
* 输出一个Map前的操作
|
||||
*
|
||||
* @param size map大小
|
||||
* @param keyEncoder Encodeable
|
||||
* @param valueEncoder Encodeable
|
||||
* @param obj 对象, 不一定是Map对象,也可能是伪Map对象
|
||||
*
|
||||
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||
*/
|
||||
public abstract int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj);
|
||||
|
||||
/**
|
||||
* 输出一个Map中key与value间的间隔符
|
||||
*
|
||||
*/
|
||||
public abstract void writeMapMark();
|
||||
|
||||
/**
|
||||
* 输出一个Map后的操作
|
||||
*
|
||||
*/
|
||||
public abstract void writeMapE();
|
||||
|
||||
/**
|
||||
* 输出一个字段名
|
||||
*
|
||||
* @param member EnMember
|
||||
* @param fieldName 字段名称
|
||||
* @param fieldType 字段类型
|
||||
* @param fieldPos 字段顺序
|
||||
*/
|
||||
public abstract void writeFieldName(EnMember member, String fieldName, Type fieldType, int fieldPos);
|
||||
|
||||
/**
|
||||
* 写入一个boolean值
|
||||
*
|
||||
* @param value boolean值
|
||||
*/
|
||||
public abstract void writeBoolean(boolean value);
|
||||
|
||||
/**
|
||||
* 写入一个byte值
|
||||
*
|
||||
* @param value byte值
|
||||
*/
|
||||
public abstract void writeByte(byte value);
|
||||
|
||||
/**
|
||||
* 写入byte[]
|
||||
*
|
||||
* @param values byte[]
|
||||
*/
|
||||
public abstract void writeByteArray(byte[] values);
|
||||
|
||||
/**
|
||||
* 写入一个char值
|
||||
*
|
||||
* @param value char值
|
||||
*/
|
||||
public abstract void writeChar(char value);
|
||||
|
||||
/**
|
||||
* 写入一个short值
|
||||
*
|
||||
* @param value short值
|
||||
*/
|
||||
public abstract void writeShort(short value);
|
||||
|
||||
/**
|
||||
* 写入一个int值
|
||||
*
|
||||
* @param value int值
|
||||
*/
|
||||
public abstract void writeInt(int value);
|
||||
|
||||
/**
|
||||
* 写入一个long值
|
||||
*
|
||||
* @param value long值
|
||||
*/
|
||||
public abstract void writeLong(long value);
|
||||
|
||||
/**
|
||||
* 写入一个float值
|
||||
*
|
||||
* @param value float值
|
||||
*/
|
||||
public abstract void writeFloat(float value);
|
||||
|
||||
/**
|
||||
* 写入一个double值
|
||||
*
|
||||
* @param value double值
|
||||
*/
|
||||
public abstract void writeDouble(double value);
|
||||
|
||||
/**
|
||||
* 写入无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等 *
|
||||
*
|
||||
* @param value 非空且不含需要转义的字符的String值
|
||||
*/
|
||||
public abstract void writeSmallString(String value);
|
||||
|
||||
/**
|
||||
* 写入一个String值
|
||||
*
|
||||
* @param value String值
|
||||
*/
|
||||
public abstract void writeString(String value);
|
||||
|
||||
/**
|
||||
* 写入一个StringConvertWrapper值
|
||||
*
|
||||
* @param value StringConvertWrapper值
|
||||
*/
|
||||
public abstract void writeWrapper(StringWrapper value);
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 序列化的数据输出流
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class Writer {
|
||||
|
||||
//当前对象输出字段名之前是否需要分隔符, JSON字段间的分隔符为,逗号
|
||||
protected boolean comma;
|
||||
|
||||
//convertTo时是否以指定Type的ObjectEncoder进行处理
|
||||
protected Type specify;
|
||||
|
||||
//对某个字段值进行动态处理
|
||||
protected BiFunction<Attribute, Object, Object> objFieldFunc;
|
||||
|
||||
//对某个对象进行动态扩展字段值处理
|
||||
protected Function<Object, ConvertField[]> objExtFunc;
|
||||
|
||||
/**
|
||||
* 设置specify
|
||||
*
|
||||
* @param value Type
|
||||
*/
|
||||
public void specify(Type value) {
|
||||
if (value instanceof GenericArrayType) {
|
||||
this.specify = ((GenericArrayType) value).getGenericComponentType();
|
||||
} else if (value instanceof Class && ((Class) value).isArray()) {
|
||||
this.specify = ((Class) value).getComponentType();
|
||||
} else {
|
||||
this.specify = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean recycle() {
|
||||
this.objFieldFunc = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回specify
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public Type specify() {
|
||||
return this.specify;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。
|
||||
*
|
||||
* @return 是否简化
|
||||
*/
|
||||
public abstract boolean tiny();
|
||||
|
||||
/**
|
||||
* 输出null值
|
||||
*/
|
||||
public abstract void writeNull();
|
||||
|
||||
/**
|
||||
* 是否需要写入类名, BSON需要, JSON不需要
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public abstract boolean needWriteClassName();
|
||||
|
||||
/**
|
||||
* 写入类名
|
||||
*
|
||||
* @param clazz 类名
|
||||
*/
|
||||
public abstract void writeClassName(String clazz);
|
||||
|
||||
/**
|
||||
* 输出一个对象前的操作
|
||||
* 注: 覆盖此方法必须要先调用父方法 super.writeObjectB(obj);
|
||||
*
|
||||
* @param obj 写入的对象
|
||||
*
|
||||
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||
*/
|
||||
public int writeObjectB(Object obj) {
|
||||
this.comma = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个为null的对象
|
||||
*
|
||||
* @param clazz 对象的类名
|
||||
*/
|
||||
public final void writeObjectNull(final Class clazz) {
|
||||
writeClassName(null);
|
||||
writeNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个对象的某个字段
|
||||
*
|
||||
* @param member 字段
|
||||
*
|
||||
* @param obj 写入的对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writeObjectField(final EnMember member, Object obj) {
|
||||
Object value;
|
||||
if (objFieldFunc == null) {
|
||||
value = member.attribute.get(obj);
|
||||
} else {
|
||||
value = objFieldFunc.apply(member.attribute, obj);
|
||||
}
|
||||
if (value == null) return;
|
||||
if (tiny()) {
|
||||
if (member.string) {
|
||||
if (((CharSequence) value).length() == 0) return;
|
||||
} else if (member.bool) {
|
||||
if (!((Boolean) value)) return;
|
||||
}
|
||||
}
|
||||
Attribute attr = member.getAttribute();
|
||||
this.writeFieldName(member, attr.field(), attr.genericType(), member.getPosition());
|
||||
member.encoder.convertTo(this, value);
|
||||
this.comma = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个对象的某个扩展字段
|
||||
*
|
||||
*
|
||||
* @param fieldName 字段名称
|
||||
* @param fieldType 字段类型
|
||||
* @param fieldPos 字段顺序
|
||||
* @param anyEncoder Encoder
|
||||
* @param value 写入的字段对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writeObjectField(final String fieldName, Type fieldType, int fieldPos, Encodeable anyEncoder, Object value) {
|
||||
if (value == null) return;
|
||||
if (fieldType == null) fieldType = value.getClass();
|
||||
if (tiny() && fieldType instanceof Class) {
|
||||
Class clazz = (Class) fieldType;
|
||||
if (CharSequence.class.isAssignableFrom(clazz)) {
|
||||
if (((CharSequence) value).length() == 0) return;
|
||||
} else if (clazz == boolean.class || clazz == Boolean.class) {
|
||||
if (!((Boolean) value)) return;
|
||||
}
|
||||
}
|
||||
this.writeFieldName(null, fieldName, fieldType, fieldPos);
|
||||
anyEncoder.convertTo(this, value);
|
||||
this.comma = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个字段名
|
||||
*
|
||||
* @param member 字段
|
||||
*/
|
||||
public final void writeFieldName(final EnMember member) {
|
||||
Attribute attr = member.getAttribute();
|
||||
this.writeFieldName(member, attr.field(), attr.genericType(), member.getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出一个对象后的操作
|
||||
*
|
||||
* @param obj 写入的对象
|
||||
*/
|
||||
public abstract void writeObjectE(Object obj);
|
||||
|
||||
/**
|
||||
* 输出一个数组前的操作
|
||||
*
|
||||
* @param size 数组长度
|
||||
* @param arrayEncoder Encodeable 可能是ArrayEncoder、CollectionEncoder或StreamEncoder
|
||||
* @param componentEncoder Encodeable
|
||||
* @param obj 对象, 不一定是数组、Collection对象,也可能是伪Collection对象
|
||||
*
|
||||
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||
*/
|
||||
public abstract int writeArrayB(int size, Encodeable arrayEncoder, Encodeable<Writer, Object> componentEncoder, Object obj);
|
||||
|
||||
/**
|
||||
* 输出数组元素间的间隔符
|
||||
*
|
||||
*/
|
||||
public abstract void writeArrayMark();
|
||||
|
||||
/**
|
||||
* 输出一个数组后的操作
|
||||
*
|
||||
*/
|
||||
public abstract void writeArrayE();
|
||||
|
||||
/**
|
||||
* 输出一个Map前的操作
|
||||
*
|
||||
* @param size map大小
|
||||
* @param keyEncoder Encodeable
|
||||
* @param valueEncoder Encodeable
|
||||
* @param obj 对象, 不一定是Map对象,也可能是伪Map对象
|
||||
*
|
||||
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||
*/
|
||||
public abstract int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj);
|
||||
|
||||
/**
|
||||
* 输出一个Map中key与value间的间隔符
|
||||
*
|
||||
*/
|
||||
public abstract void writeMapMark();
|
||||
|
||||
/**
|
||||
* 输出一个Map后的操作
|
||||
*
|
||||
*/
|
||||
public abstract void writeMapE();
|
||||
|
||||
/**
|
||||
* 输出一个字段名
|
||||
*
|
||||
* @param member EnMember
|
||||
* @param fieldName 字段名称
|
||||
* @param fieldType 字段类型
|
||||
* @param fieldPos 字段顺序
|
||||
*/
|
||||
public abstract void writeFieldName(EnMember member, String fieldName, Type fieldType, int fieldPos);
|
||||
|
||||
/**
|
||||
* 写入一个boolean值
|
||||
*
|
||||
* @param value boolean值
|
||||
*/
|
||||
public abstract void writeBoolean(boolean value);
|
||||
|
||||
/**
|
||||
* 写入一个byte值
|
||||
*
|
||||
* @param value byte值
|
||||
*/
|
||||
public abstract void writeByte(byte value);
|
||||
|
||||
/**
|
||||
* 写入byte[]
|
||||
*
|
||||
* @param values byte[]
|
||||
*/
|
||||
public abstract void writeByteArray(byte[] values);
|
||||
|
||||
/**
|
||||
* 写入一个char值
|
||||
*
|
||||
* @param value char值
|
||||
*/
|
||||
public abstract void writeChar(char value);
|
||||
|
||||
/**
|
||||
* 写入一个short值
|
||||
*
|
||||
* @param value short值
|
||||
*/
|
||||
public abstract void writeShort(short value);
|
||||
|
||||
/**
|
||||
* 写入一个int值
|
||||
*
|
||||
* @param value int值
|
||||
*/
|
||||
public abstract void writeInt(int value);
|
||||
|
||||
/**
|
||||
* 写入一个long值
|
||||
*
|
||||
* @param value long值
|
||||
*/
|
||||
public abstract void writeLong(long value);
|
||||
|
||||
/**
|
||||
* 写入一个float值
|
||||
*
|
||||
* @param value float值
|
||||
*/
|
||||
public abstract void writeFloat(float value);
|
||||
|
||||
/**
|
||||
* 写入一个double值
|
||||
*
|
||||
* @param value double值
|
||||
*/
|
||||
public abstract void writeDouble(double value);
|
||||
|
||||
/**
|
||||
* 写入无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等 *
|
||||
*
|
||||
* @param value 非空且不含需要转义的字符的String值
|
||||
*/
|
||||
public abstract void writeSmallString(String value);
|
||||
|
||||
/**
|
||||
* 写入一个String值
|
||||
*
|
||||
* @param value String值
|
||||
*/
|
||||
public abstract void writeString(String value);
|
||||
|
||||
/**
|
||||
* 写入一个StringConvertWrapper值
|
||||
*
|
||||
* @param value StringConvertWrapper值
|
||||
*/
|
||||
public abstract void writeWrapper(StringWrapper value);
|
||||
}
|
||||
|
||||
@@ -1,238 +1,238 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.redkale.convert.*;
|
||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
||||
import org.redkale.convert.ext.ByteSimpledCoder;
|
||||
|
||||
/**
|
||||
* 以ByteBuffer为数据载体的BsonReader
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonByteBufferReader extends BsonReader {
|
||||
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
private int currentIndex = 0;
|
||||
|
||||
private ByteBuffer currentBuffer;
|
||||
|
||||
protected ConvertMask mask;
|
||||
|
||||
protected BsonByteBufferReader(ConvertMask mask, ByteBuffer... buffers) {
|
||||
this.mask = mask;
|
||||
this.buffers = buffers;
|
||||
if (buffers != null && buffers.length > 0) this.currentBuffer = buffers[currentIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle(); // this.position 初始化值为-1
|
||||
this.currentIndex = 0;
|
||||
this.currentBuffer = null;
|
||||
this.buffers = null;
|
||||
this.mask = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte currentByte() {
|
||||
return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
short lt = readShort();
|
||||
byte kt = readByte();
|
||||
byte vt = readByte();
|
||||
if (typevals != null) {
|
||||
typevals[0] = kt;
|
||||
typevals[1] = vt;
|
||||
}
|
||||
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否为[
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param componentDecoder Decodeable
|
||||
*
|
||||
* @return 数组长度或 SIGN_NULL
|
||||
*/
|
||||
@Override
|
||||
public final int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
short lt = readShort();
|
||||
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
|
||||
byte comval = readByte();
|
||||
if (typevals != null) typevals[0] = comval;
|
||||
}
|
||||
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
||||
}
|
||||
//------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final boolean readBoolean() {
|
||||
return readByte() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
if (this.currentBuffer.hasRemaining()) {
|
||||
this.position++;
|
||||
return mask == null ? this.currentBuffer.get() : mask.unmask(this.currentBuffer.get());
|
||||
}
|
||||
for (;;) {
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
if (this.currentBuffer.hasRemaining()) {
|
||||
this.position++;
|
||||
return mask == null ? this.currentBuffer.get() : mask.unmask(this.currentBuffer.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final char readChar() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 2) {
|
||||
this.position += 2;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getChar();
|
||||
} else {
|
||||
return (char) ((0xff00 & (mask.unmask(this.currentBuffer.get()) << 8)) | (0xff & mask.unmask(this.currentBuffer.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (char) ((0xff00 & (readByte() << 8)) | (0xff & readByte()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final short readShort() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 2) {
|
||||
this.position += 2;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getShort();
|
||||
} else {
|
||||
return (short) ((0xff00 & (mask.unmask(this.currentBuffer.get()) << 8)) | (0xff & mask.unmask(this.currentBuffer.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (short) ((0xff00 & (readByte() << 8)) | (0xff & readByte()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int readInt() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 4) {
|
||||
this.position += 4;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getInt();
|
||||
} else {
|
||||
return ((mask.unmask(this.currentBuffer.get()) & 0xff) << 24)
|
||||
| ((mask.unmask(this.currentBuffer.get()) & 0xff) << 16)
|
||||
| ((mask.unmask(this.currentBuffer.get()) & 0xff) << 8)
|
||||
| (mask.unmask(this.currentBuffer.get()) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final long readLong() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 8) {
|
||||
this.position += 8;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getLong();
|
||||
} else {
|
||||
return ((((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 56)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 48)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 40)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 32)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 24)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 16)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 8)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((((long) readByte() & 0xff) << 56)
|
||||
| (((long) readByte() & 0xff) << 48)
|
||||
| (((long) readByte() & 0xff) << 40)
|
||||
| (((long) readByte() & 0xff) << 32)
|
||||
| (((long) readByte() & 0xff) << 24)
|
||||
| (((long) readByte() & 0xff) << 16)
|
||||
| (((long) readByte() & 0xff) << 8)
|
||||
| (((long) readByte() & 0xff)));
|
||||
}
|
||||
|
||||
protected byte[] read(final int len) {
|
||||
byte[] bs = new byte[len];
|
||||
read(bs, 0);
|
||||
return bs;
|
||||
}
|
||||
|
||||
private void read(final byte[] bs, final int pos) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain < 1) {
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
read(bs, pos);
|
||||
return;
|
||||
}
|
||||
int len = bs.length - pos;
|
||||
if (remain >= len) {
|
||||
this.position += len;
|
||||
this.currentBuffer.get(bs, pos, len);
|
||||
if (mask != null) {
|
||||
for (int i = pos, end = pos + len; i < end; i++) {
|
||||
bs[i] = mask.unmask(bs[i]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.currentBuffer.get(bs, pos, remain);
|
||||
if (mask != null) {
|
||||
for (int i = pos, end = pos + remain; i < end; i++) {
|
||||
bs[i] = mask.unmask(bs[i]);
|
||||
}
|
||||
}
|
||||
this.position += remain;
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
read(bs, pos + remain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readSmallString() {
|
||||
int len = 0xff & readByte();
|
||||
if (len == 0) return "";
|
||||
return new String(read(len));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readString() {
|
||||
int len = readInt();
|
||||
if (len == SIGN_NULL) return null;
|
||||
if (len == 0) return "";
|
||||
return new String(read(len), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.redkale.convert.*;
|
||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
||||
import org.redkale.convert.ext.ByteSimpledCoder;
|
||||
|
||||
/**
|
||||
* 以ByteBuffer为数据载体的BsonReader
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonByteBufferReader extends BsonReader {
|
||||
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
private int currentIndex = 0;
|
||||
|
||||
private ByteBuffer currentBuffer;
|
||||
|
||||
protected ConvertMask mask;
|
||||
|
||||
protected BsonByteBufferReader(ConvertMask mask, ByteBuffer... buffers) {
|
||||
this.mask = mask;
|
||||
this.buffers = buffers;
|
||||
if (buffers != null && buffers.length > 0) this.currentBuffer = buffers[currentIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle(); // this.position 初始化值为-1
|
||||
this.currentIndex = 0;
|
||||
this.currentBuffer = null;
|
||||
this.buffers = null;
|
||||
this.mask = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte currentByte() {
|
||||
return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
short lt = readShort();
|
||||
byte kt = readByte();
|
||||
byte vt = readByte();
|
||||
if (typevals != null) {
|
||||
typevals[0] = kt;
|
||||
typevals[1] = vt;
|
||||
}
|
||||
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否为[
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param componentDecoder Decodeable
|
||||
*
|
||||
* @return 数组长度或 SIGN_NULL
|
||||
*/
|
||||
@Override
|
||||
public final int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
short lt = readShort();
|
||||
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
|
||||
byte comval = readByte();
|
||||
if (typevals != null) typevals[0] = comval;
|
||||
}
|
||||
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
||||
}
|
||||
//------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final boolean readBoolean() {
|
||||
return readByte() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
if (this.currentBuffer.hasRemaining()) {
|
||||
this.position++;
|
||||
return mask == null ? this.currentBuffer.get() : mask.unmask(this.currentBuffer.get());
|
||||
}
|
||||
for (;;) {
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
if (this.currentBuffer.hasRemaining()) {
|
||||
this.position++;
|
||||
return mask == null ? this.currentBuffer.get() : mask.unmask(this.currentBuffer.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final char readChar() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 2) {
|
||||
this.position += 2;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getChar();
|
||||
} else {
|
||||
return (char) ((0xff00 & (mask.unmask(this.currentBuffer.get()) << 8)) | (0xff & mask.unmask(this.currentBuffer.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (char) ((0xff00 & (readByte() << 8)) | (0xff & readByte()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final short readShort() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 2) {
|
||||
this.position += 2;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getShort();
|
||||
} else {
|
||||
return (short) ((0xff00 & (mask.unmask(this.currentBuffer.get()) << 8)) | (0xff & mask.unmask(this.currentBuffer.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (short) ((0xff00 & (readByte() << 8)) | (0xff & readByte()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int readInt() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 4) {
|
||||
this.position += 4;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getInt();
|
||||
} else {
|
||||
return ((mask.unmask(this.currentBuffer.get()) & 0xff) << 24)
|
||||
| ((mask.unmask(this.currentBuffer.get()) & 0xff) << 16)
|
||||
| ((mask.unmask(this.currentBuffer.get()) & 0xff) << 8)
|
||||
| (mask.unmask(this.currentBuffer.get()) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final long readLong() {
|
||||
if (this.currentBuffer != null) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain >= 8) {
|
||||
this.position += 8;
|
||||
if (mask == null) {
|
||||
return this.currentBuffer.getLong();
|
||||
} else {
|
||||
return ((((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 56)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 48)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 40)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 32)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 24)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 16)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff) << 8)
|
||||
| (((long) mask.unmask(this.currentBuffer.get()) & 0xff)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((((long) readByte() & 0xff) << 56)
|
||||
| (((long) readByte() & 0xff) << 48)
|
||||
| (((long) readByte() & 0xff) << 40)
|
||||
| (((long) readByte() & 0xff) << 32)
|
||||
| (((long) readByte() & 0xff) << 24)
|
||||
| (((long) readByte() & 0xff) << 16)
|
||||
| (((long) readByte() & 0xff) << 8)
|
||||
| (((long) readByte() & 0xff)));
|
||||
}
|
||||
|
||||
protected byte[] read(final int len) {
|
||||
byte[] bs = new byte[len];
|
||||
read(bs, 0);
|
||||
return bs;
|
||||
}
|
||||
|
||||
private void read(final byte[] bs, final int pos) {
|
||||
int remain = this.currentBuffer.remaining();
|
||||
if (remain < 1) {
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
read(bs, pos);
|
||||
return;
|
||||
}
|
||||
int len = bs.length - pos;
|
||||
if (remain >= len) {
|
||||
this.position += len;
|
||||
this.currentBuffer.get(bs, pos, len);
|
||||
if (mask != null) {
|
||||
for (int i = pos, end = pos + len; i < end; i++) {
|
||||
bs[i] = mask.unmask(bs[i]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.currentBuffer.get(bs, pos, remain);
|
||||
if (mask != null) {
|
||||
for (int i = pos, end = pos + remain; i < end; i++) {
|
||||
bs[i] = mask.unmask(bs[i]);
|
||||
}
|
||||
}
|
||||
this.position += remain;
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
read(bs, pos + remain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readSmallString() {
|
||||
int len = 0xff & readByte();
|
||||
if (len == 0) return "";
|
||||
return new String(read(len));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readString() {
|
||||
int len = readInt();
|
||||
if (len == SIGN_NULL) return null;
|
||||
if (len == 0) return "";
|
||||
return new String(read(len), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,155 +1,155 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 以ByteBuffer为数据载体的BsonWriter
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonByteBufferWriter extends BsonWriter {
|
||||
|
||||
private final Supplier<ByteBuffer> supplier;
|
||||
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
private int index;
|
||||
|
||||
public BsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
|
||||
this(false, supplier);
|
||||
}
|
||||
|
||||
protected BsonByteBufferWriter(boolean tiny, Supplier<ByteBuffer> supplier) {
|
||||
super((byte[]) null);
|
||||
this.tiny = tiny;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] toBuffers() {
|
||||
if (buffers == null) return new ByteBuffer[0];
|
||||
for (int i = index; i < this.buffers.length; i++) {
|
||||
ByteBuffer buf = this.buffers[i];
|
||||
if (buf.position() != 0) buf.flip();
|
||||
}
|
||||
return this.buffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
if (buffers == null) return new byte[0];
|
||||
int pos = 0;
|
||||
byte[] bytes = new byte[this.count];
|
||||
for (ByteBuffer buf : toBuffers()) {
|
||||
int r = buf.remaining();
|
||||
buf.get(bytes, pos, r);
|
||||
buf.flip();
|
||||
pos += r;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonByteBufferWriter tiny(boolean tiny) {
|
||||
this.tiny = tiny;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int expand(final int byteLength) {
|
||||
if (this.buffers == null) {
|
||||
this.index = 0;
|
||||
this.buffers = new ByteBuffer[]{supplier.get()};
|
||||
}
|
||||
ByteBuffer buffer = this.buffers[index];
|
||||
if (!buffer.hasRemaining()) {
|
||||
buffer.flip();
|
||||
buffer = supplier.get();
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
this.index++;
|
||||
}
|
||||
int len = buffer.remaining();
|
||||
int size = 0;
|
||||
while (len < byteLength) {
|
||||
buffer = supplier.get();
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
len += buffer.remaining();
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
if (expand(len) == 0) {
|
||||
this.buffers[index].put(chs, start, len);
|
||||
} else {
|
||||
ByteBuffer buffer = this.buffers[index];
|
||||
final int end = start + len;
|
||||
int remain = len; //还剩多少没有写
|
||||
while (remain > 0) {
|
||||
final int br = buffer.remaining();
|
||||
if (remain > br) { //一个buffer写不完
|
||||
buffer.put(chs, end - remain, br);
|
||||
buffer = nextByteBuffer();
|
||||
remain -= br;
|
||||
} else {
|
||||
buffer.put(chs, end - remain, remain);
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.count += len;
|
||||
}
|
||||
|
||||
private ByteBuffer nextByteBuffer() {
|
||||
this.buffers[this.index].flip();
|
||||
return this.buffers[++this.index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte ch) {
|
||||
expand(1);
|
||||
this.buffers[index].put(ch);
|
||||
count++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.index = 0;
|
||||
this.specify = null;
|
||||
this.buffers = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //无需实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int offset() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");//无需实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //无需实现
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 以ByteBuffer为数据载体的BsonWriter
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonByteBufferWriter extends BsonWriter {
|
||||
|
||||
private final Supplier<ByteBuffer> supplier;
|
||||
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
private int index;
|
||||
|
||||
public BsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
|
||||
this(false, supplier);
|
||||
}
|
||||
|
||||
protected BsonByteBufferWriter(boolean tiny, Supplier<ByteBuffer> supplier) {
|
||||
super((byte[]) null);
|
||||
this.tiny = tiny;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] toBuffers() {
|
||||
if (buffers == null) return new ByteBuffer[0];
|
||||
for (int i = index; i < this.buffers.length; i++) {
|
||||
ByteBuffer buf = this.buffers[i];
|
||||
if (buf.position() != 0) buf.flip();
|
||||
}
|
||||
return this.buffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
if (buffers == null) return new byte[0];
|
||||
int pos = 0;
|
||||
byte[] bytes = new byte[this.count];
|
||||
for (ByteBuffer buf : toBuffers()) {
|
||||
int r = buf.remaining();
|
||||
buf.get(bytes, pos, r);
|
||||
buf.flip();
|
||||
pos += r;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonByteBufferWriter tiny(boolean tiny) {
|
||||
this.tiny = tiny;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int expand(final int byteLength) {
|
||||
if (this.buffers == null) {
|
||||
this.index = 0;
|
||||
this.buffers = new ByteBuffer[]{supplier.get()};
|
||||
}
|
||||
ByteBuffer buffer = this.buffers[index];
|
||||
if (!buffer.hasRemaining()) {
|
||||
buffer.flip();
|
||||
buffer = supplier.get();
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
this.index++;
|
||||
}
|
||||
int len = buffer.remaining();
|
||||
int size = 0;
|
||||
while (len < byteLength) {
|
||||
buffer = supplier.get();
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
len += buffer.remaining();
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
if (expand(len) == 0) {
|
||||
this.buffers[index].put(chs, start, len);
|
||||
} else {
|
||||
ByteBuffer buffer = this.buffers[index];
|
||||
final int end = start + len;
|
||||
int remain = len; //还剩多少没有写
|
||||
while (remain > 0) {
|
||||
final int br = buffer.remaining();
|
||||
if (remain > br) { //一个buffer写不完
|
||||
buffer.put(chs, end - remain, br);
|
||||
buffer = nextByteBuffer();
|
||||
remain -= br;
|
||||
} else {
|
||||
buffer.put(chs, end - remain, remain);
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.count += len;
|
||||
}
|
||||
|
||||
private ByteBuffer nextByteBuffer() {
|
||||
this.buffers[this.index].flip();
|
||||
return this.buffers[++this.index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte ch) {
|
||||
expand(1);
|
||||
this.buffers[index].put(ch);
|
||||
count++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.index = 0;
|
||||
this.specify = null;
|
||||
this.buffers = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //无需实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int offset() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");//无需实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //无需实现
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,297 +1,297 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* BSON协议格式:
|
||||
* 1) 基本数据类型: 直接转换成byte[]
|
||||
* 2) SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
|
||||
* 3) String: length(4 bytes) + byte[](utf8);
|
||||
* 4) 数组: length(4 bytes) + byte[]...
|
||||
* 5) Object:
|
||||
* 1、 realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
|
||||
* 2、 空字符串(SmallString)
|
||||
* 3、 SIGN_OBJECTB 标记位,值固定为0xBB (short)
|
||||
* 4、 循环字段值:
|
||||
* 4.1 SIGN_HASNEXT 标记位,值固定为1 (byte)
|
||||
* 4.2 字段类型; 1-9为基本类型和字符串; 101-109为基本类型和字符串的数组; 127为Object
|
||||
* 4.3 字段名 (SmallString)
|
||||
* 4.4 字段的值Object
|
||||
* 5、 SIGN_NONEXT 标记位,值固定为0 (byte)
|
||||
* 6、 SIGN_OBJECTE 标记位,值固定为0xEE (short)
|
||||
*
|
||||
* </pre></blockquote>
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
||||
|
||||
private final ThreadLocal<BsonWriter> writerPool = ThreadLocal.withInitial(BsonWriter::new);
|
||||
|
||||
private final Consumer<BsonWriter> offerConsumer = w -> offerBsonWriter(w);
|
||||
|
||||
private final boolean tiny;
|
||||
|
||||
protected BsonConvert(ConvertFactory<BsonReader, BsonWriter> factory, boolean tiny) {
|
||||
super(factory);
|
||||
this.tiny = tiny;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory getFactory() {
|
||||
return (BsonFactory) factory;
|
||||
}
|
||||
|
||||
public static BsonConvert root() {
|
||||
return BsonFactory.root().getConvert();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc) {
|
||||
return newConvert(fieldFunc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||
return new BsonConvert(getFactory(), tiny) {
|
||||
@Override
|
||||
protected <S extends BsonWriter> S configWrite(S writer) {
|
||||
return fieldFunc(writer, fieldFunc, objExtFunc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//------------------------------ reader -----------------------------------------------------------
|
||||
public BsonReader pollBsonReader(final ByteBuffer... buffers) {
|
||||
return new BsonByteBufferReader((ConvertMask) null, buffers);
|
||||
}
|
||||
|
||||
public BsonReader pollBsonReader(final InputStream in) {
|
||||
return new BsonStreamReader(in);
|
||||
}
|
||||
|
||||
public BsonReader pollBsonReader() {
|
||||
return new BsonReader();
|
||||
}
|
||||
|
||||
public void offerBsonReader(final BsonReader in) {
|
||||
//无需回收
|
||||
}
|
||||
|
||||
//------------------------------ writer -----------------------------------------------------------
|
||||
public BsonByteBufferWriter pollBsonWriter(final Supplier<ByteBuffer> supplier) {
|
||||
return configWrite(new BsonByteBufferWriter(tiny, supplier));
|
||||
}
|
||||
|
||||
protected BsonWriter pollBsonWriter(final OutputStream out) {
|
||||
return configWrite(new BsonStreamWriter(tiny, out));
|
||||
}
|
||||
|
||||
public BsonWriter pollBsonWriter() {
|
||||
BsonWriter writer = writerPool.get();
|
||||
if (writer == null) {
|
||||
writer = new BsonWriter();
|
||||
} else {
|
||||
writerPool.set(null);
|
||||
}
|
||||
return configWrite(writer.tiny(tiny));
|
||||
}
|
||||
|
||||
public void offerBsonWriter(final BsonWriter out) {
|
||||
if (out != null) {
|
||||
out.recycle();
|
||||
writerPool.set(out);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------ convertFrom -----------------------------------------------------------
|
||||
@Override
|
||||
public <T> T convertFrom(final Type type, final byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
return convertFrom(type, bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int len) {
|
||||
if (type == null) return null;
|
||||
final BsonReader in = new BsonReader(bytes, offset, len);
|
||||
@SuppressWarnings("unchecked")
|
||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
||||
return rs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final InputStream in) {
|
||||
if (type == null || in == null) return null;
|
||||
return (T) factory.loadDecoder(type).convertFrom(new BsonStreamReader(in));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ByteBuffer... buffers) {
|
||||
if (type == null || buffers.length < 1) return null;
|
||||
return (T) factory.loadDecoder(type).convertFrom(new BsonByteBufferReader((ConvertMask) null, buffers));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers) {
|
||||
if (type == null || buffers.length < 1) return null;
|
||||
return (T) factory.loadDecoder(type).convertFrom(new BsonByteBufferReader(mask, buffers));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final BsonReader reader) {
|
||||
if (type == null) return null;
|
||||
@SuppressWarnings("unchecked")
|
||||
T rs = (T) factory.loadDecoder(type).convertFrom(reader);
|
||||
return rs;
|
||||
}
|
||||
|
||||
//------------------------------ convertTo -----------------------------------------------------------
|
||||
@Override
|
||||
public byte[] convertTo(final Object value) {
|
||||
if (value == null) {
|
||||
final BsonWriter out = pollBsonWriter();
|
||||
out.writeNull();
|
||||
byte[] result = out.toArray();
|
||||
offerBsonWriter(out);
|
||||
return result;
|
||||
}
|
||||
return convertTo(value.getClass(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertTo(final Type type, final Object value) {
|
||||
if (type == null) return null;
|
||||
final BsonWriter writer = pollBsonWriter();
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
byte[] result = writer.toArray();
|
||||
offerBsonWriter(writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertToBytes(final Object value) {
|
||||
return convertTo(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertToBytes(final Type type, final Object value) {
|
||||
return convertTo(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final Object value, final ConvertBytesHandler handler) {
|
||||
convertToBytes(value == null ? null : value.getClass(), value, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler) {
|
||||
final BsonWriter writer = pollBsonWriter();
|
||||
if (type == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
writer.completed(handler, offerConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final ByteArray array, final Object value) {
|
||||
convertToBytes(array, value == null ? null : value.getClass(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
||||
final BsonWriter writer = configWrite(new BsonWriter(array).tiny(tiny));
|
||||
if (type == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
writer.directTo(array);
|
||||
}
|
||||
|
||||
public void convertTo(final OutputStream out, final Object value) {
|
||||
if (value == null) {
|
||||
pollBsonWriter(out).writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(value.getClass()).convertTo(pollBsonWriter(out), value);
|
||||
}
|
||||
}
|
||||
|
||||
public void convertTo(final OutputStream out, final Type type, final Object value) {
|
||||
if (type == null) return;
|
||||
if (value == null) {
|
||||
pollBsonWriter(out).writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(pollBsonWriter(out), value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) {
|
||||
if (supplier == null) return null;
|
||||
BsonByteBufferWriter out = pollBsonWriter(supplier);
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
||||
}
|
||||
return out.toBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
|
||||
if (supplier == null || type == null) return null;
|
||||
BsonByteBufferWriter writer = pollBsonWriter(supplier);
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
return writer.toBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(final BsonWriter writer, final Object value) {
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(value.getClass()).convertTo(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(final BsonWriter writer, final Type type, final Object value) {
|
||||
if (type == null) return;
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
|
||||
public BsonWriter convertToWriter(final Object value) {
|
||||
if (value == null) return null;
|
||||
return convertToWriter(value.getClass(), value);
|
||||
}
|
||||
|
||||
public BsonWriter convertToWriter(final Type type, final Object value) {
|
||||
if (type == null) return null;
|
||||
final BsonWriter writer = writerPool.get().tiny(tiny);
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* BSON协议格式:
|
||||
* 1) 基本数据类型: 直接转换成byte[]
|
||||
* 2) SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
|
||||
* 3) String: length(4 bytes) + byte[](utf8);
|
||||
* 4) 数组: length(4 bytes) + byte[]...
|
||||
* 5) Object:
|
||||
* 1、 realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
|
||||
* 2、 空字符串(SmallString)
|
||||
* 3、 SIGN_OBJECTB 标记位,值固定为0xBB (short)
|
||||
* 4、 循环字段值:
|
||||
* 4.1 SIGN_HASNEXT 标记位,值固定为1 (byte)
|
||||
* 4.2 字段类型; 1-9为基本类型和字符串; 101-109为基本类型和字符串的数组; 127为Object
|
||||
* 4.3 字段名 (SmallString)
|
||||
* 4.4 字段的值Object
|
||||
* 5、 SIGN_NONEXT 标记位,值固定为0 (byte)
|
||||
* 6、 SIGN_OBJECTE 标记位,值固定为0xEE (short)
|
||||
*
|
||||
* </pre></blockquote>
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
||||
|
||||
private final ThreadLocal<BsonWriter> writerPool = ThreadLocal.withInitial(BsonWriter::new);
|
||||
|
||||
private final Consumer<BsonWriter> offerConsumer = w -> offerBsonWriter(w);
|
||||
|
||||
private final boolean tiny;
|
||||
|
||||
protected BsonConvert(ConvertFactory<BsonReader, BsonWriter> factory, boolean tiny) {
|
||||
super(factory);
|
||||
this.tiny = tiny;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory getFactory() {
|
||||
return (BsonFactory) factory;
|
||||
}
|
||||
|
||||
public static BsonConvert root() {
|
||||
return BsonFactory.root().getConvert();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc) {
|
||||
return newConvert(fieldFunc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||
return new BsonConvert(getFactory(), tiny) {
|
||||
@Override
|
||||
protected <S extends BsonWriter> S configWrite(S writer) {
|
||||
return fieldFunc(writer, fieldFunc, objExtFunc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//------------------------------ reader -----------------------------------------------------------
|
||||
public BsonReader pollBsonReader(final ByteBuffer... buffers) {
|
||||
return new BsonByteBufferReader((ConvertMask) null, buffers);
|
||||
}
|
||||
|
||||
public BsonReader pollBsonReader(final InputStream in) {
|
||||
return new BsonStreamReader(in);
|
||||
}
|
||||
|
||||
public BsonReader pollBsonReader() {
|
||||
return new BsonReader();
|
||||
}
|
||||
|
||||
public void offerBsonReader(final BsonReader in) {
|
||||
//无需回收
|
||||
}
|
||||
|
||||
//------------------------------ writer -----------------------------------------------------------
|
||||
public BsonByteBufferWriter pollBsonWriter(final Supplier<ByteBuffer> supplier) {
|
||||
return configWrite(new BsonByteBufferWriter(tiny, supplier));
|
||||
}
|
||||
|
||||
protected BsonWriter pollBsonWriter(final OutputStream out) {
|
||||
return configWrite(new BsonStreamWriter(tiny, out));
|
||||
}
|
||||
|
||||
public BsonWriter pollBsonWriter() {
|
||||
BsonWriter writer = writerPool.get();
|
||||
if (writer == null) {
|
||||
writer = new BsonWriter();
|
||||
} else {
|
||||
writerPool.set(null);
|
||||
}
|
||||
return configWrite(writer.tiny(tiny));
|
||||
}
|
||||
|
||||
public void offerBsonWriter(final BsonWriter out) {
|
||||
if (out != null) {
|
||||
out.recycle();
|
||||
writerPool.set(out);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------ convertFrom -----------------------------------------------------------
|
||||
@Override
|
||||
public <T> T convertFrom(final Type type, final byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
return convertFrom(type, bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int len) {
|
||||
if (type == null) return null;
|
||||
final BsonReader in = new BsonReader(bytes, offset, len);
|
||||
@SuppressWarnings("unchecked")
|
||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
||||
return rs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final InputStream in) {
|
||||
if (type == null || in == null) return null;
|
||||
return (T) factory.loadDecoder(type).convertFrom(new BsonStreamReader(in));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ByteBuffer... buffers) {
|
||||
if (type == null || buffers.length < 1) return null;
|
||||
return (T) factory.loadDecoder(type).convertFrom(new BsonByteBufferReader((ConvertMask) null, buffers));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers) {
|
||||
if (type == null || buffers.length < 1) return null;
|
||||
return (T) factory.loadDecoder(type).convertFrom(new BsonByteBufferReader(mask, buffers));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final BsonReader reader) {
|
||||
if (type == null) return null;
|
||||
@SuppressWarnings("unchecked")
|
||||
T rs = (T) factory.loadDecoder(type).convertFrom(reader);
|
||||
return rs;
|
||||
}
|
||||
|
||||
//------------------------------ convertTo -----------------------------------------------------------
|
||||
@Override
|
||||
public byte[] convertTo(final Object value) {
|
||||
if (value == null) {
|
||||
final BsonWriter out = pollBsonWriter();
|
||||
out.writeNull();
|
||||
byte[] result = out.toArray();
|
||||
offerBsonWriter(out);
|
||||
return result;
|
||||
}
|
||||
return convertTo(value.getClass(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertTo(final Type type, final Object value) {
|
||||
if (type == null) return null;
|
||||
final BsonWriter writer = pollBsonWriter();
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
byte[] result = writer.toArray();
|
||||
offerBsonWriter(writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertToBytes(final Object value) {
|
||||
return convertTo(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertToBytes(final Type type, final Object value) {
|
||||
return convertTo(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final Object value, final ConvertBytesHandler handler) {
|
||||
convertToBytes(value == null ? null : value.getClass(), value, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler) {
|
||||
final BsonWriter writer = pollBsonWriter();
|
||||
if (type == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
writer.completed(handler, offerConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final ByteArray array, final Object value) {
|
||||
convertToBytes(array, value == null ? null : value.getClass(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
||||
final BsonWriter writer = configWrite(new BsonWriter(array).tiny(tiny));
|
||||
if (type == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
writer.directTo(array);
|
||||
}
|
||||
|
||||
public void convertTo(final OutputStream out, final Object value) {
|
||||
if (value == null) {
|
||||
pollBsonWriter(out).writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(value.getClass()).convertTo(pollBsonWriter(out), value);
|
||||
}
|
||||
}
|
||||
|
||||
public void convertTo(final OutputStream out, final Type type, final Object value) {
|
||||
if (type == null) return;
|
||||
if (value == null) {
|
||||
pollBsonWriter(out).writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(pollBsonWriter(out), value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) {
|
||||
if (supplier == null) return null;
|
||||
BsonByteBufferWriter out = pollBsonWriter(supplier);
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
||||
}
|
||||
return out.toBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
|
||||
if (supplier == null || type == null) return null;
|
||||
BsonByteBufferWriter writer = pollBsonWriter(supplier);
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
return writer.toBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(final BsonWriter writer, final Object value) {
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
factory.loadEncoder(value.getClass()).convertTo(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(final BsonWriter writer, final Type type, final Object value) {
|
||||
if (type == null) return;
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
}
|
||||
|
||||
public BsonWriter convertToWriter(final Object value) {
|
||||
if (value == null) return null;
|
||||
return convertToWriter(value.getClass(), value);
|
||||
}
|
||||
|
||||
public BsonWriter convertToWriter(final Type type, final Object value) {
|
||||
if (type == null) return null;
|
||||
final BsonWriter writer = writerPool.get().tiny(tiny);
|
||||
factory.loadEncoder(type).convertTo(writer, value);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,212 +1,212 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.ext.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* BSON的ConvertFactory
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
||||
|
||||
private static final BsonFactory instance = new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true));
|
||||
|
||||
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
|
||||
|
||||
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
|
||||
|
||||
static final Decodeable skipArrayDecoder = new SkipArrayDecoder(instance, Object[].class);
|
||||
|
||||
static final Decodeable skipCollectionDecoder = new SkipCollectionDecoder(instance, new TypeToken<Collection<Object>>() {
|
||||
}.getType());
|
||||
|
||||
static final Decodeable skipStreamDecoder = new SkipStreamDecoder(instance, new TypeToken<Stream<Object>>() {
|
||||
}.getType());
|
||||
|
||||
static final Decodeable skipMapDecoder = new SkipMapDecoder(instance, Map.class);
|
||||
|
||||
static {
|
||||
instance.register(Serializable.class, objectDecoder);
|
||||
instance.register(Serializable.class, objectEncoder);
|
||||
|
||||
//instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class));
|
||||
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
||||
}
|
||||
|
||||
private BsonFactory(BsonFactory parent, boolean tiny) {
|
||||
super(parent, tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory tiny(boolean tiny) {
|
||||
this.tiny = tiny;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory skipAllIgnore(final boolean skipIgnore) {
|
||||
this.registerSkipAllIgnore(skipIgnore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static BsonFactory root() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static BsonFactory create() {
|
||||
return new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BsonConvert getConvert() {
|
||||
if (convert == null) convert = new BsonConvert(this, tiny);
|
||||
return (BsonConvert) convert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory createChild() {
|
||||
return new BsonFactory(this, this.tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory createChild(boolean tiny) {
|
||||
return new BsonFactory(this, tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConvertType getConvertType() {
|
||||
return ConvertType.BSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReversible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldSort() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static byte typeEnum(final Type type) {
|
||||
return typeEnum(TypeToken.typeToClass(type));
|
||||
}
|
||||
|
||||
protected static byte typeEnum(final Class type) {
|
||||
Objects.requireNonNull(type);
|
||||
byte typeval = 127; //字段的类型值
|
||||
if (type == boolean.class || type == Boolean.class) {
|
||||
typeval = 11;
|
||||
} else if (type == byte.class || type == Byte.class) {
|
||||
typeval = 12;
|
||||
} else if (type == short.class || type == Short.class) {
|
||||
typeval = 13;
|
||||
} else if (type == char.class || type == Character.class) {
|
||||
typeval = 14;
|
||||
} else if (type == int.class || type == Integer.class) {
|
||||
typeval = 15;
|
||||
} else if (type == long.class || type == Long.class) {
|
||||
typeval = 16;
|
||||
} else if (type == float.class || type == Float.class) {
|
||||
typeval = 17;
|
||||
} else if (type == double.class || type == Double.class) {
|
||||
typeval = 18;
|
||||
} else if (type == String.class) {
|
||||
typeval = 19;
|
||||
} else if (type == boolean[].class || type == Boolean[].class) {
|
||||
typeval = 21;
|
||||
} else if (type == byte[].class || type == Byte[].class) {
|
||||
typeval = 22;
|
||||
} else if (type == short[].class || type == Short[].class) {
|
||||
typeval = 23;
|
||||
} else if (type == char[].class || type == Character[].class) {
|
||||
typeval = 24;
|
||||
} else if (type == int[].class || type == Integer[].class) {
|
||||
typeval = 25;
|
||||
} else if (type == long[].class || type == Long[].class) {
|
||||
typeval = 26;
|
||||
} else if (type == float[].class || type == Float[].class) {
|
||||
typeval = 27;
|
||||
} else if (type == double[].class || type == Double[].class) {
|
||||
typeval = 28;
|
||||
} else if (type == String[].class) {
|
||||
typeval = 29;
|
||||
} else if (type.isArray()) {
|
||||
typeval = 81;
|
||||
} else if (Collection.class.isAssignableFrom(type)) {
|
||||
typeval = 82;
|
||||
} else if (Stream.class.isAssignableFrom(type)) {
|
||||
typeval = 83;
|
||||
} else if (Map.class.isAssignableFrom(type)) {
|
||||
typeval = 84;
|
||||
}
|
||||
return typeval;
|
||||
}
|
||||
|
||||
protected static Decodeable typeEnum(final byte typeval) {
|
||||
switch (typeval) {
|
||||
case 11:
|
||||
return BoolSimpledCoder.instance;
|
||||
case 12:
|
||||
return ByteSimpledCoder.instance;
|
||||
case 13:
|
||||
return ShortSimpledCoder.instance;
|
||||
case 14:
|
||||
return CharSimpledCoder.instance;
|
||||
case 15:
|
||||
return IntSimpledCoder.instance;
|
||||
case 16:
|
||||
return LongSimpledCoder.instance;
|
||||
case 17:
|
||||
return FloatSimpledCoder.instance;
|
||||
case 18:
|
||||
return DoubleSimpledCoder.instance;
|
||||
case 19:
|
||||
return StringSimpledCoder.instance;
|
||||
case 21:
|
||||
return BoolArraySimpledCoder.instance;
|
||||
case 22:
|
||||
return ByteArraySimpledCoder.instance;
|
||||
case 23:
|
||||
return ShortArraySimpledCoder.instance;
|
||||
case 24:
|
||||
return CharArraySimpledCoder.instance;
|
||||
case 25:
|
||||
return IntArraySimpledCoder.instance;
|
||||
case 26:
|
||||
return LongArraySimpledCoder.instance;
|
||||
case 27:
|
||||
return FloatArraySimpledCoder.instance;
|
||||
case 28:
|
||||
return DoubleArraySimpledCoder.instance;
|
||||
case 29:
|
||||
return StringArraySimpledCoder.instance;
|
||||
case 81:
|
||||
return skipArrayDecoder;
|
||||
case 82:
|
||||
return skipCollectionDecoder;
|
||||
case 83:
|
||||
return skipStreamDecoder;
|
||||
case 84:
|
||||
return skipMapDecoder;
|
||||
case 127:
|
||||
return BsonFactory.objectDecoder;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.ext.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* BSON的ConvertFactory
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
||||
|
||||
private static final BsonFactory instance = new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true));
|
||||
|
||||
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
|
||||
|
||||
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
|
||||
|
||||
static final Decodeable skipArrayDecoder = new SkipArrayDecoder(instance, Object[].class);
|
||||
|
||||
static final Decodeable skipCollectionDecoder = new SkipCollectionDecoder(instance, new TypeToken<Collection<Object>>() {
|
||||
}.getType());
|
||||
|
||||
static final Decodeable skipStreamDecoder = new SkipStreamDecoder(instance, new TypeToken<Stream<Object>>() {
|
||||
}.getType());
|
||||
|
||||
static final Decodeable skipMapDecoder = new SkipMapDecoder(instance, Map.class);
|
||||
|
||||
static {
|
||||
instance.register(Serializable.class, objectDecoder);
|
||||
instance.register(Serializable.class, objectEncoder);
|
||||
|
||||
//instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class));
|
||||
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
||||
}
|
||||
|
||||
private BsonFactory(BsonFactory parent, boolean tiny) {
|
||||
super(parent, tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory tiny(boolean tiny) {
|
||||
this.tiny = tiny;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory skipAllIgnore(final boolean skipIgnore) {
|
||||
this.registerSkipAllIgnore(skipIgnore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static BsonFactory root() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static BsonFactory create() {
|
||||
return new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BsonConvert getConvert() {
|
||||
if (convert == null) convert = new BsonConvert(this, tiny);
|
||||
return (BsonConvert) convert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory createChild() {
|
||||
return new BsonFactory(this, this.tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory createChild(boolean tiny) {
|
||||
return new BsonFactory(this, tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConvertType getConvertType() {
|
||||
return ConvertType.BSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReversible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldSort() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static byte typeEnum(final Type type) {
|
||||
return typeEnum(TypeToken.typeToClass(type));
|
||||
}
|
||||
|
||||
protected static byte typeEnum(final Class type) {
|
||||
Objects.requireNonNull(type);
|
||||
byte typeval = 127; //字段的类型值
|
||||
if (type == boolean.class || type == Boolean.class) {
|
||||
typeval = 11;
|
||||
} else if (type == byte.class || type == Byte.class) {
|
||||
typeval = 12;
|
||||
} else if (type == short.class || type == Short.class) {
|
||||
typeval = 13;
|
||||
} else if (type == char.class || type == Character.class) {
|
||||
typeval = 14;
|
||||
} else if (type == int.class || type == Integer.class) {
|
||||
typeval = 15;
|
||||
} else if (type == long.class || type == Long.class) {
|
||||
typeval = 16;
|
||||
} else if (type == float.class || type == Float.class) {
|
||||
typeval = 17;
|
||||
} else if (type == double.class || type == Double.class) {
|
||||
typeval = 18;
|
||||
} else if (type == String.class) {
|
||||
typeval = 19;
|
||||
} else if (type == boolean[].class || type == Boolean[].class) {
|
||||
typeval = 21;
|
||||
} else if (type == byte[].class || type == Byte[].class) {
|
||||
typeval = 22;
|
||||
} else if (type == short[].class || type == Short[].class) {
|
||||
typeval = 23;
|
||||
} else if (type == char[].class || type == Character[].class) {
|
||||
typeval = 24;
|
||||
} else if (type == int[].class || type == Integer[].class) {
|
||||
typeval = 25;
|
||||
} else if (type == long[].class || type == Long[].class) {
|
||||
typeval = 26;
|
||||
} else if (type == float[].class || type == Float[].class) {
|
||||
typeval = 27;
|
||||
} else if (type == double[].class || type == Double[].class) {
|
||||
typeval = 28;
|
||||
} else if (type == String[].class) {
|
||||
typeval = 29;
|
||||
} else if (type.isArray()) {
|
||||
typeval = 81;
|
||||
} else if (Collection.class.isAssignableFrom(type)) {
|
||||
typeval = 82;
|
||||
} else if (Stream.class.isAssignableFrom(type)) {
|
||||
typeval = 83;
|
||||
} else if (Map.class.isAssignableFrom(type)) {
|
||||
typeval = 84;
|
||||
}
|
||||
return typeval;
|
||||
}
|
||||
|
||||
protected static Decodeable typeEnum(final byte typeval) {
|
||||
switch (typeval) {
|
||||
case 11:
|
||||
return BoolSimpledCoder.instance;
|
||||
case 12:
|
||||
return ByteSimpledCoder.instance;
|
||||
case 13:
|
||||
return ShortSimpledCoder.instance;
|
||||
case 14:
|
||||
return CharSimpledCoder.instance;
|
||||
case 15:
|
||||
return IntSimpledCoder.instance;
|
||||
case 16:
|
||||
return LongSimpledCoder.instance;
|
||||
case 17:
|
||||
return FloatSimpledCoder.instance;
|
||||
case 18:
|
||||
return DoubleSimpledCoder.instance;
|
||||
case 19:
|
||||
return StringSimpledCoder.instance;
|
||||
case 21:
|
||||
return BoolArraySimpledCoder.instance;
|
||||
case 22:
|
||||
return ByteArraySimpledCoder.instance;
|
||||
case 23:
|
||||
return ShortArraySimpledCoder.instance;
|
||||
case 24:
|
||||
return CharArraySimpledCoder.instance;
|
||||
case 25:
|
||||
return IntArraySimpledCoder.instance;
|
||||
case 26:
|
||||
return LongArraySimpledCoder.instance;
|
||||
case 27:
|
||||
return FloatArraySimpledCoder.instance;
|
||||
case 28:
|
||||
return DoubleArraySimpledCoder.instance;
|
||||
case 29:
|
||||
return StringArraySimpledCoder.instance;
|
||||
case 81:
|
||||
return skipArrayDecoder;
|
||||
case 82:
|
||||
return skipCollectionDecoder;
|
||||
case 83:
|
||||
return skipStreamDecoder;
|
||||
case 84:
|
||||
return skipMapDecoder;
|
||||
case 127:
|
||||
return BsonFactory.objectDecoder;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,355 +1,355 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.redkale.convert.*;
|
||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
||||
import org.redkale.convert.ext.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* BSON数据源
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonReader extends Reader {
|
||||
|
||||
public static final short SIGN_OBJECTB = (short) 0xBB;
|
||||
|
||||
public static final short SIGN_OBJECTE = (short) 0xEE;
|
||||
|
||||
public static final byte SIGN_HASNEXT = 1;
|
||||
|
||||
public static final byte SIGN_NONEXT = 0;
|
||||
|
||||
public static final byte VERBOSE_NO = 1;
|
||||
|
||||
public static final byte VERBOSE_YES = 2;
|
||||
|
||||
protected byte typeval; //字段的类型值 对应 BsonWriter.writeField
|
||||
|
||||
protected int position = -1;
|
||||
|
||||
private byte[] content;
|
||||
|
||||
public BsonReader() {
|
||||
}
|
||||
|
||||
public static ObjectPool<BsonReader> createPool(int max) {
|
||||
return ObjectPool.createSafePool(max, (Object... params) -> new BsonReader(), null, (t) -> t.recycle());
|
||||
}
|
||||
|
||||
public BsonReader(byte[] bytes) {
|
||||
setBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public BsonReader(byte[] bytes, int start, int len) {
|
||||
setBytes(bytes, start, len);
|
||||
}
|
||||
|
||||
public final void setBytes(byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
this.position = 0;
|
||||
} else {
|
||||
setBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
public final void setBytes(byte[] bytes, int start, int len) {
|
||||
if (bytes == null) {
|
||||
this.position = 0;
|
||||
} else {
|
||||
this.content = bytes;
|
||||
this.position = start - 1;
|
||||
//this.limit = start + len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean recycle() {
|
||||
this.position = -1;
|
||||
this.typeval = 0;
|
||||
//this.limit = -1;
|
||||
this.content = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
this.recycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过属性的值
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final void skipValue() {
|
||||
if (typeval == 0) return;
|
||||
final byte val = this.typeval;
|
||||
this.typeval = 0;
|
||||
switch (val) {
|
||||
case 11: readBoolean();
|
||||
break;
|
||||
case 12: readByte();
|
||||
break;
|
||||
case 13: readShort();
|
||||
break;
|
||||
case 14: readChar();
|
||||
break;
|
||||
case 15: readInt();
|
||||
break;
|
||||
case 16: readLong();
|
||||
break;
|
||||
case 17: readFloat();
|
||||
break;
|
||||
case 18: readDouble();
|
||||
break;
|
||||
case 19: readString();
|
||||
break;
|
||||
default:
|
||||
Decodeable decoder = BsonFactory.typeEnum(val);
|
||||
if (decoder != null) decoder.convertFrom(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readObjectB(final Class clazz) {
|
||||
this.fieldIndex = 0; //必须要重置为0
|
||||
final String newcls = readClassName();
|
||||
if (newcls != null && !newcls.isEmpty()) return newcls;
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return null;
|
||||
if (bt != SIGN_OBJECTB) {
|
||||
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
|
||||
+ " (position = " + position + ") but '" + currentByte() + "'");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readObjectE(final Class clazz) {
|
||||
if (readShort() != SIGN_OBJECTE) {
|
||||
throw new ConvertException("a bson object must end with " + (SIGN_OBJECTE)
|
||||
+ " (position = " + position + ") but '" + currentByte() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
protected byte currentByte() {
|
||||
return this.content[this.position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||
byte kt = readByte();
|
||||
byte vt = readByte();
|
||||
if (typevals != null) {
|
||||
typevals[0] = kt;
|
||||
typevals[1] = vt;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readMapE() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否为[
|
||||
*
|
||||
* @return 数组长度或SIGN_NULL
|
||||
*/
|
||||
@Override
|
||||
public int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) { //componentDecoder可能为null
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
|
||||
byte comval = readByte();
|
||||
if (typevals != null) typevals[0] = comval;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readArrayE() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否:
|
||||
*/
|
||||
@Override
|
||||
public final void readBlank() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int position() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readMemberContentLength(DeMember member, Decodeable decoder) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||
*
|
||||
* @param startPosition 起始位置
|
||||
* @param contentLength 内容大小, 不确定的传-1
|
||||
*
|
||||
* @return 是否存在
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext(int startPosition, int contentLength) {
|
||||
byte b = readByte();
|
||||
if (b == SIGN_HASNEXT) return true;
|
||||
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
||||
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DeMember readFieldName(final DeMember[] members) {
|
||||
final String exceptedfield = readSmallString();
|
||||
this.typeval = readByte();
|
||||
final int len = members.length;
|
||||
if (this.fieldIndex >= len) this.fieldIndex = 0;
|
||||
for (int k = this.fieldIndex; k < len; k++) {
|
||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
||||
this.fieldIndex = k;
|
||||
return members[k];
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < this.fieldIndex; k++) {
|
||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
||||
this.fieldIndex = k;
|
||||
return members[k];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
@Override
|
||||
public boolean readBoolean() {
|
||||
return content[++this.position] == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
return content[++this.position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] readByteArray() {
|
||||
int len = readArrayB(null, null, null);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = readMemberContentLength(null, null);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
byte[] data = new byte[8];
|
||||
int startPosition = position();
|
||||
while (hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
byte[] newdata = new byte[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = readByte();
|
||||
}
|
||||
readArrayE();
|
||||
byte[] newdata = new byte[size];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
return newdata;
|
||||
} else {
|
||||
byte[] values = new byte[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = readByte();
|
||||
}
|
||||
readArrayE();
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar() {
|
||||
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort() {
|
||||
return (short) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() {
|
||||
return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16)
|
||||
| ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() {
|
||||
return ((((long) content[++this.position] & 0xff) << 56)
|
||||
| (((long) content[++this.position] & 0xff) << 48)
|
||||
| (((long) content[++this.position] & 0xff) << 40)
|
||||
| (((long) content[++this.position] & 0xff) << 32)
|
||||
| (((long) content[++this.position] & 0xff) << 24)
|
||||
| (((long) content[++this.position] & 0xff) << 16)
|
||||
| (((long) content[++this.position] & 0xff) << 8)
|
||||
| (((long) content[++this.position] & 0xff)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final float readFloat() {
|
||||
return Float.intBitsToFloat(readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double readDouble() {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readClassName() {
|
||||
return readSmallString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readSmallString() {
|
||||
int len = 0xff & readByte();
|
||||
if (len == 0) return "";
|
||||
String value = new String(content, ++this.position, len);
|
||||
this.position += len - 1; //上一行已经++this.position,所以此处要-1
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString() {
|
||||
int len = readInt();
|
||||
if (len == SIGN_NULL) return null;
|
||||
if (len == 0) return "";
|
||||
String value = new String(content, ++this.position, len, StandardCharsets.UTF_8);
|
||||
this.position += len - 1;//上一行已经++this.position,所以此处要-1
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType readType() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.redkale.convert.*;
|
||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
||||
import org.redkale.convert.ext.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* BSON数据源
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonReader extends Reader {
|
||||
|
||||
public static final short SIGN_OBJECTB = (short) 0xBB;
|
||||
|
||||
public static final short SIGN_OBJECTE = (short) 0xEE;
|
||||
|
||||
public static final byte SIGN_HASNEXT = 1;
|
||||
|
||||
public static final byte SIGN_NONEXT = 0;
|
||||
|
||||
public static final byte VERBOSE_NO = 1;
|
||||
|
||||
public static final byte VERBOSE_YES = 2;
|
||||
|
||||
protected byte typeval; //字段的类型值 对应 BsonWriter.writeField
|
||||
|
||||
protected int position = -1;
|
||||
|
||||
private byte[] content;
|
||||
|
||||
public BsonReader() {
|
||||
}
|
||||
|
||||
public static ObjectPool<BsonReader> createPool(int max) {
|
||||
return ObjectPool.createSafePool(max, (Object... params) -> new BsonReader(), null, (t) -> t.recycle());
|
||||
}
|
||||
|
||||
public BsonReader(byte[] bytes) {
|
||||
setBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public BsonReader(byte[] bytes, int start, int len) {
|
||||
setBytes(bytes, start, len);
|
||||
}
|
||||
|
||||
public final void setBytes(byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
this.position = 0;
|
||||
} else {
|
||||
setBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
public final void setBytes(byte[] bytes, int start, int len) {
|
||||
if (bytes == null) {
|
||||
this.position = 0;
|
||||
} else {
|
||||
this.content = bytes;
|
||||
this.position = start - 1;
|
||||
//this.limit = start + len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean recycle() {
|
||||
this.position = -1;
|
||||
this.typeval = 0;
|
||||
//this.limit = -1;
|
||||
this.content = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
this.recycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过属性的值
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final void skipValue() {
|
||||
if (typeval == 0) return;
|
||||
final byte val = this.typeval;
|
||||
this.typeval = 0;
|
||||
switch (val) {
|
||||
case 11: readBoolean();
|
||||
break;
|
||||
case 12: readByte();
|
||||
break;
|
||||
case 13: readShort();
|
||||
break;
|
||||
case 14: readChar();
|
||||
break;
|
||||
case 15: readInt();
|
||||
break;
|
||||
case 16: readLong();
|
||||
break;
|
||||
case 17: readFloat();
|
||||
break;
|
||||
case 18: readDouble();
|
||||
break;
|
||||
case 19: readString();
|
||||
break;
|
||||
default:
|
||||
Decodeable decoder = BsonFactory.typeEnum(val);
|
||||
if (decoder != null) decoder.convertFrom(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readObjectB(final Class clazz) {
|
||||
this.fieldIndex = 0; //必须要重置为0
|
||||
final String newcls = readClassName();
|
||||
if (newcls != null && !newcls.isEmpty()) return newcls;
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return null;
|
||||
if (bt != SIGN_OBJECTB) {
|
||||
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
|
||||
+ " (position = " + position + ") but '" + currentByte() + "'");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readObjectE(final Class clazz) {
|
||||
if (readShort() != SIGN_OBJECTE) {
|
||||
throw new ConvertException("a bson object must end with " + (SIGN_OBJECTE)
|
||||
+ " (position = " + position + ") but '" + currentByte() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
protected byte currentByte() {
|
||||
return this.content[this.position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||
byte kt = readByte();
|
||||
byte vt = readByte();
|
||||
if (typevals != null) {
|
||||
typevals[0] = kt;
|
||||
typevals[1] = vt;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readMapE() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否为[
|
||||
*
|
||||
* @return 数组长度或SIGN_NULL
|
||||
*/
|
||||
@Override
|
||||
public int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) { //componentDecoder可能为null
|
||||
short bt = readShort();
|
||||
if (bt == Reader.SIGN_NULL) return bt;
|
||||
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
|
||||
byte comval = readByte();
|
||||
if (typevals != null) typevals[0] = comval;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readArrayE() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否:
|
||||
*/
|
||||
@Override
|
||||
public final void readBlank() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int position() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readMemberContentLength(DeMember member, Decodeable decoder) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||
*
|
||||
* @param startPosition 起始位置
|
||||
* @param contentLength 内容大小, 不确定的传-1
|
||||
*
|
||||
* @return 是否存在
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext(int startPosition, int contentLength) {
|
||||
byte b = readByte();
|
||||
if (b == SIGN_HASNEXT) return true;
|
||||
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
||||
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DeMember readFieldName(final DeMember[] members) {
|
||||
final String exceptedfield = readSmallString();
|
||||
this.typeval = readByte();
|
||||
final int len = members.length;
|
||||
if (this.fieldIndex >= len) this.fieldIndex = 0;
|
||||
for (int k = this.fieldIndex; k < len; k++) {
|
||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
||||
this.fieldIndex = k;
|
||||
return members[k];
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < this.fieldIndex; k++) {
|
||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
||||
this.fieldIndex = k;
|
||||
return members[k];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
@Override
|
||||
public boolean readBoolean() {
|
||||
return content[++this.position] == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
return content[++this.position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] readByteArray() {
|
||||
int len = readArrayB(null, null, null);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = readMemberContentLength(null, null);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
byte[] data = new byte[8];
|
||||
int startPosition = position();
|
||||
while (hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
byte[] newdata = new byte[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = readByte();
|
||||
}
|
||||
readArrayE();
|
||||
byte[] newdata = new byte[size];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
return newdata;
|
||||
} else {
|
||||
byte[] values = new byte[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = readByte();
|
||||
}
|
||||
readArrayE();
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar() {
|
||||
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort() {
|
||||
return (short) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() {
|
||||
return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16)
|
||||
| ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() {
|
||||
return ((((long) content[++this.position] & 0xff) << 56)
|
||||
| (((long) content[++this.position] & 0xff) << 48)
|
||||
| (((long) content[++this.position] & 0xff) << 40)
|
||||
| (((long) content[++this.position] & 0xff) << 32)
|
||||
| (((long) content[++this.position] & 0xff) << 24)
|
||||
| (((long) content[++this.position] & 0xff) << 16)
|
||||
| (((long) content[++this.position] & 0xff) << 8)
|
||||
| (((long) content[++this.position] & 0xff)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final float readFloat() {
|
||||
return Float.intBitsToFloat(readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double readDouble() {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readClassName() {
|
||||
return readSmallString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readSmallString() {
|
||||
int len = 0xff & readByte();
|
||||
if (len == 0) return "";
|
||||
String value = new String(content, ++this.position, len);
|
||||
this.position += len - 1; //上一行已经++this.position,所以此处要-1
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString() {
|
||||
int len = readInt();
|
||||
if (len == SIGN_NULL) return null;
|
||||
if (len == 0) return "";
|
||||
String value = new String(content, ++this.position, len, StandardCharsets.UTF_8);
|
||||
this.position += len - 1;//上一行已经++this.position,所以此处要-1
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType readType() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化/反解析的数据类型
|
||||
*/
|
||||
public abstract class BsonSimpledCoder<T> extends SimpledCoder<BsonReader, BsonWriter, T> {
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化/反解析的数据类型
|
||||
*/
|
||||
public abstract class BsonSimpledCoder<T> extends SimpledCoder<BsonReader, BsonWriter, T> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class BsonStreamReader extends BsonByteBufferReader {
|
||||
|
||||
private InputStream in;
|
||||
|
||||
private byte currByte;
|
||||
|
||||
protected BsonStreamReader(InputStream in) {
|
||||
super((ConvertMask) null);
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle(); // this.position 初始化值为-1
|
||||
this.in = null;
|
||||
this.currByte = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
try {
|
||||
byte b = (currByte = (byte) in.read());
|
||||
this.position++;
|
||||
return b;
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte currentByte() {
|
||||
return currByte;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] read(final int len) {
|
||||
byte[] bs = new byte[len];
|
||||
try {
|
||||
in.read(bs);
|
||||
this.position += len;
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
return bs;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class BsonStreamReader extends BsonByteBufferReader {
|
||||
|
||||
private InputStream in;
|
||||
|
||||
private byte currByte;
|
||||
|
||||
protected BsonStreamReader(InputStream in) {
|
||||
super((ConvertMask) null);
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle(); // this.position 初始化值为-1
|
||||
this.in = null;
|
||||
this.currByte = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
try {
|
||||
byte b = (currByte = (byte) in.read());
|
||||
this.position++;
|
||||
return b;
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte currentByte() {
|
||||
return currByte;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] read(final int len) {
|
||||
byte[] bs = new byte[len];
|
||||
try {
|
||||
in.read(bs);
|
||||
this.position += len;
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
return bs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class BsonStreamWriter extends BsonByteBufferWriter {
|
||||
|
||||
private OutputStream out;
|
||||
|
||||
protected BsonStreamWriter(boolean tiny, OutputStream out) {
|
||||
super(tiny, null);
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.out = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
try {
|
||||
out.write(chs, start, len);
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte ch) {
|
||||
try {
|
||||
out.write((byte) ch);
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class BsonStreamWriter extends BsonByteBufferWriter {
|
||||
|
||||
private OutputStream out;
|
||||
|
||||
protected BsonStreamWriter(boolean tiny, OutputStream out) {
|
||||
super(tiny, null);
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.out = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
try {
|
||||
out.write(chs, start, len);
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte ch) {
|
||||
try {
|
||||
out.write((byte) ch);
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,336 +1,336 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Consumer;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.ext.ByteSimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonWriter extends Writer implements ByteTuple {
|
||||
|
||||
private static final int defaultSize = Integer.getInteger("redkale.convert.bson.writer.buffer.defsize", Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
||||
|
||||
private byte[] content;
|
||||
|
||||
protected int count;
|
||||
|
||||
protected boolean tiny;
|
||||
|
||||
public static ObjectPool<BsonWriter> createPool(int max) {
|
||||
return ObjectPool.createSafePool(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int offset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接获取全部数据, 实际数据需要根据count长度来截取
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public byte[] directBytes() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本对象的内容引用复制给array
|
||||
*
|
||||
* @param array ByteArray
|
||||
*/
|
||||
public void directTo(ByteArray array) {
|
||||
array.directFrom(content, count);
|
||||
}
|
||||
|
||||
public void completed(ConvertBytesHandler handler, Consumer<BsonWriter> callback) {
|
||||
handler.completed(content, 0, count, callback, this);
|
||||
}
|
||||
|
||||
public ByteArray toByteArray() {
|
||||
return new ByteArray(this);
|
||||
}
|
||||
|
||||
public byte[] toArray() {
|
||||
if (count == content.length) return content;
|
||||
byte[] newdata = new byte[count];
|
||||
System.arraycopy(content, 0, newdata, 0, count);
|
||||
return newdata;
|
||||
}
|
||||
|
||||
public ByteBuffer[] toBuffers() {
|
||||
return new ByteBuffer[]{ByteBuffer.wrap(content, 0, count)};
|
||||
}
|
||||
|
||||
protected BsonWriter(byte[] bs) {
|
||||
this.content = bs == null ? new byte[0] : bs;
|
||||
}
|
||||
|
||||
public BsonWriter() {
|
||||
this(defaultSize);
|
||||
}
|
||||
|
||||
public BsonWriter(int size) {
|
||||
this.content = new byte[size > 128 ? size : 128];
|
||||
}
|
||||
|
||||
public BsonWriter(ByteArray array) {
|
||||
this.content = array.content();
|
||||
this.count = array.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean tiny() {
|
||||
return tiny;
|
||||
}
|
||||
|
||||
public BsonWriter tiny(boolean tiny) {
|
||||
this.tiny = tiny;
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* 扩充指定长度的缓冲区
|
||||
*
|
||||
* @param len 扩容长度
|
||||
*
|
||||
* @return 固定0
|
||||
*/
|
||||
protected int expand(int len) {
|
||||
int newcount = count + len;
|
||||
if (newcount <= content.length) return 0;
|
||||
byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)];
|
||||
System.arraycopy(content, 0, newdata, 0, count);
|
||||
this.content = newdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeTo(final byte ch) {
|
||||
expand(1);
|
||||
content[count++] = ch;
|
||||
}
|
||||
|
||||
public final void writeTo(final byte... chs) {
|
||||
writeTo(chs, 0, chs.length);
|
||||
}
|
||||
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
expand(len);
|
||||
System.arraycopy(chs, start, content, count, len);
|
||||
count += len;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.count = 0;
|
||||
this.specify = null;
|
||||
if (this.content != null && this.content.length > defaultSize) {
|
||||
this.content = new byte[defaultSize];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
public final int count() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeBoolean(boolean value) {
|
||||
writeTo(value ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeByte(byte value) {
|
||||
writeTo(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeByteArray(byte[] values) {
|
||||
if (values == null) {
|
||||
writeNull();
|
||||
return;
|
||||
}
|
||||
writeArrayB(values.length, null, null, values);
|
||||
boolean flag = false;
|
||||
for (byte v : values) {
|
||||
if (flag) writeArrayMark();
|
||||
writeByte(v);
|
||||
flag = true;
|
||||
}
|
||||
writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeChar(final char value) {
|
||||
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeShort(short value) {
|
||||
writeTo((byte) (value >> 8), (byte) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeInt(int value) {
|
||||
writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeLong(long value) {
|
||||
writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
|
||||
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeFloat(float value) {
|
||||
writeInt(Float.floatToIntBits(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeDouble(double value) {
|
||||
writeLong(Double.doubleToLongBits(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean needWriteClassName() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeClassName(String clazz) {
|
||||
writeSmallString(clazz == null ? "" : clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int writeObjectB(Object obj) {
|
||||
super.writeObjectB(obj);
|
||||
writeSmallString("");
|
||||
writeShort(BsonReader.SIGN_OBJECTB);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeObjectE(Object obj) {
|
||||
writeByte(BsonReader.SIGN_NONEXT);
|
||||
writeShort(BsonReader.SIGN_OBJECTE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeFieldName(EnMember member, String fieldName, Type fieldType, int fieldPos) {
|
||||
writeByte(BsonReader.SIGN_HASNEXT);
|
||||
writeSmallString(fieldName);
|
||||
writeByte(BsonFactory.typeEnum(fieldType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对于类的字段名、枚举值这些长度一般不超过255且不会出现双字节字符的字符串采用writeSmallString处理, readSmallString用于读取
|
||||
*
|
||||
* @param value String值
|
||||
*/
|
||||
@Override
|
||||
public final void writeSmallString(String value) {
|
||||
if (value.isEmpty()) {
|
||||
writeTo((byte) 0);
|
||||
return;
|
||||
}
|
||||
char[] chars = Utility.charArray(value);
|
||||
if (chars.length > 255) throw new ConvertException("'" + value + "' have very long length");
|
||||
byte[] bytes = new byte[chars.length + 1];
|
||||
bytes[0] = (byte) chars.length;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' have double-word");
|
||||
bytes[i + 1] = (byte) chars[i];
|
||||
}
|
||||
writeTo(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeString(String value) {
|
||||
if (value == null) {
|
||||
writeInt(Reader.SIGN_NULL);
|
||||
return;
|
||||
} else if (value.isEmpty()) {
|
||||
writeInt(0);
|
||||
return;
|
||||
}
|
||||
byte[] bytes = Utility.encodeUTF8(value);
|
||||
writeInt(bytes.length);
|
||||
writeTo(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeWrapper(StringWrapper value) {
|
||||
this.writeString(value == null ? null : value.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeNull() {
|
||||
writeShort(Reader.SIGN_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int writeArrayB(int size, Encodeable arrayEncoder, Encodeable<Writer, Object> componentEncoder, Object obj) {
|
||||
writeInt(size);
|
||||
if (componentEncoder != null && componentEncoder != ByteSimpledCoder.instance) {
|
||||
writeByte(BsonFactory.typeEnum(componentEncoder.getType()));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeArrayMark() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeArrayE() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
|
||||
writeInt(size);
|
||||
writeByte(BsonFactory.typeEnum(keyEncoder.getType()));
|
||||
writeByte(BsonFactory.typeEnum(valueEncoder.getType()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeMapMark() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeMapE() {
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Consumer;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.ext.ByteSimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class BsonWriter extends Writer implements ByteTuple {
|
||||
|
||||
private static final int defaultSize = Integer.getInteger("redkale.convert.bson.writer.buffer.defsize", Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
||||
|
||||
private byte[] content;
|
||||
|
||||
protected int count;
|
||||
|
||||
protected boolean tiny;
|
||||
|
||||
public static ObjectPool<BsonWriter> createPool(int max) {
|
||||
return ObjectPool.createSafePool(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int offset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接获取全部数据, 实际数据需要根据count长度来截取
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public byte[] directBytes() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本对象的内容引用复制给array
|
||||
*
|
||||
* @param array ByteArray
|
||||
*/
|
||||
public void directTo(ByteArray array) {
|
||||
array.directFrom(content, count);
|
||||
}
|
||||
|
||||
public void completed(ConvertBytesHandler handler, Consumer<BsonWriter> callback) {
|
||||
handler.completed(content, 0, count, callback, this);
|
||||
}
|
||||
|
||||
public ByteArray toByteArray() {
|
||||
return new ByteArray(this);
|
||||
}
|
||||
|
||||
public byte[] toArray() {
|
||||
if (count == content.length) return content;
|
||||
byte[] newdata = new byte[count];
|
||||
System.arraycopy(content, 0, newdata, 0, count);
|
||||
return newdata;
|
||||
}
|
||||
|
||||
public ByteBuffer[] toBuffers() {
|
||||
return new ByteBuffer[]{ByteBuffer.wrap(content, 0, count)};
|
||||
}
|
||||
|
||||
protected BsonWriter(byte[] bs) {
|
||||
this.content = bs == null ? new byte[0] : bs;
|
||||
}
|
||||
|
||||
public BsonWriter() {
|
||||
this(defaultSize);
|
||||
}
|
||||
|
||||
public BsonWriter(int size) {
|
||||
this.content = new byte[size > 128 ? size : 128];
|
||||
}
|
||||
|
||||
public BsonWriter(ByteArray array) {
|
||||
this.content = array.content();
|
||||
this.count = array.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean tiny() {
|
||||
return tiny;
|
||||
}
|
||||
|
||||
public BsonWriter tiny(boolean tiny) {
|
||||
this.tiny = tiny;
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* 扩充指定长度的缓冲区
|
||||
*
|
||||
* @param len 扩容长度
|
||||
*
|
||||
* @return 固定0
|
||||
*/
|
||||
protected int expand(int len) {
|
||||
int newcount = count + len;
|
||||
if (newcount <= content.length) return 0;
|
||||
byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)];
|
||||
System.arraycopy(content, 0, newdata, 0, count);
|
||||
this.content = newdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeTo(final byte ch) {
|
||||
expand(1);
|
||||
content[count++] = ch;
|
||||
}
|
||||
|
||||
public final void writeTo(final byte... chs) {
|
||||
writeTo(chs, 0, chs.length);
|
||||
}
|
||||
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
expand(len);
|
||||
System.arraycopy(chs, start, content, count, len);
|
||||
count += len;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.count = 0;
|
||||
this.specify = null;
|
||||
if (this.content != null && this.content.length > defaultSize) {
|
||||
this.content = new byte[defaultSize];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
public final int count() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeBoolean(boolean value) {
|
||||
writeTo(value ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeByte(byte value) {
|
||||
writeTo(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeByteArray(byte[] values) {
|
||||
if (values == null) {
|
||||
writeNull();
|
||||
return;
|
||||
}
|
||||
writeArrayB(values.length, null, null, values);
|
||||
boolean flag = false;
|
||||
for (byte v : values) {
|
||||
if (flag) writeArrayMark();
|
||||
writeByte(v);
|
||||
flag = true;
|
||||
}
|
||||
writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeChar(final char value) {
|
||||
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeShort(short value) {
|
||||
writeTo((byte) (value >> 8), (byte) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeInt(int value) {
|
||||
writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeLong(long value) {
|
||||
writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
|
||||
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeFloat(float value) {
|
||||
writeInt(Float.floatToIntBits(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeDouble(double value) {
|
||||
writeLong(Double.doubleToLongBits(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean needWriteClassName() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeClassName(String clazz) {
|
||||
writeSmallString(clazz == null ? "" : clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int writeObjectB(Object obj) {
|
||||
super.writeObjectB(obj);
|
||||
writeSmallString("");
|
||||
writeShort(BsonReader.SIGN_OBJECTB);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeObjectE(Object obj) {
|
||||
writeByte(BsonReader.SIGN_NONEXT);
|
||||
writeShort(BsonReader.SIGN_OBJECTE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeFieldName(EnMember member, String fieldName, Type fieldType, int fieldPos) {
|
||||
writeByte(BsonReader.SIGN_HASNEXT);
|
||||
writeSmallString(fieldName);
|
||||
writeByte(BsonFactory.typeEnum(fieldType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对于类的字段名、枚举值这些长度一般不超过255且不会出现双字节字符的字符串采用writeSmallString处理, readSmallString用于读取
|
||||
*
|
||||
* @param value String值
|
||||
*/
|
||||
@Override
|
||||
public final void writeSmallString(String value) {
|
||||
if (value.isEmpty()) {
|
||||
writeTo((byte) 0);
|
||||
return;
|
||||
}
|
||||
char[] chars = Utility.charArray(value);
|
||||
if (chars.length > 255) throw new ConvertException("'" + value + "' have very long length");
|
||||
byte[] bytes = new byte[chars.length + 1];
|
||||
bytes[0] = (byte) chars.length;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' have double-word");
|
||||
bytes[i + 1] = (byte) chars[i];
|
||||
}
|
||||
writeTo(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeString(String value) {
|
||||
if (value == null) {
|
||||
writeInt(Reader.SIGN_NULL);
|
||||
return;
|
||||
} else if (value.isEmpty()) {
|
||||
writeInt(0);
|
||||
return;
|
||||
}
|
||||
byte[] bytes = Utility.encodeUTF8(value);
|
||||
writeInt(bytes.length);
|
||||
writeTo(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeWrapper(StringWrapper value) {
|
||||
this.writeString(value == null ? null : value.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeNull() {
|
||||
writeShort(Reader.SIGN_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int writeArrayB(int size, Encodeable arrayEncoder, Encodeable<Writer, Object> componentEncoder, Object obj) {
|
||||
writeInt(size);
|
||||
if (componentEncoder != null && componentEncoder != ByteSimpledCoder.instance) {
|
||||
writeByte(BsonFactory.typeEnum(componentEncoder.getType()));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeArrayMark() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeArrayE() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
|
||||
writeInt(size);
|
||||
writeByte(BsonFactory.typeEnum(keyEncoder.getType()));
|
||||
writeByte(BsonFactory.typeEnum(valueEncoder.getType()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeMapMark() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeMapE() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* 数组的反序列化操作类 <br>
|
||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的数组元素类型
|
||||
*/
|
||||
public class SkipArrayDecoder<T> extends ArrayDecoder<T> {
|
||||
|
||||
public SkipArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* 数组的反序列化操作类 <br>
|
||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的数组元素类型
|
||||
*/
|
||||
public class SkipArrayDecoder<T> extends ArrayDecoder<T> {
|
||||
|
||||
public SkipArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* Collection的反序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
*/
|
||||
public class SkipCollectionDecoder<T> extends CollectionDecoder<T> {
|
||||
|
||||
public SkipCollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* Collection的反序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
*/
|
||||
public class SkipCollectionDecoder<T> extends CollectionDecoder<T> {
|
||||
|
||||
public SkipCollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* Map的反序列化操作类 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
*/
|
||||
public class SkipMapDecoder<K, V> extends MapDecoder<K, V> {
|
||||
|
||||
public SkipMapDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[1]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* Map的反序列化操作类 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
*/
|
||||
public class SkipMapDecoder<K, V> extends MapDecoder<K, V> {
|
||||
|
||||
public SkipMapDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[1]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* Stream的反序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
*/
|
||||
public class SkipStreamDecoder<T> extends StreamDecoder<T> {
|
||||
|
||||
public SkipStreamDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* Stream的反序列化操作类 <br>
|
||||
* 支持一定程度的泛型。 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
*/
|
||||
public class SkipStreamDecoder<T> extends StreamDecoder<T> {
|
||||
|
||||
public SkipStreamDecoder(final ConvertFactory factory, final Type type) {
|
||||
super(factory, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 提供BSON的序列化和反解析功能
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
/**
|
||||
* 提供BSON的序列化和反解析功能
|
||||
*/
|
||||
package org.redkale.convert.bson;
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* AtomicInteger 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class AtomicIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, AtomicInteger> {
|
||||
|
||||
public static final AtomicIntegerSimpledCoder instance = new AtomicIntegerSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, AtomicInteger value) {
|
||||
out.writeInt(value == null ? 0 : value.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtomicInteger convertFrom(R in) {
|
||||
return new AtomicInteger(in.readInt());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* AtomicInteger 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class AtomicIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, AtomicInteger> {
|
||||
|
||||
public static final AtomicIntegerSimpledCoder instance = new AtomicIntegerSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, AtomicInteger value) {
|
||||
out.writeInt(value == null ? 0 : value.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtomicInteger convertFrom(R in) {
|
||||
return new AtomicInteger(in.readInt());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* AtomicLong 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class AtomicLongSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, AtomicLong> {
|
||||
|
||||
public static final AtomicLongSimpledCoder instance = new AtomicLongSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, AtomicLong value) {
|
||||
out.writeLong(value == null ? 0 : value.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtomicLong convertFrom(R in) {
|
||||
return new AtomicLong(in.readLong());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* AtomicLong 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class AtomicLongSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, AtomicLong> {
|
||||
|
||||
public static final AtomicLongSimpledCoder instance = new AtomicLongSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, AtomicLong value) {
|
||||
out.writeLong(value == null ? 0 : value.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtomicLong convertFrom(R in) {
|
||||
return new AtomicLong(in.readLong());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
import org.redkale.convert.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* BigDecimal 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BigDecimalSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigDecimal> {
|
||||
|
||||
public static final BigDecimalSimpledCoder instance = new BigDecimalSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, BigDecimal value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
out.writeSmallString(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal convertFrom(R in) {
|
||||
String value = in.readSmallString();
|
||||
if (value == null) return null;
|
||||
return new BigDecimal(Utility.charArray(value));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
import org.redkale.convert.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* BigDecimal 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BigDecimalSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigDecimal> {
|
||||
|
||||
public static final BigDecimalSimpledCoder instance = new BigDecimalSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, BigDecimal value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
out.writeSmallString(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal convertFrom(R in) {
|
||||
String value = in.readSmallString();
|
||||
if (value == null) return null;
|
||||
return new BigDecimal(Utility.charArray(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
import org.redkale.convert.Reader;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* BigInteger 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BigIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigInteger> {
|
||||
|
||||
public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder();
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertTo(W out, BigInteger value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
ByteArraySimpledCoder.instance.convertTo(out, value.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BigInteger convertFrom(R in) {
|
||||
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
||||
return bytes == null ? null : new BigInteger(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* BigInteger 的JsonSimpledCoder实现
|
||||
*
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public static class BigIntegerJsonSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigInteger> {
|
||||
|
||||
public static final BigIntegerJsonSimpledCoder instance = new BigIntegerJsonSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(final Writer out, final BigInteger value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
} else {
|
||||
out.writeString(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger convertFrom(Reader in) {
|
||||
final String str = in.readString();
|
||||
if (str == null) return null;
|
||||
return new BigInteger(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
import org.redkale.convert.Reader;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* BigInteger 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BigIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigInteger> {
|
||||
|
||||
public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder();
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertTo(W out, BigInteger value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
ByteArraySimpledCoder.instance.convertTo(out, value.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BigInteger convertFrom(R in) {
|
||||
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
||||
return bytes == null ? null : new BigInteger(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* BigInteger 的JsonSimpledCoder实现
|
||||
*
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public static class BigIntegerJsonSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigInteger> {
|
||||
|
||||
public static final BigIntegerJsonSimpledCoder instance = new BigIntegerJsonSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(final Writer out, final BigInteger value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
} else {
|
||||
out.writeString(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger convertFrom(Reader in) {
|
||||
final String str = in.readString();
|
||||
if (str == null) return null;
|
||||
return new BigInteger(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* boolean[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BoolArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, boolean[]> {
|
||||
|
||||
public static final BoolArraySimpledCoder instance = new BoolArraySimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, boolean[] values) {
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (out.writeArrayB(values.length, this, BoolSimpledCoder.instance, values) < 0) {
|
||||
boolean flag = false;
|
||||
for (boolean v : values) {
|
||||
if (flag) out.writeArrayMark();
|
||||
out.writeBoolean(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] convertFrom(R in) {
|
||||
int len = in.readArrayB(null, null, BoolSimpledCoder.instance);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(null, BoolSimpledCoder.instance);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
boolean[] data = new boolean[8];
|
||||
int startPosition = in.position();
|
||||
while (in.hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
boolean[] newdata = new boolean[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = in.readBoolean();
|
||||
}
|
||||
in.readArrayE();
|
||||
boolean[] newdata = new boolean[size];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
return newdata;
|
||||
} else {
|
||||
boolean[] values = new boolean[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = in.readBoolean();
|
||||
}
|
||||
in.readArrayE();
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* boolean[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BoolArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, boolean[]> {
|
||||
|
||||
public static final BoolArraySimpledCoder instance = new BoolArraySimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, boolean[] values) {
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (out.writeArrayB(values.length, this, BoolSimpledCoder.instance, values) < 0) {
|
||||
boolean flag = false;
|
||||
for (boolean v : values) {
|
||||
if (flag) out.writeArrayMark();
|
||||
out.writeBoolean(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] convertFrom(R in) {
|
||||
int len = in.readArrayB(null, null, BoolSimpledCoder.instance);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(null, BoolSimpledCoder.instance);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
boolean[] data = new boolean[8];
|
||||
int startPosition = in.position();
|
||||
while (in.hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
boolean[] newdata = new boolean[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = in.readBoolean();
|
||||
}
|
||||
in.readArrayE();
|
||||
boolean[] newdata = new boolean[size];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
return newdata;
|
||||
} else {
|
||||
boolean[] values = new boolean[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = in.readBoolean();
|
||||
}
|
||||
in.readArrayE();
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* boolean 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BoolSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Boolean> {
|
||||
|
||||
public static final BoolSimpledCoder instance = new BoolSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Boolean value) {
|
||||
out.writeBoolean(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean convertFrom(R in) {
|
||||
return in.readBoolean();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* boolean 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class BoolSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Boolean> {
|
||||
|
||||
public static final BoolSimpledCoder instance = new BoolSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Boolean value) {
|
||||
out.writeBoolean(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean convertFrom(R in) {
|
||||
return in.readBoolean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* byte[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class ByteArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, byte[]> {
|
||||
|
||||
public static final ByteArraySimpledCoder instance = new ByteArraySimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, byte[] values) {
|
||||
out.writeByteArray(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertFrom(R in) {
|
||||
return in.readByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* byte[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class ByteArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, byte[]> {
|
||||
|
||||
public static final ByteArraySimpledCoder instance = new ByteArraySimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, byte[] values) {
|
||||
out.writeByteArray(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertFrom(R in) {
|
||||
return in.readByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* ByteBuffer 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class ByteBufferSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, ByteBuffer> {
|
||||
|
||||
public static final ByteBufferSimpledCoder instance = new ByteBufferSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, ByteBuffer value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (out.writeArrayB(value.remaining(), this, ByteSimpledCoder.instance, value) < 0) {
|
||||
boolean flag = false;
|
||||
for (byte v : value.array()) {
|
||||
if (flag) out.writeArrayMark();
|
||||
out.writeByte(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer convertFrom(R in) {
|
||||
int len = in.readArrayB(null, null, ByteSimpledCoder.instance);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(null, ByteSimpledCoder.instance);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
byte[] data = new byte[8];
|
||||
int startPosition = in.position();
|
||||
while (in.hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
byte[] newdata = new byte[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = in.readByte();
|
||||
}
|
||||
in.readArrayE();
|
||||
return ByteBuffer.wrap(data, 0, size);
|
||||
} else {
|
||||
byte[] values = new byte[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = in.readByte();
|
||||
}
|
||||
in.readArrayE();
|
||||
return ByteBuffer.wrap(values);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* ByteBuffer 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class ByteBufferSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, ByteBuffer> {
|
||||
|
||||
public static final ByteBufferSimpledCoder instance = new ByteBufferSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, ByteBuffer value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (out.writeArrayB(value.remaining(), this, ByteSimpledCoder.instance, value) < 0) {
|
||||
boolean flag = false;
|
||||
for (byte v : value.array()) {
|
||||
if (flag) out.writeArrayMark();
|
||||
out.writeByte(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer convertFrom(R in) {
|
||||
int len = in.readArrayB(null, null, ByteSimpledCoder.instance);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(null, ByteSimpledCoder.instance);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
byte[] data = new byte[8];
|
||||
int startPosition = in.position();
|
||||
while (in.hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
byte[] newdata = new byte[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = in.readByte();
|
||||
}
|
||||
in.readArrayE();
|
||||
return ByteBuffer.wrap(data, 0, size);
|
||||
} else {
|
||||
byte[] values = new byte[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = in.readByte();
|
||||
}
|
||||
in.readArrayE();
|
||||
return ByteBuffer.wrap(values);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* byte 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class ByteSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Byte> {
|
||||
|
||||
public static final ByteSimpledCoder instance = new ByteSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Byte value) {
|
||||
out.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte convertFrom(R in) {
|
||||
return in.readByte();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* byte 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class ByteSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Byte> {
|
||||
|
||||
public static final ByteSimpledCoder instance = new ByteSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Byte value) {
|
||||
out.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte convertFrom(R in) {
|
||||
return in.readByte();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* char[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class CharArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, char[]> {
|
||||
|
||||
public static final CharArraySimpledCoder instance = new CharArraySimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, char[] values) {
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (out.writeArrayB(values.length, this, CharSimpledCoder.instance, values) < 0) {
|
||||
boolean flag = false;
|
||||
for (char v : values) {
|
||||
if (flag) out.writeArrayMark();
|
||||
out.writeChar(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] convertFrom(R in) {
|
||||
int len = in.readArrayB(null, null, CharSimpledCoder.instance);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(null, CharSimpledCoder.instance);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
char[] data = new char[8];
|
||||
int startPosition = in.position();
|
||||
while (in.hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
char[] newdata = new char[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = in.readChar();
|
||||
}
|
||||
in.readArrayE();
|
||||
char[] newdata = new char[size];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
return newdata;
|
||||
} else {
|
||||
char[] values = new char[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = in.readChar();
|
||||
}
|
||||
in.readArrayE();
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* char[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class CharArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, char[]> {
|
||||
|
||||
public static final CharArraySimpledCoder instance = new CharArraySimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, char[] values) {
|
||||
if (values == null) {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (out.writeArrayB(values.length, this, CharSimpledCoder.instance, values) < 0) {
|
||||
boolean flag = false;
|
||||
for (char v : values) {
|
||||
if (flag) out.writeArrayMark();
|
||||
out.writeChar(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
out.writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] convertFrom(R in) {
|
||||
int len = in.readArrayB(null, null, CharSimpledCoder.instance);
|
||||
int contentLength = -1;
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||
contentLength = in.readMemberContentLength(null, CharSimpledCoder.instance);
|
||||
len = Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
int size = 0;
|
||||
char[] data = new char[8];
|
||||
int startPosition = in.position();
|
||||
while (in.hasNext(startPosition, contentLength)) {
|
||||
if (size >= data.length) {
|
||||
char[] newdata = new char[data.length + 4];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
data = newdata;
|
||||
}
|
||||
data[size++] = in.readChar();
|
||||
}
|
||||
in.readArrayE();
|
||||
char[] newdata = new char[size];
|
||||
System.arraycopy(data, 0, newdata, 0, size);
|
||||
return newdata;
|
||||
} else {
|
||||
char[] values = new char[len];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = in.readChar();
|
||||
}
|
||||
in.readArrayE();
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* CharSequence 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class CharSequenceSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, CharSequence> {
|
||||
|
||||
public static final CharSequenceSimpledCoder instance = new CharSequenceSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, CharSequence value) {
|
||||
out.writeString(value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence convertFrom(R in) {
|
||||
return in.readString();
|
||||
}
|
||||
|
||||
public static class StringBuilderSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, StringBuilder> {
|
||||
|
||||
public static final StringBuilderSimpledCoder instance = new StringBuilderSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, StringBuilder value) {
|
||||
out.writeString(value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder convertFrom(R in) {
|
||||
String rs = in.readString();
|
||||
return rs == null ? null : new StringBuilder(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* CharSequence 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class CharSequenceSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, CharSequence> {
|
||||
|
||||
public static final CharSequenceSimpledCoder instance = new CharSequenceSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, CharSequence value) {
|
||||
out.writeString(value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence convertFrom(R in) {
|
||||
return in.readString();
|
||||
}
|
||||
|
||||
public static class StringBuilderSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, StringBuilder> {
|
||||
|
||||
public static final StringBuilderSimpledCoder instance = new StringBuilderSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, StringBuilder value) {
|
||||
out.writeString(value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder convertFrom(R in) {
|
||||
String rs = in.readString();
|
||||
return rs == null ? null : new StringBuilder(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* char 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class CharSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Character> {
|
||||
|
||||
public static final CharSimpledCoder instance = new CharSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Character value) {
|
||||
out.writeChar(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character convertFrom(R in) {
|
||||
return in.readChar();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import org.redkale.convert.Reader;
|
||||
import org.redkale.convert.SimpledCoder;
|
||||
import org.redkale.convert.Writer;
|
||||
|
||||
/**
|
||||
* char 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class CharSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Character> {
|
||||
|
||||
public static final CharSimpledCoder instance = new CharSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Character value) {
|
||||
out.writeChar(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character convertFrom(R in) {
|
||||
return in.readChar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* java.nio.channels.CompletionHandler 的SimpledCoder实现, 只输出null
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class CompletionHandlerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, CompletionHandler> {
|
||||
|
||||
public static final CompletionHandlerSimpledCoder instance = new CompletionHandlerSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, CompletionHandler value) {
|
||||
out.writeObjectNull(CompletionHandler.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionHandler convertFrom(R in) {
|
||||
in.readObjectB(CompletionHandler.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.ext;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
* java.nio.channels.CompletionHandler 的SimpledCoder实现, 只输出null
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public final class CompletionHandlerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, CompletionHandler> {
|
||||
|
||||
public static final CompletionHandlerSimpledCoder instance = new CompletionHandlerSimpledCoder();
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, CompletionHandler value) {
|
||||
out.writeObjectNull(CompletionHandler.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionHandler convertFrom(R in) {
|
||||
in.readObjectB(CompletionHandler.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user