This commit is contained in:
redkale
2024-05-27 14:05:27 +08:00
parent a77180a0ba
commit bb14060517
642 changed files with 137396 additions and 137396 deletions

View File

@@ -30,10 +30,10 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface Priority {
/**
* 优先级值
*
* @return int
*/
int value();
/**
* 优先级值
*
* @return int
*/
int value();
}

View File

@@ -17,67 +17,67 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
// /**
// * AuthenticationType
// */
// @Deprecated
// public enum AuthenticationType {
// /**
// * @deprecated
// */
// CONTAINER,
// /**
// * @deprecated
// */
// APPLICATION
// }
//
/**
* 资源名称
*
* @return String
*/
public String name() default "";
// /**
// * 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 "";
/**
* 依赖注入的类型
*
* @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 "";
}

View File

@@ -35,24 +35,24 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Cacheable {
/**
* (Optional) Whether or not the entity should be cached.
*
* @return boolean
*/
boolean value() default true;
/**
* (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;
/**
* (Optional) 定时自动更新缓存的周期秒数为0表示不做定时更新 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
*
* @return int
*/
int interval() default 0;
/**
* DataSource是否直接返回对象的真实引用 而不是copy一份
*
* @return boolean
*/
boolean direct() default false;
/**
* DataSource是否直接返回对象的真实引用 而不是copy一份
*
* @return boolean
*/
boolean direct() default false;
}

View File

@@ -56,92 +56,92 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Column {
/**
* (Optional) The name of the column. Defaults to the property or field name.
*
* @return String
*/
String name() default "";
/**
* (Optional) The name of the column. Defaults to the property or field name.
*
* @return String
*/
String name() default "";
/**
* (Optional) The comment of the column.
*
* @return String
*/
String comment() default "";
/**
* (Optional) The comment of the column.
*
* @return String
*/
String comment() default "";
/**
* (Optional) Whether the column is a unique key. This is a shortcut for the <code>UniqueConstraint</code>
* annotation at the table level and is useful for when the unique key constraint corresponds to only a single
* column. This constraint applies in addition to any constraint entailed by primary key mapping and to constraints
* specified at the table level.
*
* @return boolean
*/
boolean unique() default false;
/**
* (Optional) Whether the column is a unique key. This is a shortcut for the <code>UniqueConstraint</code>
* annotation at the table level and is useful for when the unique key constraint corresponds to only a single
* column. This constraint applies in addition to any constraint entailed by primary key mapping and to constraints
* specified at the table level.
*
* @return boolean
*/
boolean unique() default false;
/**
* (Optional) Whether the database column is required.
*
* @return boolean
*/
boolean nullable() default true;
/**
* (Optional) Whether the database column is required.
*
* @return boolean
*/
boolean nullable() default true;
/**
* for OpenAPI Specification 3
*
* @return String
*/
String example() default "";
/**
* for OpenAPI Specification 3
*
* @return String
*/
String example() default "";
/**
* (Optional) Whether the column is included in SQL INSERT statements generated by the persistence provider.
*
* @return boolean
*/
boolean insertable() default true;
/**
* (Optional) Whether the column is included in SQL INSERT statements generated by the persistence provider.
*
* @return boolean
*/
boolean insertable() default true;
/**
* (Optional) Whether the column is included in SQL UPDATE statements generated by the persistence provider.
*
* @return boolean
*/
boolean updatable() default true;
/**
* (Optional) Whether the column is included in SQL UPDATE statements generated by the persistence provider.
*
* @return boolean
*/
boolean updatable() default true;
/**
* (Optional) The name of the table that contains the column. If absent the column is assumed to be in the primary
* table.
*
* @return String
*/
@Deprecated
String table() default "";
/**
* (Optional) The name of the table that contains the column. If absent the column is assumed to be in the primary
* table.
*
* @return String
*/
@Deprecated
String table() default "";
/**
* (Optional) The column length. (Applies only if a string-valued column is used.) if type==String and length ==
* 65535 then sqltype is TEXT <br>
* if type==String and length &#60;= 16777215 then sqltype is MEDIUMTEXT <br>
* if type==String and length &#62; 16777215 then sqltype is LONGTEXT <br>
* if type==byte[] and length &#60;= 65535 then sqltype is BLOB <br>
* if type==byte[] and length &#60;= 16777215 then sqltype is MEDIUMBLOB <br>
* if type==byte[] and length &#62; 16777215 then sqltype is LONGBLOB <br>
*
* @return int
*/
int length() default 255;
/**
* (Optional) The column length. (Applies only if a string-valued column is used.) if type==String and length ==
* 65535 then sqltype is TEXT <br>
* if type==String and length &#60;= 16777215 then sqltype is MEDIUMTEXT <br>
* if type==String and length &#62; 16777215 then sqltype is LONGTEXT <br>
* if type==byte[] and length &#60;= 65535 then sqltype is BLOB <br>
* if type==byte[] and length &#60;= 16777215 then sqltype is MEDIUMBLOB <br>
* if type==byte[] and length &#62; 16777215 then sqltype is LONGBLOB <br>
*
* @return int
*/
int length() default 255;
/**
* (Optional) The precision for a decimal (exact numeric) column. (Applies only if a decimal column is used.) Value
* must be set by developer if used when generating the DDL for the column.
*
* @return int
*/
int precision() default 0;
/**
* (Optional) The precision for a decimal (exact numeric) column. (Applies only if a decimal column is used.) Value
* must be set by developer if used when generating the DDL for the column.
*
* @return int
*/
int precision() default 0;
/**
* (Optional) The scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.)
*
* @return int
*/
int scale() default 0;
/**
* (Optional) The scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.)
*
* @return int
*/
int scale() default 0;
}

View File

@@ -32,18 +32,18 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Entity {
/**
* (Optional) The entity name. Defaults to the unqualified name of the entity class. This name is used to refer to
* the entity in queries. The name must not be a reserved literal in the Java Persistence query language.
*
* @return String
*/
String name() default "";
/**
* (Optional) The entity name. Defaults to the unqualified name of the entity class. This name is used to refer to
* the entity in queries. The name must not be a reserved literal in the Java Persistence query language.
*
* @return String
*/
String name() default "";
/**
* (Optional) The comment of the entity.
*
* @return String
*/
String comment() default "";
/**
* (Optional) The comment of the entity.
*
* @return String
*/
String comment() default "";
}

View File

@@ -41,24 +41,24 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Index {
/**
* (Optional) The name of the index; defaults to a provider-generated name.
*
* @return String
*/
String name() default "";
/**
* (Optional) The name of the index; defaults to a provider-generated name.
*
* @return String
*/
String name() default "";
/**
* (Required) The names of the columns to be included in the index, in order.
*
* @return String
*/
String columnList();
/**
* (Required) The names of the columns to be included in the index, in order.
*
* @return String
*/
String columnList();
/**
* (Optional) Whether the index is unique.
*
* @return boolean
*/
boolean unique() default false;
/**
* (Optional) Whether the index is unique.
*
* @return boolean
*/
boolean unique() default false;
}

View File

@@ -41,48 +41,48 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Table {
/**
* (Optional) The name of the table.
*
* <p>Defaults to the entity name.
*
* @return String
*/
String name() default "";
/**
* (Optional) The name of the table.
*
* <p>Defaults to the entity name.
*
* @return String
*/
String name() default "";
/**
* (Optional) The catalog of the table.
*
* <p>Defaults to the default catalog.
*
* @return String
*/
String catalog() default "";
/**
* (Optional) The catalog of the table.
*
* <p>Defaults to the default catalog.
*
* @return String
*/
String catalog() default "";
/**
* (Optional) Unique constraints that are to be placed on the table. These are only used if table generation is in
* effect. These constraints apply in addition to any constraints specified by the <code>Column</code> and <code>
* JoinColumn</code> annotations and constraints entailed by primary key mappings.
*
* <p>Defaults to no additional constraints.
*
* @return UniqueConstraint[]
*/
UniqueConstraint[] uniqueConstraints() default {};
/**
* (Optional) Unique constraints that are to be placed on the table. These are only used if table generation is in
* effect. These constraints apply in addition to any constraints specified by the <code>Column</code> and <code>
* JoinColumn</code> annotations and constraints entailed by primary key mappings.
*
* <p>Defaults to no additional constraints.
*
* @return UniqueConstraint[]
*/
UniqueConstraint[] uniqueConstraints() default {};
/**
* (Optional) Indexes for the table. These are only used if table generation is in effect. Note that it is not
* necessary to specify an index for a primary key, as the primary key index will be created automatically.
*
* @return indexes
* @since Java Persistence 2.1
*/
Index[] indexes() default {};
/**
* (Optional) Indexes for the table. These are only used if table generation is in effect. Note that it is not
* necessary to specify an index for a primary key, as the primary key index will be created automatically.
*
* @return indexes
* @since Java Persistence 2.1
*/
Index[] indexes() default {};
/**
* comment
*
* @return String
*/
String comment() default "";
/**
* comment
*
* @return String
*/
String comment() default "";
}

View File

@@ -40,18 +40,18 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface UniqueConstraint {
/**
* (Optional) Constraint name. A provider-chosen name will be chosen if a name is not specified.
*
* @return String
* @since Java Persistence 2.0
*/
String name() default "";
/**
* (Optional) Constraint name. A provider-chosen name will be chosen if a name is not specified.
*
* @return String
* @since Java Persistence 2.0
*/
String name() default "";
/**
* (Required) An array of the column names that make up the constraint.
*
* @return String[]
*/
String[] columnNames();
/**
* (Required) An array of the column names that make up the constraint.
*
* @return String[]
*/
String[] columnNames();
}

View File

@@ -4,51 +4,51 @@
* @author zhangjx
*/
module org.redkale {
requires java.base;
requires java.logging;
requires java.net.http;
requires java.sql;
requires jdk.unsupported; // sun.misc.Unsafe
requires java.base;
requires java.logging;
requires java.net.http;
requires java.sql;
requires jdk.unsupported; // sun.misc.Unsafe
exports org.redkale.annotation;
exports org.redkale.boot;
exports org.redkale.boot.watch;
exports org.redkale.cache;
exports org.redkale.cache.spi;
exports org.redkale.cluster;
exports org.redkale.cluster.spi;
exports org.redkale.convert;
exports org.redkale.convert.bson;
exports org.redkale.convert.ext;
exports org.redkale.convert.json;
exports org.redkale.convert.proto;
exports org.redkale.convert.spi;
exports org.redkale.inject;
exports org.redkale.lock;
exports org.redkale.lock.spi;
exports org.redkale.mq;
exports org.redkale.mq.spi;
exports org.redkale.net;
exports org.redkale.net.client;
exports org.redkale.net.http;
exports org.redkale.net.sncp;
exports org.redkale.persistence;
exports org.redkale.props.spi;
exports org.redkale.schedule;
exports org.redkale.schedule.spi;
exports org.redkale.service;
exports org.redkale.source;
exports org.redkale.source.spi;
exports org.redkale.util;
exports org.redkale.watch;
exports org.redkale.annotation;
exports org.redkale.boot;
exports org.redkale.boot.watch;
exports org.redkale.cache;
exports org.redkale.cache.spi;
exports org.redkale.cluster;
exports org.redkale.cluster.spi;
exports org.redkale.convert;
exports org.redkale.convert.bson;
exports org.redkale.convert.ext;
exports org.redkale.convert.json;
exports org.redkale.convert.proto;
exports org.redkale.convert.spi;
exports org.redkale.inject;
exports org.redkale.lock;
exports org.redkale.lock.spi;
exports org.redkale.mq;
exports org.redkale.mq.spi;
exports org.redkale.net;
exports org.redkale.net.client;
exports org.redkale.net.http;
exports org.redkale.net.sncp;
exports org.redkale.persistence;
exports org.redkale.props.spi;
exports org.redkale.schedule;
exports org.redkale.schedule.spi;
exports org.redkale.service;
exports org.redkale.source;
exports org.redkale.source.spi;
exports org.redkale.util;
exports org.redkale.watch;
uses org.redkale.props.spi.PropertiesAgentProvider;
uses org.redkale.cache.spi.CacheManagerProvider;
uses org.redkale.cluster.spi.ClusterAgentProvider;
uses org.redkale.convert.spi.ConvertProvider;
uses org.redkale.mq.spi.MessageAgentProvider;
uses org.redkale.schedule.spi.ScheduleManagerProvider;
uses org.redkale.source.spi.CacheSourceProvider;
uses org.redkale.source.spi.DataSourceProvider;
uses org.redkale.source.spi.DataNativeSqlParserProvider;
uses org.redkale.props.spi.PropertiesAgentProvider;
uses org.redkale.cache.spi.CacheManagerProvider;
uses org.redkale.cluster.spi.ClusterAgentProvider;
uses org.redkale.convert.spi.ConvertProvider;
uses org.redkale.mq.spi.MessageAgentProvider;
uses org.redkale.schedule.spi.ScheduleManagerProvider;
uses org.redkale.source.spi.CacheSourceProvider;
uses org.redkale.source.spi.DataSourceProvider;
uses org.redkale.source.spi.DataNativeSqlParserProvider;
}

View File

@@ -22,5 +22,5 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface AutoLoad {
boolean value() default true;
boolean value() default true;
}

View File

@@ -21,5 +21,5 @@ import java.lang.annotation.*;
@Retention(SOURCE)
public @interface ClassDepends {
Class[] value() default {};
Class[] value() default {};
}

View File

@@ -23,25 +23,25 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Command {
/**
* 命令号,没有指定值则接收所有的命令
*
* @return String
*/
String value() default "";
/**
* 命令号,没有指定值则接收所有的命令
*
* @return String
*/
String value() default "";
/**
* 参数帮助说明在value不为空命令redkale --help时显示
*
* @return String
* @since 2.7.0
*/
String description() default "";
/**
* 参数帮助说明在value不为空命令redkale --help时显示
*
* @return String
* @since 2.7.0
*/
String description() default "";
/**
* 描述
*
* @return String
*/
String comment() default "";
/**
* 描述
*
* @return String
*/
String comment() default "";
}

View File

@@ -23,7 +23,7 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface Comment {
String name() default "";
String name() default "";
String value();
String value();
}

View File

@@ -23,5 +23,5 @@ import java.lang.annotation.*;
@ClassDepends
public @interface ConstructorParameters {
String[] value();
String[] value();
}

View File

@@ -37,15 +37,15 @@ import java.lang.annotation.*;
@Repeatable(LogExcludeLevel.LogExcludeLevels.class)
public @interface LogExcludeLevel {
String[] levels();
String[] levels();
String[] keys();
String[] keys();
@Documented
@Target({TYPE})
@Retention(RUNTIME)
@interface LogExcludeLevels {
@Documented
@Target({TYPE})
@Retention(RUNTIME)
@interface LogExcludeLevels {
LogExcludeLevel[] value();
}
LogExcludeLevel[] value();
}
}

View File

@@ -22,5 +22,5 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface LogLevel {
String value();
String value();
}

View File

@@ -21,5 +21,5 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface NonBlocking { // 不可使用@Inherited防止被继承, 见HttpServlet.preExecute/authenticate/execute
boolean value() default true;
boolean value() default true;
}

View File

@@ -23,7 +23,7 @@ import java.lang.annotation.Target;
@Retention(RUNTIME)
public @interface Param {
String value();
String value();
String comment() default "";
String comment() default "";
}

View File

@@ -30,16 +30,16 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface Priority {
/** 最高优先级, 其他值必须比此值小 */
public static final int HIGHTEST = Integer.MAX_VALUE;
/** 最高优先级, 其他值必须比此值小 */
public static final int HIGHTEST = Integer.MAX_VALUE;
/** 最低优先级, 其他值必须比此值大 */
public static final int LOWEST = Integer.MIN_VALUE;
/** 最低优先级, 其他值必须比此值大 */
public static final int LOWEST = Integer.MIN_VALUE;
/**
* 优先级值
*
* @return int
*/
int value();
/**
* 优先级值
*
* @return int
*/
int value();
}

View File

@@ -19,42 +19,42 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
public static final String PARENT_NAME = "@";
public static final String PARENT_NAME = "@";
public static final String SELF_NAME = "#name";
public static final String SELF_NAME = "#name";
public static final String SELF_TYPE = "#type";
public static final String SELF_TYPE = "#type";
/**
* 是否必须存在
*
* @return boolean
* @since 2.8.0
*/
public boolean required() default true;
/**
* 是否必须存在
*
* @return boolean
* @since 2.8.0
*/
public boolean required() default true;
/**
* 资源名称 <br>
*
* <blockquote>
*
* <pre>
* name规则:
* 1: "@"有特殊含义, 表示资源本身,"@"不能单独使用
* 2: "#name"、"#type"有特殊含义
* 3: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* </pre>
*
* </blockquote>
*
* @return String
*/
public String name() default "";
/**
* 资源名称 <br>
*
* <blockquote>
*
* <pre>
* name规则:
* 1: "@"有特殊含义, 表示资源本身,"@"不能单独使用
* 2: "#name"、"#type"有特殊含义
* 3: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* </pre>
*
* </blockquote>
*
* @return String
*/
public String name() default "";
/**
* 依赖注入的类型
*
* @return Class
*/
public Class<?> type() default Object.class;
/**
* 依赖注入的类型
*
* @return Class
*/
public Class<?> type() default Object.class;
}

View File

@@ -55,12 +55,12 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface ResourceChanged {
/**
* 新旧值是否不同时才回调方法 <br>
* true: 新值与旧值不同时才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
*
* @since 2.7.0
* @return boolean
*/
boolean different() default true;
/**
* 新旧值是否不同时才回调方法 <br>
* true: 新值与旧值不同时才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
*
* @since 2.7.0
* @return boolean
*/
boolean different() default true;
}

View File

@@ -24,5 +24,5 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface ResourceType {
Class value();
Class value();
}

View File

@@ -68,103 +68,103 @@ package org.redkale.asm;
*/
public abstract class AnnotationVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
/**
* The ASM API version implemented by this visitor. The value of this field must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
/** The annotation visitor to which this visitor must delegate method calls. May be null. */
protected AnnotationVisitor av;
/** The annotation visitor to which this visitor must delegate method calls. May be null. */
protected AnnotationVisitor av;
/**
* Constructs a new {@link AnnotationVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link AnnotationVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link AnnotationVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param av the annotation visitor to which this visitor must delegate method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
this.api = api;
this.av = av;
}
/**
* Constructs a new {@link AnnotationVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param av the annotation visitor to which this visitor must delegate method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
this.api = api;
this.av = av;
}
/**
* Visits a primitive value of the annotation.
*
* @param name the value name.
* @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link Character},
* {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double}, {@link String} or {@link Type}
* of OBJECT or ARRAY sort. This value can also be an array of byte, boolean, short, char, int, long, float or
* double values (this is equivalent to using {@link #visitArray visitArray} and visiting each array element in
* turn, but is more convenient).
*/
public void visit(String name, Object value) {
if (av != null) {
av.visit(name, value);
}
}
/**
* Visits a primitive value of the annotation.
*
* @param name the value name.
* @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link Character},
* {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double}, {@link String} or {@link Type}
* of OBJECT or ARRAY sort. This value can also be an array of byte, boolean, short, char, int, long, float or
* double values (this is equivalent to using {@link #visitArray visitArray} and visiting each array element in
* turn, but is more convenient).
*/
public void visit(String name, Object value) {
if (av != null) {
av.visit(name, value);
}
}
/**
* Visits an enumeration value of the annotation.
*
* @param name the value name.
* @param desc the class descriptor of the enumeration class.
* @param value the actual enumeration value.
*/
public void visitEnum(String name, String desc, String value) {
if (av != null) {
av.visitEnum(name, desc, value);
}
}
/**
* Visits an enumeration value of the annotation.
*
* @param name the value name.
* @param desc the class descriptor of the enumeration class.
* @param value the actual enumeration value.
*/
public void visitEnum(String name, String desc, String value) {
if (av != null) {
av.visitEnum(name, desc, value);
}
}
/**
* Visits a nested annotation value of the annotation.
*
* @param name the value name.
* @param desc the class descriptor of the nested annotation class.
* @return a visitor to visit the actual nested annotation value, or &#60;tt&#62;null&#60;/tt&#62; if this visitor
* is not interested in visiting this nested annotation. <i>The nested annotation value must be fully visited
* before calling other methods on this annotation visitor</i>.
*/
public AnnotationVisitor visitAnnotation(String name, String desc) {
if (av != null) {
return av.visitAnnotation(name, desc);
}
return null;
}
/**
* Visits a nested annotation value of the annotation.
*
* @param name the value name.
* @param desc the class descriptor of the nested annotation class.
* @return a visitor to visit the actual nested annotation value, or &#60;tt&#62;null&#60;/tt&#62; if this visitor
* is not interested in visiting this nested annotation. <i>The nested annotation value must be fully visited
* before calling other methods on this annotation visitor</i>.
*/
public AnnotationVisitor visitAnnotation(String name, String desc) {
if (av != null) {
return av.visitAnnotation(name, desc);
}
return null;
}
/**
* Visits an array value of the annotation. Note that arrays of primitive types (such as byte, boolean, short, char,
* int, long, float or double) can be passed as value to {@link #visit visit}. This is what {@link ClassReader}
* does.
*
* @param name the value name.
* @return a visitor to visit the actual array value elements, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is
* not interested in visiting these values. The 'name' parameters passed to the methods of this visitor are
* ignored. <i>All the array values must be visited before calling other methods on this annotation visitor</i>.
*/
public AnnotationVisitor visitArray(String name) {
if (av != null) {
return av.visitArray(name);
}
return null;
}
/**
* Visits an array value of the annotation. Note that arrays of primitive types (such as byte, boolean, short, char,
* int, long, float or double) can be passed as value to {@link #visit visit}. This is what {@link ClassReader}
* does.
*
* @param name the value name.
* @return a visitor to visit the actual array value elements, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is
* not interested in visiting these values. The 'name' parameters passed to the methods of this visitor are
* ignored. <i>All the array values must be visited before calling other methods on this annotation visitor</i>.
*/
public AnnotationVisitor visitArray(String name) {
if (av != null) {
return av.visitArray(name);
}
return null;
}
/** Visits the end of the annotation. */
public void visitEnd() {
if (av != null) {
av.visitEnd();
}
}
/** Visits the end of the annotation. */
public void visitEnd() {
if (av != null) {
av.visitEnd();
}
}
}

View File

@@ -66,301 +66,301 @@ package org.redkale.asm;
*/
final class AnnotationWriter extends AnnotationVisitor {
/** The class writer to which this annotation must be added. */
private final ClassWriter cw;
/** The class writer to which this annotation must be added. */
private final ClassWriter cw;
/** The number of values in this annotation. */
private int size;
/** The number of values in this annotation. */
private int size;
/**
* &#60;tt&#62;true&#60;tt&#62; if values are named, &#60;tt&#62;false&#60;/tt&#62; otherwise. Annotation writers
* used for annotation default and annotation arrays use unnamed values.
*/
private final boolean named;
/**
* &#60;tt&#62;true&#60;tt&#62; if values are named, &#60;tt&#62;false&#60;/tt&#62; otherwise. Annotation writers
* used for annotation default and annotation arrays use unnamed values.
*/
private final boolean named;
/**
* The annotation values in bytecode form. This byte vector only contains the values themselves, i.e. the number of
* values must be stored as a unsigned short just before these bytes.
*/
private final ByteVector bv;
/**
* The annotation values in bytecode form. This byte vector only contains the values themselves, i.e. the number of
* values must be stored as a unsigned short just before these bytes.
*/
private final ByteVector bv;
/** The byte vector to be used to store the number of values of this annotation. See {@link #bv}. */
private final ByteVector parent;
/** The byte vector to be used to store the number of values of this annotation. See {@link #bv}. */
private final ByteVector parent;
/** Where the number of values of this annotation must be stored in {@link #parent}. */
private final int offset;
/** Where the number of values of this annotation must be stored in {@link #parent}. */
private final int offset;
/** Next annotation writer. This field is used to store annotation lists. */
AnnotationWriter next;
/** Next annotation writer. This field is used to store annotation lists. */
AnnotationWriter next;
/** Previous annotation writer. This field is used to store annotation lists. */
AnnotationWriter prev;
/** Previous annotation writer. This field is used to store annotation lists. */
AnnotationWriter prev;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
/**
* Constructs a new {@link AnnotationWriter}.
*
* @param cw the class writer to which this annotation must be added.
* @param named &#60;tt&#62;true&#60;tt&#62; if values are named, &#60;tt&#62;false&#60;/tt&#62; otherwise.
* @param bv where the annotation values must be stored.
* @param parent where the number of annotation values must be stored.
* @param offset where in &#60;tt&#62;parent&#60;/tt&#62; the number of annotation values must be stored.
*/
AnnotationWriter(
final ClassWriter cw, final boolean named, final ByteVector bv, final ByteVector parent, final int offset) {
super(Opcodes.ASM6);
this.cw = cw;
this.named = named;
this.bv = bv;
this.parent = parent;
this.offset = offset;
}
/**
* Constructs a new {@link AnnotationWriter}.
*
* @param cw the class writer to which this annotation must be added.
* @param named &#60;tt&#62;true&#60;tt&#62; if values are named, &#60;tt&#62;false&#60;/tt&#62; otherwise.
* @param bv where the annotation values must be stored.
* @param parent where the number of annotation values must be stored.
* @param offset where in &#60;tt&#62;parent&#60;/tt&#62; the number of annotation values must be stored.
*/
AnnotationWriter(
final ClassWriter cw, final boolean named, final ByteVector bv, final ByteVector parent, final int offset) {
super(Opcodes.ASM6);
this.cw = cw;
this.named = named;
this.bv = bv;
this.parent = parent;
this.offset = offset;
}
// ------------------------------------------------------------------------
// Implementation of the AnnotationVisitor abstract class
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Implementation of the AnnotationVisitor abstract class
// ------------------------------------------------------------------------
@Override
public void visit(final String name, final Object value) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
if (value instanceof String) {
bv.put12('s', cw.newUTF8((String) value));
} else if (value instanceof Byte) {
bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
} else if (value instanceof Boolean) {
int v = ((Boolean) value).booleanValue() ? 1 : 0;
bv.put12('Z', cw.newInteger(v).index);
} else if (value instanceof Character) {
bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
} else if (value instanceof Short) {
bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
} else if (value instanceof Type) {
bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
} else if (value instanceof byte[]) {
byte[] v = (byte[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('B', cw.newInteger(v[i]).index);
}
} else if (value instanceof boolean[]) {
boolean[] v = (boolean[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
}
} else if (value instanceof short[]) {
short[] v = (short[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('S', cw.newInteger(v[i]).index);
}
} else if (value instanceof char[]) {
char[] v = (char[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('C', cw.newInteger(v[i]).index);
}
} else if (value instanceof int[]) {
int[] v = (int[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('I', cw.newInteger(v[i]).index);
}
} else if (value instanceof long[]) {
long[] v = (long[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('J', cw.newLong(v[i]).index);
}
} else if (value instanceof float[]) {
float[] v = (float[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('F', cw.newFloat(v[i]).index);
}
} else if (value instanceof double[]) {
double[] v = (double[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('D', cw.newDouble(v[i]).index);
}
} else {
Item i = cw.newConstItem(value);
bv.put12(".s.IFJDCS".charAt(i.type), i.index);
}
}
@Override
public void visit(final String name, final Object value) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
if (value instanceof String) {
bv.put12('s', cw.newUTF8((String) value));
} else if (value instanceof Byte) {
bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
} else if (value instanceof Boolean) {
int v = ((Boolean) value).booleanValue() ? 1 : 0;
bv.put12('Z', cw.newInteger(v).index);
} else if (value instanceof Character) {
bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
} else if (value instanceof Short) {
bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
} else if (value instanceof Type) {
bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
} else if (value instanceof byte[]) {
byte[] v = (byte[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('B', cw.newInteger(v[i]).index);
}
} else if (value instanceof boolean[]) {
boolean[] v = (boolean[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
}
} else if (value instanceof short[]) {
short[] v = (short[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('S', cw.newInteger(v[i]).index);
}
} else if (value instanceof char[]) {
char[] v = (char[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('C', cw.newInteger(v[i]).index);
}
} else if (value instanceof int[]) {
int[] v = (int[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('I', cw.newInteger(v[i]).index);
}
} else if (value instanceof long[]) {
long[] v = (long[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('J', cw.newLong(v[i]).index);
}
} else if (value instanceof float[]) {
float[] v = (float[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('F', cw.newFloat(v[i]).index);
}
} else if (value instanceof double[]) {
double[] v = (double[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('D', cw.newDouble(v[i]).index);
}
} else {
Item i = cw.newConstItem(value);
bv.put12(".s.IFJDCS".charAt(i.type), i.index);
}
}
@Override
public void visitEnum(final String name, final String desc, final String value) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
}
@Override
public void visitEnum(final String name, final String desc, final String value) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
}
@Override
public AnnotationVisitor visitAnnotation(final String name, final String desc) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
// write tag and type, and reserve space for values count
bv.put12('@', cw.newUTF8(desc)).putShort(0);
return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
}
@Override
public AnnotationVisitor visitAnnotation(final String name, final String desc) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
// write tag and type, and reserve space for values count
bv.put12('@', cw.newUTF8(desc)).putShort(0);
return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
}
@Override
public AnnotationVisitor visitArray(final String name) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
// write tag, and reserve space for array size
bv.put12('[', 0);
return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
}
@Override
public AnnotationVisitor visitArray(final String name) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
}
// write tag, and reserve space for array size
bv.put12('[', 0);
return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
}
@Override
public void visitEnd() {
if (parent != null) {
byte[] data = parent.data;
data[offset] = (byte) (size >>> 8);
data[offset + 1] = (byte) size;
}
}
@Override
public void visitEnd() {
if (parent != null) {
byte[] data = parent.data;
data[offset] = (byte) (size >>> 8);
data[offset + 1] = (byte) size;
}
}
// ------------------------------------------------------------------------
// Utility methods
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Utility methods
// ------------------------------------------------------------------------
/**
* Returns the size of this annotation writer list.
*
* @return the size of this annotation writer list.
*/
int getSize() {
int size = 0;
AnnotationWriter aw = this;
while (aw != null) {
size += aw.bv.length;
aw = aw.next;
}
return size;
}
/**
* Returns the size of this annotation writer list.
*
* @return the size of this annotation writer list.
*/
int getSize() {
int size = 0;
AnnotationWriter aw = this;
while (aw != null) {
size += aw.bv.length;
aw = aw.next;
}
return size;
}
/**
* Puts the annotations of this annotation writer list into the given byte vector.
*
* @param out where the annotations must be put.
*/
void put(final ByteVector out) {
int n = 0;
int size = 2;
AnnotationWriter aw = this;
AnnotationWriter last = null;
while (aw != null) {
++n;
size += aw.bv.length;
aw.visitEnd(); // in case user forgot to call visitEnd
aw.prev = last;
last = aw;
aw = aw.next;
}
out.putInt(size);
out.putShort(n);
aw = last;
while (aw != null) {
out.putByteArray(aw.bv.data, 0, aw.bv.length);
aw = aw.prev;
}
}
/**
* Puts the annotations of this annotation writer list into the given byte vector.
*
* @param out where the annotations must be put.
*/
void put(final ByteVector out) {
int n = 0;
int size = 2;
AnnotationWriter aw = this;
AnnotationWriter last = null;
while (aw != null) {
++n;
size += aw.bv.length;
aw.visitEnd(); // in case user forgot to call visitEnd
aw.prev = last;
last = aw;
aw = aw.next;
}
out.putInt(size);
out.putShort(n);
aw = last;
while (aw != null) {
out.putByteArray(aw.bv.data, 0, aw.bv.length);
aw = aw.prev;
}
}
/**
* Puts the given annotation lists into the given byte vector.
*
* @param panns an array of annotation writer lists.
* @param off index of the first annotation to be written.
* @param out where the annotations must be put.
*/
static void put(final AnnotationWriter[] panns, final int off, final ByteVector out) {
int size = 1 + 2 * (panns.length - off);
for (int i = off; i < panns.length; ++i) {
size += panns[i] == null ? 0 : panns[i].getSize();
}
out.putInt(size).putByte(panns.length - off);
for (int i = off; i < panns.length; ++i) {
AnnotationWriter aw = panns[i];
AnnotationWriter last = null;
int n = 0;
while (aw != null) {
++n;
aw.visitEnd(); // in case user forgot to call visitEnd
aw.prev = last;
last = aw;
aw = aw.next;
}
out.putShort(n);
aw = last;
while (aw != null) {
out.putByteArray(aw.bv.data, 0, aw.bv.length);
aw = aw.prev;
}
}
}
/**
* Puts the given annotation lists into the given byte vector.
*
* @param panns an array of annotation writer lists.
* @param off index of the first annotation to be written.
* @param out where the annotations must be put.
*/
static void put(final AnnotationWriter[] panns, final int off, final ByteVector out) {
int size = 1 + 2 * (panns.length - off);
for (int i = off; i < panns.length; ++i) {
size += panns[i] == null ? 0 : panns[i].getSize();
}
out.putInt(size).putByte(panns.length - off);
for (int i = off; i < panns.length; ++i) {
AnnotationWriter aw = panns[i];
AnnotationWriter last = null;
int n = 0;
while (aw != null) {
++n;
aw.visitEnd(); // in case user forgot to call visitEnd
aw.prev = last;
last = aw;
aw = aw.next;
}
out.putShort(n);
aw = last;
while (aw != null) {
out.putByteArray(aw.bv.data, 0, aw.bv.length);
aw = aw.prev;
}
}
}
/**
* Puts the given type reference and type path into the given bytevector. LOCAL_VARIABLE and RESOURCE_VARIABLE
* target types are not supported.
*
* @param typeRef a reference to the annotated type. See {@link TypeReference}.
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or static inner type
* within 'typeRef'. May be &#60;tt&#62;null&#60;/tt&#62; if the annotation targets 'typeRef' as a whole.
* @param out where the type reference and type path must be put.
*/
static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
switch (typeRef >>> 24) {
case 0x00: // CLASS_TYPE_PARAMETER
case 0x01: // METHOD_TYPE_PARAMETER
case 0x16: // METHOD_FORMAL_PARAMETER
out.putShort(typeRef >>> 16);
break;
case 0x13: // FIELD
case 0x14: // METHOD_RETURN
case 0x15: // METHOD_RECEIVER
out.putByte(typeRef >>> 24);
break;
case 0x47: // CAST
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
out.putInt(typeRef);
break;
// case 0x10: // CLASS_EXTENDS
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
// case 0x17: // THROWS
// case 0x42: // EXCEPTION_PARAMETER
// case 0x43: // INSTANCEOF
// case 0x44: // NEW
// case 0x45: // CONSTRUCTOR_REFERENCE
// case 0x46: // METHOD_REFERENCE
default:
out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
break;
}
if (typePath == null) {
out.putByte(0);
} else {
int length = typePath.b[typePath.offset] * 2 + 1;
out.putByteArray(typePath.b, typePath.offset, length);
}
}
/**
* Puts the given type reference and type path into the given bytevector. LOCAL_VARIABLE and RESOURCE_VARIABLE
* target types are not supported.
*
* @param typeRef a reference to the annotated type. See {@link TypeReference}.
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or static inner type
* within 'typeRef'. May be &#60;tt&#62;null&#60;/tt&#62; if the annotation targets 'typeRef' as a whole.
* @param out where the type reference and type path must be put.
*/
static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
switch (typeRef >>> 24) {
case 0x00: // CLASS_TYPE_PARAMETER
case 0x01: // METHOD_TYPE_PARAMETER
case 0x16: // METHOD_FORMAL_PARAMETER
out.putShort(typeRef >>> 16);
break;
case 0x13: // FIELD
case 0x14: // METHOD_RETURN
case 0x15: // METHOD_RECEIVER
out.putByte(typeRef >>> 24);
break;
case 0x47: // CAST
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
out.putInt(typeRef);
break;
// case 0x10: // CLASS_EXTENDS
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
// case 0x17: // THROWS
// case 0x42: // EXCEPTION_PARAMETER
// case 0x43: // INSTANCEOF
// case 0x44: // NEW
// case 0x45: // CONSTRUCTOR_REFERENCE
// case 0x46: // METHOD_REFERENCE
default:
out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
break;
}
if (typePath == null) {
out.putByte(0);
} else {
int length = typePath.b[typePath.offset] * 2 + 1;
out.putByteArray(typePath.b, typePath.offset, length);
}
}
}

View File

@@ -17,124 +17,124 @@ import org.redkale.convert.json.JsonConvert;
*/
public class AsmMethodBean {
private List<AsmMethodParam> params;
private List<AsmMethodParam> params;
private int access;
private int access;
private String name;
private String name;
private String desc;
private String desc;
private String signature;
private String signature;
private String[] exceptions;
private String[] exceptions;
public AsmMethodBean() {}
public AsmMethodBean() {}
public AsmMethodBean(int access, String name, String desc, String signature, String[] exceptions) {
this.access = access;
this.name = name;
this.desc = desc;
this.signature = signature;
this.exceptions = exceptions;
this.params = new ArrayList<>();
}
public AsmMethodBean(int access, String name, String desc, String signature, String[] exceptions) {
this.access = access;
this.name = name;
this.desc = desc;
this.signature = signature;
this.exceptions = exceptions;
this.params = new ArrayList<>();
}
public static AsmMethodBean get(Map<String, AsmMethodBean> map, Method method) {
return map == null ? null : map.get(method.getName() + ":" + Type.getMethodDescriptor(method));
}
public static AsmMethodBean get(Map<String, AsmMethodBean> map, Method method) {
return map == null ? null : map.get(method.getName() + ":" + Type.getMethodDescriptor(method));
}
void removeEmptyNames() {
if (params != null) {
List<AsmMethodParam> dels = null;
for (AsmMethodParam p : params) {
if (" ".equals(p.getName())) {
if (dels == null) {
dels = new ArrayList<>();
}
dels.add(p);
}
}
if (dels != null) {
for (AsmMethodParam p : dels) {
params.remove(p);
}
}
}
}
void removeEmptyNames() {
if (params != null) {
List<AsmMethodParam> dels = null;
for (AsmMethodParam p : params) {
if (" ".equals(p.getName())) {
if (dels == null) {
dels = new ArrayList<>();
}
dels.add(p);
}
}
if (dels != null) {
for (AsmMethodParam p : dels) {
params.remove(p);
}
}
}
}
public List<String> fieldNameList() {
if (params == null) {
return new ArrayList<>();
}
List<String> rs = new ArrayList<>(params.size());
for (AsmMethodParam p : params) {
rs.add(p.getName());
}
return rs;
}
public List<String> fieldNameList() {
if (params == null) {
return new ArrayList<>();
}
List<String> rs = new ArrayList<>(params.size());
for (AsmMethodParam p : params) {
rs.add(p.getName());
}
return rs;
}
public String[] fieldNameArray() {
if (params == null) {
return null;
}
String[] rs = new String[params.size()];
for (int i = 0; i < rs.length; i++) {
rs[i] = params.get(i).getName();
}
return rs;
}
public String[] fieldNameArray() {
if (params == null) {
return null;
}
String[] rs = new String[params.size()];
for (int i = 0; i < rs.length; i++) {
rs[i] = params.get(i).getName();
}
return rs;
}
public List<AsmMethodParam> getParams() {
return params;
}
public List<AsmMethodParam> getParams() {
return params;
}
public void setParams(List<AsmMethodParam> params) {
this.params = params;
}
public void setParams(List<AsmMethodParam> params) {
this.params = params;
}
public int getAccess() {
return access;
}
public int getAccess() {
return access;
}
public void setAccess(int access) {
this.access = access;
}
public void setAccess(int access) {
this.access = access;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getSignature() {
return signature;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String[] getExceptions() {
return exceptions;
}
public String[] getExceptions() {
return exceptions;
}
public void setExceptions(String[] exceptions) {
this.exceptions = exceptions;
}
public void setExceptions(String[] exceptions) {
this.exceptions = exceptions;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -40,370 +40,370 @@ import org.redkale.util.Utility;
*/
public abstract class AsmMethodBoost<T> {
protected final AtomicInteger fieldIndex = new AtomicInteger();
protected final AtomicInteger fieldIndex = new AtomicInteger();
protected final boolean remote;
protected final boolean remote;
protected final Class serviceType;
protected final Class serviceType;
protected AsmMethodBoost(boolean remote, Class serviceType) {
this.remote = remote;
this.serviceType = serviceType;
}
protected AsmMethodBoost(boolean remote, Class serviceType) {
this.remote = remote;
this.serviceType = serviceType;
}
public static AsmMethodBoost create(boolean remote, Collection<AsmMethodBoost> list) {
return new AsmMethodBoosts(remote, list);
}
public static AsmMethodBoost create(boolean remote, Collection<AsmMethodBoost> list) {
return new AsmMethodBoosts(remote, list);
}
public static AsmMethodBoost create(boolean remote, AsmMethodBoost... items) {
return new AsmMethodBoosts(remote, items);
}
public static AsmMethodBoost create(boolean remote, AsmMethodBoost... items) {
return new AsmMethodBoosts(remote, items);
}
/**
* 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method)
*
* @param clazz Class
* @return Map
*/
public static Map<String, AsmMethodBean> getMethodBeans(Class clazz) {
Map<String, AsmMethodBean> rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz);
// 返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多
rs.values().forEach(AsmMethodBean::removeEmptyNames);
return rs;
}
/**
* 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method)
*
* @param clazz Class
* @return Map
*/
public static Map<String, AsmMethodBean> getMethodBeans(Class clazz) {
Map<String, AsmMethodBean> rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz);
// 返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多
rs.values().forEach(AsmMethodBean::removeEmptyNames);
return rs;
}
public static String getMethodBeanKey(Method method) {
return method.getName() + ":" + Type.getMethodDescriptor(method);
}
public static String getMethodBeanKey(Method method) {
return method.getName() + ":" + Type.getMethodDescriptor(method);
}
/**
* 获取需屏蔽的方法上的注解
*
* @param method 方法
* @return 需要屏蔽的注解
*/
public abstract List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
/**
* 获取需屏蔽的方法上的注解
*
* @param method 方法
* @return 需要屏蔽的注解
*/
public abstract List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
/**
* 对方法进行动态加强处理
*
* @param classLoader ClassLoader
* @param cw 动态字节码Writer
* @param newDynName 动态新类名
* @param fieldPrefix 动态字段的前缀
* @param filterAnns 需要过滤的注解
* @param method 操作的方法
* @param newMethodName 新的方法名, 可能为null
* @return 下一个新的方法名不做任何处理应返回参数newMethodName
*/
public abstract String doMethod(
ClassLoader classLoader,
ClassWriter cw,
String newDynName,
String fieldPrefix,
List<Class<? extends Annotation>> filterAnns,
Method method,
@Nullable String newMethodName);
/**
* 对方法进行动态加强处理
*
* @param classLoader ClassLoader
* @param cw 动态字节码Writer
* @param newDynName 动态新类名
* @param fieldPrefix 动态字段的前缀
* @param filterAnns 需要过滤的注解
* @param method 操作的方法
* @param newMethodName 新的方法名, 可能为null
* @return 下一个新的方法名不做任何处理应返回参数newMethodName
*/
public abstract String doMethod(
ClassLoader classLoader,
ClassWriter cw,
String newDynName,
String fieldPrefix,
List<Class<? extends Annotation>> filterAnns,
Method method,
@Nullable String newMethodName);
/**
* 处理所有动态方法后调用
*
* @param classLoader ClassLoader
* @param cw 动态字节码Writer
* @param newDynName 动态新类名
* @param fieldPrefix 动态字段的前缀
*/
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {}
/**
* 处理所有动态方法后调用
*
* @param classLoader ClassLoader
* @param cw 动态字节码Writer
* @param newDynName 动态新类名
* @param fieldPrefix 动态字段的前缀
*/
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {}
/**
* 实例对象进行操作,通常用于给动态的字段赋值
*
* @param resourceFactory ResourceFactory
* @param service 实例对象
*/
public abstract void doInstance(ResourceFactory resourceFactory, T service);
/**
* 实例对象进行操作,通常用于给动态的字段赋值
*
* @param resourceFactory ResourceFactory
* @param service 实例对象
*/
public abstract void doInstance(ResourceFactory resourceFactory, T service);
protected AsmMethodBean getMethodBean(Method method) {
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
return AsmMethodBean.get(methodBeans, method);
}
protected AsmMethodBean getMethodBean(Method method) {
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
return AsmMethodBean.get(methodBeans, method);
}
protected MethodVisitor createMethodVisitor(
ClassWriter cw, Method method, String newMethodName, AsmMethodBean methodBean) {
return new MethodDebugVisitor(cw.visitMethod(
getAcc(method, newMethodName),
getNowMethodName(method, newMethodName),
Type.getMethodDescriptor(method),
getMethodSignature(method, methodBean),
getMethodExceptions(method, methodBean)));
}
protected MethodVisitor createMethodVisitor(
ClassWriter cw, Method method, String newMethodName, AsmMethodBean methodBean) {
return new MethodDebugVisitor(cw.visitMethod(
getAcc(method, newMethodName),
getNowMethodName(method, newMethodName),
Type.getMethodDescriptor(method),
getMethodSignature(method, methodBean),
getMethodExceptions(method, methodBean)));
}
protected int getAcc(Method method, String newMethodName) {
if (newMethodName != null) {
return ACC_PRIVATE;
}
return Modifier.isProtected(method.getModifiers()) ? ACC_PROTECTED : ACC_PUBLIC;
}
protected int getAcc(Method method, String newMethodName) {
if (newMethodName != null) {
return ACC_PRIVATE;
}
return Modifier.isProtected(method.getModifiers()) ? ACC_PROTECTED : ACC_PUBLIC;
}
protected String getNowMethodName(Method method, String newMethodName) {
return newMethodName == null ? method.getName() : newMethodName;
}
protected String getNowMethodName(Method method, String newMethodName) {
return newMethodName == null ? method.getName() : newMethodName;
}
protected String getMethodSignature(Method method, AsmMethodBean methodBean) {
return methodBean != null ? methodBean.getSignature() : null;
}
protected String getMethodSignature(Method method, AsmMethodBean methodBean) {
return methodBean != null ? methodBean.getSignature() : null;
}
protected String[] getMethodExceptions(Method method, AsmMethodBean methodBean) {
if (methodBean == null) {
String[] exceptions = null;
Class<?>[] expTypes = method.getExceptionTypes();
if (expTypes.length > 0) {
exceptions = new String[expTypes.length];
for (int i = 0; i < expTypes.length; i++) {
exceptions[i] = expTypes[i].getName().replace('.', '/');
}
}
return exceptions;
} else {
return methodBean.getExceptions();
}
}
protected String[] getMethodExceptions(Method method, AsmMethodBean methodBean) {
if (methodBean == null) {
String[] exceptions = null;
Class<?>[] expTypes = method.getExceptionTypes();
if (expTypes.length > 0) {
exceptions = new String[expTypes.length];
for (int i = 0; i < expTypes.length; i++) {
exceptions[i] = expTypes[i].getName().replace('.', '/');
}
}
return exceptions;
} else {
return methodBean.getExceptions();
}
}
protected void visitRawAnnotation(
Method method, String newMethodName, MethodVisitor mv, Class selfAnnType, List filterAnns) {
if (newMethodName == null) {
// 给方法加上原有的Annotation
final Annotation[] anns = method.getAnnotations();
for (Annotation ann : anns) {
if (ann.annotationType() != selfAnnType
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
}
}
// 给参数加上原有的Annotation
final Annotation[][] annss = method.getParameterAnnotations();
for (int k = 0; k < annss.length; k++) {
for (Annotation ann : annss[k]) {
Asms.visitAnnotation(
mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
}
}
}
}
protected void visitRawAnnotation(
Method method, String newMethodName, MethodVisitor mv, Class selfAnnType, List filterAnns) {
if (newMethodName == null) {
// 给方法加上原有的Annotation
final Annotation[] anns = method.getAnnotations();
for (Annotation ann : anns) {
if (ann.annotationType() != selfAnnType
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
}
}
// 给参数加上原有的Annotation
final Annotation[][] annss = method.getParameterAnnotations();
for (int k = 0; k < annss.length; k++) {
for (Annotation ann : annss[k]) {
Asms.visitAnnotation(
mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
}
}
}
}
protected List<Integer> visitVarInsnParamTypes(MethodVisitor mv, Method method, int insn) {
// 传参数
Class[] paramTypes = method.getParameterTypes();
List<Integer> insns = new ArrayList<>();
for (Class pt : paramTypes) {
insn++;
if (pt.isPrimitive()) {
if (pt == long.class) {
mv.visitVarInsn(LLOAD, insn++);
} else if (pt == float.class) {
mv.visitVarInsn(FLOAD, insn++);
} else if (pt == double.class) {
mv.visitVarInsn(DLOAD, insn++);
} else {
mv.visitVarInsn(ILOAD, insn);
}
} else {
mv.visitVarInsn(ALOAD, insn);
}
insns.add(insn);
}
return insns;
}
protected List<Integer> visitVarInsnParamTypes(MethodVisitor mv, Method method, int insn) {
// 传参数
Class[] paramTypes = method.getParameterTypes();
List<Integer> insns = new ArrayList<>();
for (Class pt : paramTypes) {
insn++;
if (pt.isPrimitive()) {
if (pt == long.class) {
mv.visitVarInsn(LLOAD, insn++);
} else if (pt == float.class) {
mv.visitVarInsn(FLOAD, insn++);
} else if (pt == double.class) {
mv.visitVarInsn(DLOAD, insn++);
} else {
mv.visitVarInsn(ILOAD, insn);
}
} else {
mv.visitVarInsn(ALOAD, insn);
}
insns.add(insn);
}
return insns;
}
protected void visitParamTypesLocalVariable(
MethodVisitor mv, Method method, Label l0, Label l2, List<Integer> insns, AsmMethodBean methodBean) {
Class[] paramTypes = method.getParameterTypes();
if (methodBean != null && paramTypes.length > 0) {
mv.visitLabel(l2);
List<AsmMethodParam> params = methodBean.getParams();
for (int i = 0; i < paramTypes.length; i++) {
AsmMethodParam param = params.get(i);
mv.visitLocalVariable(
param.getName(),
param.description(paramTypes[i]),
param.signature(paramTypes[i]),
l0,
l2,
insns.get(i));
}
}
}
protected void visitParamTypesLocalVariable(
MethodVisitor mv, Method method, Label l0, Label l2, List<Integer> insns, AsmMethodBean methodBean) {
Class[] paramTypes = method.getParameterTypes();
if (methodBean != null && paramTypes.length > 0) {
mv.visitLabel(l2);
List<AsmMethodParam> params = methodBean.getParams();
for (int i = 0; i < paramTypes.length; i++) {
AsmMethodParam param = params.get(i);
mv.visitLocalVariable(
param.getName(),
param.description(paramTypes[i]),
param.signature(paramTypes[i]),
l0,
l2,
insns.get(i));
}
}
}
protected void visitInsnReturn(
MethodVisitor mv, Method method, Label l0, List<Integer> insns, AsmMethodBean methodBean) {
if (method.getGenericReturnType() == void.class) {
mv.visitInsn(RETURN);
} else {
Class returnclz = method.getReturnType();
if (returnclz.isPrimitive()) {
if (returnclz == long.class) {
mv.visitInsn(LRETURN);
} else if (returnclz == float.class) {
mv.visitInsn(FRETURN);
} else if (returnclz == double.class) {
mv.visitInsn(DRETURN);
} else {
mv.visitInsn(IRETURN);
}
} else {
mv.visitInsn(ARETURN);
}
}
visitParamTypesLocalVariable(mv, method, l0, new Label(), insns, methodBean);
}
protected void visitInsnReturn(
MethodVisitor mv, Method method, Label l0, List<Integer> insns, AsmMethodBean methodBean) {
if (method.getGenericReturnType() == void.class) {
mv.visitInsn(RETURN);
} else {
Class returnclz = method.getReturnType();
if (returnclz.isPrimitive()) {
if (returnclz == long.class) {
mv.visitInsn(LRETURN);
} else if (returnclz == float.class) {
mv.visitInsn(FRETURN);
} else if (returnclz == double.class) {
mv.visitInsn(DRETURN);
} else {
mv.visitInsn(IRETURN);
}
} else {
mv.visitInsn(ARETURN);
}
}
visitParamTypesLocalVariable(mv, method, l0, new Label(), insns, methodBean);
}
/**
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
*
* @param <T> 泛型
* @since 2.8.0
*/
static class AsmMethodBoosts<T> extends AsmMethodBoost<T> {
/**
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
*
* @param <T> 泛型
* @since 2.8.0
*/
static class AsmMethodBoosts<T> extends AsmMethodBoost<T> {
private final AsmMethodBoost[] items;
private final AsmMethodBoost[] items;
public AsmMethodBoosts(boolean remote, Collection<AsmMethodBoost> list) {
super(remote, null);
this.items = list.toArray(new AsmMethodBoost[list.size()]);
}
public AsmMethodBoosts(boolean remote, Collection<AsmMethodBoost> list) {
super(remote, null);
this.items = list.toArray(new AsmMethodBoost[list.size()]);
}
public AsmMethodBoosts(boolean remote, AsmMethodBoost... items) {
super(remote, null);
this.items = items;
}
public AsmMethodBoosts(boolean remote, AsmMethodBoost... items) {
super(remote, null);
this.items = items;
}
@Override
public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
List<Class<? extends Annotation>> list = null;
for (AsmMethodBoost item : items) {
if (item != null) {
List<Class<? extends Annotation>> sub = item.filterMethodAnnotations(method);
if (sub != null) {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(sub);
}
}
}
return list;
}
@Override
public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
List<Class<? extends Annotation>> list = null;
for (AsmMethodBoost item : items) {
if (item != null) {
List<Class<? extends Annotation>> sub = item.filterMethodAnnotations(method);
if (sub != null) {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(sub);
}
}
}
return list;
}
@Override
public String doMethod(
ClassLoader classLoader,
ClassWriter cw,
String newDynName,
String fieldPrefix,
List<Class<? extends Annotation>> filterAnns,
Method method,
String newMethodName) {
String newName = newMethodName;
for (AsmMethodBoost item : items) {
if (item != null) {
newName = item.doMethod(classLoader, cw, newDynName, fieldPrefix, filterAnns, method, newName);
}
}
return newName;
}
@Override
public String doMethod(
ClassLoader classLoader,
ClassWriter cw,
String newDynName,
String fieldPrefix,
List<Class<? extends Annotation>> filterAnns,
Method method,
String newMethodName) {
String newName = newMethodName;
for (AsmMethodBoost item : items) {
if (item != null) {
newName = item.doMethod(classLoader, cw, newDynName, fieldPrefix, filterAnns, method, newName);
}
}
return newName;
}
@Override
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
for (AsmMethodBoost item : items) {
if (item != null) {
item.doAfterMethods(classLoader, cw, newDynName, fieldPrefix);
}
}
}
@Override
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
for (AsmMethodBoost item : items) {
if (item != null) {
item.doAfterMethods(classLoader, cw, newDynName, fieldPrefix);
}
}
}
@Override
public void doInstance(ResourceFactory resourceFactory, T service) {
for (AsmMethodBoost item : items) {
if (item != null) {
item.doInstance(resourceFactory, service);
}
}
}
}
@Override
public void doInstance(ResourceFactory resourceFactory, T service) {
for (AsmMethodBoost item : items) {
if (item != null) {
item.doInstance(resourceFactory, service);
}
}
}
}
static class MethodParamClassVisitor extends ClassVisitor {
static class MethodParamClassVisitor extends ClassVisitor {
private Class serviceType;
private Class serviceType;
private final Map<String, AsmMethodBean> methodBeanMap;
private final Map<String, AsmMethodBean> methodBeanMap;
public MethodParamClassVisitor(int api, Class serviceType, final Map<String, AsmMethodBean> methodBeanMap) {
super(api);
this.serviceType = serviceType;
this.methodBeanMap = methodBeanMap;
}
public MethodParamClassVisitor(int api, Class serviceType, final Map<String, AsmMethodBean> methodBeanMap) {
super(api);
this.serviceType = serviceType;
this.methodBeanMap = methodBeanMap;
}
@Override
public MethodVisitor visitMethod(
int methodAccess,
String methodName,
String methodDesc,
String methodSignature,
String[] methodExceptions) {
super.visitMethod(api, methodName, methodDesc, methodSignature, methodExceptions);
if (java.lang.reflect.Modifier.isStatic(methodAccess)) {
return null;
}
String key = methodName + ":" + methodDesc;
if (methodBeanMap.containsKey(key)) {
return null;
}
AsmMethodBean bean =
new AsmMethodBean(methodAccess, methodName, methodDesc, methodSignature, methodExceptions);
List<AsmMethodParam> paramList = bean.getParams();
methodBeanMap.put(key, bean);
return new MethodVisitor(Opcodes.ASM6) {
@Override
public void visitParameter(String paramName, int paramAccess) {
paramList.add(new AsmMethodParam(paramName));
}
@Override
public MethodVisitor visitMethod(
int methodAccess,
String methodName,
String methodDesc,
String methodSignature,
String[] methodExceptions) {
super.visitMethod(api, methodName, methodDesc, methodSignature, methodExceptions);
if (java.lang.reflect.Modifier.isStatic(methodAccess)) {
return null;
}
String key = methodName + ":" + methodDesc;
if (methodBeanMap.containsKey(key)) {
return null;
}
AsmMethodBean bean =
new AsmMethodBean(methodAccess, methodName, methodDesc, methodSignature, methodExceptions);
List<AsmMethodParam> paramList = bean.getParams();
methodBeanMap.put(key, bean);
return new MethodVisitor(Opcodes.ASM6) {
@Override
public void visitParameter(String paramName, int paramAccess) {
paramList.add(new AsmMethodParam(paramName));
}
@Override
public void visitLocalVariable(
String varName, String varDesc, String varSignature, Label start, Label end, int varIndex) {
if (varIndex < 1) {
return;
}
int size = paramList.size();
// index并不会按顺序执行
if (varIndex > size) {
for (int i = size; i < varIndex; i++) {
paramList.add(new AsmMethodParam(" ", varDesc, varSignature));
}
paramList.set(varIndex - 1, new AsmMethodParam(varName, varDesc, varSignature));
}
paramList.set(varIndex - 1, new AsmMethodParam(varName, varDesc, varSignature));
}
};
}
@Override
public void visitLocalVariable(
String varName, String varDesc, String varSignature, Label start, Label end, int varIndex) {
if (varIndex < 1) {
return;
}
int size = paramList.size();
// index并不会按顺序执行
if (varIndex > size) {
for (int i = size; i < varIndex; i++) {
paramList.add(new AsmMethodParam(" ", varDesc, varSignature));
}
paramList.set(varIndex - 1, new AsmMethodParam(varName, varDesc, varSignature));
}
paramList.set(varIndex - 1, new AsmMethodParam(varName, varDesc, varSignature));
}
};
}
// 返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多
static Map<String, AsmMethodBean> getMethodParamNames(Map<String, AsmMethodBean> map, Class clazz) {
String n = clazz.getName();
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
if (in == null) {
return map;
}
try {
new ClassReader(Utility.readBytesThenClose(in))
.accept(new MethodParamClassVisitor(Opcodes.ASM6, clazz, map), 0);
} catch (Exception e) { // 无需理会
}
Class superClass = clazz.getSuperclass();
if (superClass == null || superClass == Object.class) { // 接口的getSuperclass为null
return map;
}
return getMethodParamNames(map, superClass);
}
}
// 返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多
static Map<String, AsmMethodBean> getMethodParamNames(Map<String, AsmMethodBean> map, Class clazz) {
String n = clazz.getName();
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
if (in == null) {
return map;
}
try {
new ClassReader(Utility.readBytesThenClose(in))
.accept(new MethodParamClassVisitor(Opcodes.ASM6, clazz, map), 0);
} catch (Exception e) { // 无需理会
}
Class superClass = clazz.getSuperclass();
if (superClass == null || superClass == Object.class) { // 接口的getSuperclass为null
return map;
}
return getMethodParamNames(map, superClass);
}
}
}

View File

@@ -15,58 +15,58 @@ import org.redkale.util.TypeToken;
*/
public class AsmMethodParam {
private String name;
private String name;
private String description;
private String description;
private String signature;
private String signature;
public AsmMethodParam() {}
public AsmMethodParam() {}
public AsmMethodParam(String name) {
this.name = name;
}
public AsmMethodParam(String name) {
this.name = name;
}
public AsmMethodParam(String name, String description, String signature) {
this.name = name;
this.description = description;
this.signature = signature;
}
public AsmMethodParam(String name, String description, String signature) {
this.name = name;
this.description = description;
this.signature = signature;
}
public String description(java.lang.reflect.Type type) {
return description == null ? Type.getDescriptor(TypeToken.typeToClass(type)) : description;
}
public String description(java.lang.reflect.Type type) {
return description == null ? Type.getDescriptor(TypeToken.typeToClass(type)) : description;
}
public String signature(java.lang.reflect.Type type) {
return signature;
}
public String signature(java.lang.reflect.Type type) {
return signature;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSignature() {
return signature;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -25,173 +25,173 @@ import org.redkale.util.RedkaleException;
*/
public final class Asms {
private Asms() {}
private Asms() {}
public static Handle createLambdaMetaHandle() {
return new Handle(
Opcodes.H_INVOKESTATIC,
"java/lang/invoke/LambdaMetafactory",
"metafactory",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
false);
}
public static Handle createLambdaMetaHandle() {
return new Handle(
Opcodes.H_INVOKESTATIC,
"java/lang/invoke/LambdaMetafactory",
"metafactory",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
false);
}
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) {
throw new RedkaleException(e);
}
}
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) {
throw new RedkaleException(e);
}
}
public static void visitInsn(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 visitInsn(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 visitFieldInsn(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
} else if (clazz == byte.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
} else if (clazz == char.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
} else if (clazz == short.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
} else if (clazz == int.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
} else if (clazz == float.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
} else if (clazz == long.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
} else if (clazz == double.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
} else {
mv.visitLdcInsn(Type.getType(Type.getDescriptor(clazz)));
}
}
public static void visitFieldInsn(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
} else if (clazz == byte.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
} else if (clazz == char.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
} else if (clazz == short.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
} else if (clazz == int.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
} else if (clazz == float.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
} else if (clazz == long.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
} else if (clazz == double.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
} else {
mv.visitLdcInsn(Type.getType(Type.getDescriptor(clazz)));
}
}
public static void visitPrimitiveValueOf(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
} else if (clazz == byte.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
} else if (clazz == short.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
} else if (clazz == char.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
} else if (clazz == int.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
} else if (clazz == float.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
} else if (clazz == long.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
} else if (clazz == double.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
}
}
public static void visitPrimitiveValueOf(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
} else if (clazz == byte.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
} else if (clazz == short.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
} else if (clazz == char.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
} else if (clazz == int.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
} else if (clazz == float.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
} else if (clazz == long.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
} else if (clazz == double.class) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
}
}
public static void visitCheckCast(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
} else if (clazz == byte.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
} else if (clazz == short.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
} else if (clazz == char.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
} else if (clazz == int.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
} else if (clazz == float.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
} else if (clazz == long.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
} else if (clazz == double.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
} else {
mv.visitTypeInsn(CHECKCAST, clazz.getName().replace('.', '/'));
}
}
public static void visitCheckCast(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
} else if (clazz == byte.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
} else if (clazz == short.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
} else if (clazz == char.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
} else if (clazz == int.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
} else if (clazz == float.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
} else if (clazz == long.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
} else if (clazz == double.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
} else {
mv.visitTypeInsn(CHECKCAST, clazz.getName().replace('.', '/'));
}
}
public static void visitPrimitiveVirtual(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
} else if (clazz == byte.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
} else if (clazz == short.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
} else if (clazz == char.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
} else if (clazz == int.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
} else if (clazz == float.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
} else if (clazz == long.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
} else if (clazz == double.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
}
}
public static void visitPrimitiveVirtual(MethodVisitor mv, Class clazz) {
if (clazz == boolean.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
} else if (clazz == byte.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
} else if (clazz == short.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
} else if (clazz == char.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
} else if (clazz == int.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
} else if (clazz == float.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
} else if (clazz == long.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
} else if (clazz == double.class) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
}
}
}

View File

@@ -68,245 +68,245 @@ import java.util.Arrays;
*/
public class Attribute {
/** The type of this attribute. */
public final String type;
/** The type of this attribute. */
public final String type;
/** The raw value of this attribute, used only for unknown attributes. */
byte[] value;
/** The raw value of this attribute, used only for unknown attributes. */
byte[] value;
/** The next attribute in this attribute list. May be &#60;tt&#62;null&#60;/tt&#62;. */
Attribute next;
/** The next attribute in this attribute list. May be &#60;tt&#62;null&#60;/tt&#62;. */
Attribute next;
/**
* Constructs a new empty attribute.
*
* @param type the type of the attribute.
*/
protected Attribute(final String type) {
this.type = type;
}
/**
* Constructs a new empty attribute.
*
* @param type the type of the attribute.
*/
protected Attribute(final String type) {
this.type = type;
}
/**
* Returns &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is unknown. The default implementation of this
* method always returns &#60;tt&#62;true&#60;/tt&#62;.
*
* @return &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is unknown.
*/
public boolean isUnknown() {
return true;
}
/**
* Returns &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is unknown. The default implementation of this
* method always returns &#60;tt&#62;true&#60;/tt&#62;.
*
* @return &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is unknown.
*/
public boolean isUnknown() {
return true;
}
/**
* Returns &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is a code attribute.
*
* @return &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is a code attribute.
*/
public boolean isCodeAttribute() {
return false;
}
/**
* Returns &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is a code attribute.
*
* @return &#60;tt&#62;true&#60;/tt&#62; if this type of attribute is a code attribute.
*/
public boolean isCodeAttribute() {
return false;
}
/**
* Returns the labels corresponding to this attribute.
*
* @return the labels corresponding to this attribute, or &#60;tt&#62;null&#60;/tt&#62; if this attribute is not a
* code attribute that contains labels.
*/
protected Label[] getLabels() {
return null;
}
/**
* Returns the labels corresponding to this attribute.
*
* @return the labels corresponding to this attribute, or &#60;tt&#62;null&#60;/tt&#62; if this attribute is not a
* code attribute that contains labels.
*/
protected Label[] getLabels() {
return null;
}
/**
* Reads a {@link #type type} attribute. This method must return a <i>new</i> {@link Attribute} object, of type
* {@link #type type}, corresponding to the &#60;tt&#62;len&#60;/tt&#62; bytes starting at the given offset, in the
* given class reader.
*
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the attribute's content in {@link ClassReader#b cr.b}. The 6 attribute
* header bytes, containing the type and the length of the attribute, are not taken into account here.
* @param len the length of the attribute's content.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass(int,char[]) readClass} or {@link ClassReader#readConst readConst}.
* @param codeOff index of the first byte of code's attribute content in {@link ClassReader#b cr.b}, or -1 if the
* attribute to be read is not a code attribute. The 6 attribute header bytes, containing the type and the
* length of the attribute, are not taken into account here.
* @param labels the labels of the method's code, or &#60;tt&#62;null&#60;/tt&#62; if the attribute to be read is
* not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given bytes.
*/
protected Attribute read(
final ClassReader cr,
final int off,
final int len,
final char[] buf,
final int codeOff,
final Label[] labels) {
Attribute attr = new Attribute(type);
attr.value = new byte[len];
System.arraycopy(cr.b, off, attr.value, 0, len);
return attr;
}
/**
* Reads a {@link #type type} attribute. This method must return a <i>new</i> {@link Attribute} object, of type
* {@link #type type}, corresponding to the &#60;tt&#62;len&#60;/tt&#62; bytes starting at the given offset, in the
* given class reader.
*
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the attribute's content in {@link ClassReader#b cr.b}. The 6 attribute
* header bytes, containing the type and the length of the attribute, are not taken into account here.
* @param len the length of the attribute's content.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass(int,char[]) readClass} or {@link ClassReader#readConst readConst}.
* @param codeOff index of the first byte of code's attribute content in {@link ClassReader#b cr.b}, or -1 if the
* attribute to be read is not a code attribute. The 6 attribute header bytes, containing the type and the
* length of the attribute, are not taken into account here.
* @param labels the labels of the method's code, or &#60;tt&#62;null&#60;/tt&#62; if the attribute to be read is
* not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given bytes.
*/
protected Attribute read(
final ClassReader cr,
final int off,
final int len,
final char[] buf,
final int codeOff,
final Label[] labels) {
Attribute attr = new Attribute(type);
attr.value = new byte[len];
System.arraycopy(cr.b, off, attr.value, 0, len);
return attr;
}
/**
* Returns the byte array form of this attribute.
*
* @param cw the class to which this attribute must be added. This parameter can be used to add to the constant pool
* of this class the items that corresponds to this attribute.
* @param code the bytecode of the method corresponding to this code attribute, or &#60;tt&#62;null&#60;/tt&#62; if
* this attribute is not a code attributes.
* @param len the length of the bytecode of the method corresponding to this code attribute, or
* &#60;tt&#62;null&#60;/tt&#62; if this attribute is not a code attribute.
* @param maxStack the maximum stack size of the method corresponding to this code attribute, or -1 if this
* attribute is not a code attribute.
* @param maxLocals the maximum number of local variables of the method corresponding to this code attribute, or -1
* if this attribute is not a code attribute.
* @return the byte array form of this attribute.
*/
protected ByteVector write(
final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) {
ByteVector v = new ByteVector();
v.data = value;
v.length = value.length;
return v;
}
/**
* Returns the byte array form of this attribute.
*
* @param cw the class to which this attribute must be added. This parameter can be used to add to the constant pool
* of this class the items that corresponds to this attribute.
* @param code the bytecode of the method corresponding to this code attribute, or &#60;tt&#62;null&#60;/tt&#62; if
* this attribute is not a code attributes.
* @param len the length of the bytecode of the method corresponding to this code attribute, or
* &#60;tt&#62;null&#60;/tt&#62; if this attribute is not a code attribute.
* @param maxStack the maximum stack size of the method corresponding to this code attribute, or -1 if this
* attribute is not a code attribute.
* @param maxLocals the maximum number of local variables of the method corresponding to this code attribute, or -1
* if this attribute is not a code attribute.
* @return the byte array form of this attribute.
*/
protected ByteVector write(
final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) {
ByteVector v = new ByteVector();
v.data = value;
v.length = value.length;
return v;
}
/**
* Returns the length of the attribute list that begins with this attribute.
*
* @return the length of the attribute list that begins with this attribute.
*/
final int getCount() {
int count = 0;
Attribute attr = this;
while (attr != null) {
count += 1;
attr = attr.next;
}
return count;
}
/**
* Returns the length of the attribute list that begins with this attribute.
*
* @return the length of the attribute list that begins with this attribute.
*/
final int getCount() {
int count = 0;
Attribute attr = this;
while (attr != null) {
count += 1;
attr = attr.next;
}
return count;
}
/**
* Returns the size of all the attributes in this attribute list.
*
* @param cw the class writer to be used to convert the attributes into byte arrays, with the {@link #write write}
* method.
* @param code the bytecode of the method corresponding to these code attributes, or &#60;tt&#62;null&#60;/tt&#62;
* if these attributes are not code attributes.
* @param len the length of the bytecode of the method corresponding to these code attributes, or
* &#60;tt&#62;null&#60;/tt&#62; if these attributes are not code attributes.
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or -1 if these
* attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method corresponding to these code attributes, or
* -1 if these attributes are not code attributes.
* @return the size of all the attributes in this attribute list. This size includes the size of the attribute
* headers.
*/
final int getSize(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) {
Attribute attr = this;
int size = 0;
while (attr != null) {
cw.newUTF8(attr.type);
size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
attr = attr.next;
}
return size;
}
/**
* Returns the size of all the attributes in this attribute list.
*
* @param cw the class writer to be used to convert the attributes into byte arrays, with the {@link #write write}
* method.
* @param code the bytecode of the method corresponding to these code attributes, or &#60;tt&#62;null&#60;/tt&#62;
* if these attributes are not code attributes.
* @param len the length of the bytecode of the method corresponding to these code attributes, or
* &#60;tt&#62;null&#60;/tt&#62; if these attributes are not code attributes.
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or -1 if these
* attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method corresponding to these code attributes, or
* -1 if these attributes are not code attributes.
* @return the size of all the attributes in this attribute list. This size includes the size of the attribute
* headers.
*/
final int getSize(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) {
Attribute attr = this;
int size = 0;
while (attr != null) {
cw.newUTF8(attr.type);
size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
attr = attr.next;
}
return size;
}
/**
* Writes all the attributes of this attribute list in the given byte vector.
*
* @param cw the class writer to be used to convert the attributes into byte arrays, with the {@link #write write}
* method.
* @param code the bytecode of the method corresponding to these code attributes, or &#60;tt&#62;null&#60;/tt&#62;
* if these attributes are not code attributes.
* @param len the length of the bytecode of the method corresponding to these code attributes, or
* &#60;tt&#62;null&#60;/tt&#62; if these attributes are not code attributes.
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or -1 if these
* attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method corresponding to these code attributes, or
* -1 if these attributes are not code attributes.
* @param out where the attributes must be written.
*/
final void put(
final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals,
final ByteVector out) {
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
out.putByteArray(b.data, 0, b.length);
attr = attr.next;
}
}
/**
* Writes all the attributes of this attribute list in the given byte vector.
*
* @param cw the class writer to be used to convert the attributes into byte arrays, with the {@link #write write}
* method.
* @param code the bytecode of the method corresponding to these code attributes, or &#60;tt&#62;null&#60;/tt&#62;
* if these attributes are not code attributes.
* @param len the length of the bytecode of the method corresponding to these code attributes, or
* &#60;tt&#62;null&#60;/tt&#62; if these attributes are not code attributes.
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or -1 if these
* attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method corresponding to these code attributes, or
* -1 if these attributes are not code attributes.
* @param out where the attributes must be written.
*/
final void put(
final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals,
final ByteVector out) {
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
out.putByteArray(b.data, 0, b.length);
attr = attr.next;
}
}
// The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely
// removed.
// see also changes in ClassReader.accept.
/** */
public static class NestMembers extends Attribute {
/** */
public NestMembers() {
super("NestMembers");
}
// The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely
// removed.
// see also changes in ClassReader.accept.
/** */
public static class NestMembers extends Attribute {
/** */
public NestMembers() {
super("NestMembers");
}
byte[] bytes;
String[] classes;
byte[] bytes;
String[] classes;
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
int offset = off;
NestMembers a = new NestMembers();
int size = cr.readShort(off);
a.classes = new String[size];
off += 2;
for (int i = 0; i < size; i++) {
a.classes[i] = cr.readClass(off, buf);
off += 2;
}
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
return a;
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
int offset = off;
NestMembers a = new NestMembers();
int size = cr.readShort(off);
a.classes = new String[size];
off += 2;
for (int i = 0; i < size; i++) {
a.classes[i] = cr.readClass(off, buf);
off += 2;
}
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
return a;
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
ByteVector v = new ByteVector(bytes.length);
v.putShort(classes.length);
for (String s : classes) {
v.putShort(cw.newClass(s));
}
return v;
}
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
ByteVector v = new ByteVector(bytes.length);
v.putShort(classes.length);
for (String s : classes) {
v.putShort(cw.newClass(s));
}
return v;
}
}
/** */
public static class NestHost extends Attribute {
/** */
public static class NestHost extends Attribute {
byte[] bytes;
String clazz;
/** */
public NestHost() {
super("NestHost");
}
byte[] bytes;
String clazz;
/** */
public NestHost() {
super("NestHost");
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
int offset = off;
NestHost a = new NestHost();
a.clazz = cr.readClass(off, buf);
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
return a;
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
int offset = off;
NestHost a = new NestHost();
a.clazz = cr.readClass(off, buf);
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
return a;
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
ByteVector v = new ByteVector(bytes.length);
v.putShort(cw.newClass(clazz));
return v;
}
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
ByteVector v = new ByteVector(bytes.length);
v.putShort(cw.newClass(clazz));
return v;
}
}
static final Attribute[] DEFAULT_ATTRIBUTE_PROTOS = new Attribute[] {new NestMembers(), new NestHost()};
static final Attribute[] DEFAULT_ATTRIBUTE_PROTOS = new Attribute[] {new NestMembers(), new NestHost()};
}

View File

@@ -66,266 +66,266 @@ package org.redkale.asm;
*/
public class ByteVector {
/** The content of this vector. */
byte[] data;
/** The content of this vector. */
byte[] data;
/** Actual number of bytes in this vector. */
int length;
/** Actual number of bytes in this vector. */
int length;
/** Constructs a new {@link ByteVector ByteVector} with a default initial size. */
public ByteVector() {
data = new byte[64];
}
/** Constructs a new {@link ByteVector ByteVector} with a default initial size. */
public ByteVector() {
data = new byte[64];
}
/**
* Constructs a new {@link ByteVector ByteVector} with the given initial size.
*
* @param initialSize the initial size of the byte vector to be constructed.
*/
public ByteVector(final int initialSize) {
data = new byte[initialSize];
}
/**
* Constructs a new {@link ByteVector ByteVector} with the given initial size.
*
* @param initialSize the initial size of the byte vector to be constructed.
*/
public ByteVector(final int initialSize) {
data = new byte[initialSize];
}
/**
* Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b a byte.
* @return this byte vector.
*/
public ByteVector putByte(final int b) {
int length = this.length;
if (length + 1 > data.length) {
enlarge(1);
}
data[length++] = (byte) b;
this.length = length;
return this;
}
/**
* Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b a byte.
* @return this byte vector.
*/
public ByteVector putByte(final int b) {
int length = this.length;
if (length + 1 > data.length) {
enlarge(1);
}
data[length++] = (byte) b;
this.length = length;
return this;
}
/**
* Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b1 a byte.
* @param b2 another byte.
* @return this byte vector.
*/
ByteVector put11(final int b1, final int b2) {
int length = this.length;
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte) b1;
data[length++] = (byte) b2;
this.length = length;
return this;
}
/**
* Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b1 a byte.
* @param b2 another byte.
* @return this byte vector.
*/
ByteVector put11(final int b1, final int b2) {
int length = this.length;
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte) b1;
data[length++] = (byte) b2;
this.length = length;
return this;
}
/**
* Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param s a short.
* @return this byte vector.
*/
public ByteVector putShort(final int s) {
int length = this.length;
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte) (s >>> 8);
data[length++] = (byte) s;
this.length = length;
return this;
}
/**
* Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param s a short.
* @return this byte vector.
*/
public ByteVector putShort(final int s) {
int length = this.length;
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte) (s >>> 8);
data[length++] = (byte) s;
this.length = length;
return this;
}
/**
* Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b a byte.
* @param s a short.
* @return this byte vector.
*/
ByteVector put12(final int b, final int s) {
int length = this.length;
if (length + 3 > data.length) {
enlarge(3);
}
byte[] data = this.data;
data[length++] = (byte) b;
data[length++] = (byte) (s >>> 8);
data[length++] = (byte) s;
this.length = length;
return this;
}
/**
* Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b a byte.
* @param s a short.
* @return this byte vector.
*/
ByteVector put12(final int b, final int s) {
int length = this.length;
if (length + 3 > data.length) {
enlarge(3);
}
byte[] data = this.data;
data[length++] = (byte) b;
data[length++] = (byte) (s >>> 8);
data[length++] = (byte) s;
this.length = length;
return this;
}
/**
* Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param i an int.
* @return this byte vector.
*/
public ByteVector putInt(final int i) {
int length = this.length;
if (length + 4 > data.length) {
enlarge(4);
}
byte[] data = this.data;
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
this.length = length;
return this;
}
/**
* Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param i an int.
* @return this byte vector.
*/
public ByteVector putInt(final int i) {
int length = this.length;
if (length + 4 > data.length) {
enlarge(4);
}
byte[] data = this.data;
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
this.length = length;
return this;
}
/**
* Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param l a long.
* @return this byte vector.
*/
public ByteVector putLong(final long l) {
int length = this.length;
if (length + 8 > data.length) {
enlarge(8);
}
byte[] data = this.data;
int i = (int) (l >>> 32);
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
i = (int) l;
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
this.length = length;
return this;
}
/**
* Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param l a long.
* @return this byte vector.
*/
public ByteVector putLong(final long l) {
int length = this.length;
if (length + 8 > data.length) {
enlarge(8);
}
byte[] data = this.data;
int i = (int) (l >>> 32);
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
i = (int) l;
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
this.length = length;
return this;
}
/**
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param s a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
public ByteVector putUTF8(final String s) {
int charLength = s.length();
if (charLength > 65535) {
throw new IllegalArgumentException();
}
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
}
byte[] data = this.data;
// optimistic algorithm: instead of computing the byte length and then
// serializing the string (which requires two loops), we assume the byte
// length is equal to char length (which is the most frequent case), and
// we start serializing the string right away. During the serialization,
// if we find that this assumption is wrong, we continue with the
// general method.
data[len++] = (byte) (charLength >>> 8);
data[len++] = (byte) charLength;
for (int i = 0; i < charLength; ++i) {
char c = s.charAt(i);
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else {
length = len;
return encodeUTF8(s, i, 65535);
}
}
length = len;
return this;
}
/**
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param s a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
public ByteVector putUTF8(final String s) {
int charLength = s.length();
if (charLength > 65535) {
throw new IllegalArgumentException();
}
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
}
byte[] data = this.data;
// optimistic algorithm: instead of computing the byte length and then
// serializing the string (which requires two loops), we assume the byte
// length is equal to char length (which is the most frequent case), and
// we start serializing the string right away. During the serialization,
// if we find that this assumption is wrong, we continue with the
// general method.
data[len++] = (byte) (charLength >>> 8);
data[len++] = (byte) charLength;
for (int i = 0; i < charLength; ++i) {
char c = s.charAt(i);
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else {
length = len;
return encodeUTF8(s, i, 65535);
}
}
length = len;
return this;
}
/**
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if necessary. The string
* length is encoded in two bytes before the encoded characters, if there is space for that (i.e. if this.length - i
* - 2 >= 0).
*
* @param s the String to encode.
* @param i the index of the first character to encode. The previous characters are supposed to have already been
* encoded, using only one byte per character.
* @param maxByteLength the maximum byte length of the encoded string, including the already encoded characters.
* @return this byte vector.
*/
ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
int charLength = s.length();
int byteLength = i;
char c;
for (int j = i; j < charLength; ++j) {
c = s.charAt(j);
if (c >= '\001' && c <= '\177') {
byteLength++;
} else if (c > '\u07FF') {
byteLength += 3;
} else {
byteLength += 2;
}
}
if (byteLength > maxByteLength) {
throw new IllegalArgumentException();
}
int start = length - i - 2;
if (start >= 0) {
data[start] = (byte) (byteLength >>> 8);
data[start + 1] = (byte) byteLength;
}
if (length + byteLength - i > data.length) {
enlarge(byteLength - i);
}
int len = length;
for (int j = i; j < charLength; ++j) {
c = s.charAt(j);
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else if (c > '\u07FF') {
data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
data[len++] = (byte) (0x80 | c & 0x3F);
} else {
data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
data[len++] = (byte) (0x80 | c & 0x3F);
}
}
length = len;
return this;
}
/**
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if necessary. The string
* length is encoded in two bytes before the encoded characters, if there is space for that (i.e. if this.length - i
* - 2 >= 0).
*
* @param s the String to encode.
* @param i the index of the first character to encode. The previous characters are supposed to have already been
* encoded, using only one byte per character.
* @param maxByteLength the maximum byte length of the encoded string, including the already encoded characters.
* @return this byte vector.
*/
ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
int charLength = s.length();
int byteLength = i;
char c;
for (int j = i; j < charLength; ++j) {
c = s.charAt(j);
if (c >= '\001' && c <= '\177') {
byteLength++;
} else if (c > '\u07FF') {
byteLength += 3;
} else {
byteLength += 2;
}
}
if (byteLength > maxByteLength) {
throw new IllegalArgumentException();
}
int start = length - i - 2;
if (start >= 0) {
data[start] = (byte) (byteLength >>> 8);
data[start + 1] = (byte) byteLength;
}
if (length + byteLength - i > data.length) {
enlarge(byteLength - i);
}
int len = length;
for (int j = i; j < charLength; ++j) {
c = s.charAt(j);
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else if (c > '\u07FF') {
data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
data[len++] = (byte) (0x80 | c & 0x3F);
} else {
data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
data[len++] = (byte) (0x80 | c & 0x3F);
}
}
length = len;
return this;
}
/**
* Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b an array of bytes. May be &#60;tt&#62;null&#60;/tt&#62; to put &#60;tt&#62;len&#60;/tt&#62; null bytes
* into this byte vector.
* @param off index of the fist byte of b that must be copied.
* @param len number of bytes of b that must be copied.
* @return this byte vector.
*/
public ByteVector putByteArray(final byte[] b, final int off, final int len) {
if (length + len > data.length) {
enlarge(len);
}
if (b != null) {
System.arraycopy(b, off, data, length, len);
}
length += len;
return this;
}
/**
* Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param b an array of bytes. May be &#60;tt&#62;null&#60;/tt&#62; to put &#60;tt&#62;len&#60;/tt&#62; null bytes
* into this byte vector.
* @param off index of the fist byte of b that must be copied.
* @param len number of bytes of b that must be copied.
* @return this byte vector.
*/
public ByteVector putByteArray(final byte[] b, final int off, final int len) {
if (length + len > data.length) {
enlarge(len);
}
if (b != null) {
System.arraycopy(b, off, data, length, len);
}
length += len;
return this;
}
/**
* Enlarge this byte vector so that it can receive n more bytes.
*
* @param size number of additional bytes that this byte vector should be able to receive.
*/
private void enlarge(final int size) {
int length1 = 2 * data.length;
int length2 = length + size;
byte[] newData = new byte[length1 > length2 ? length1 : length2];
System.arraycopy(data, 0, newData, 0, length);
data = newData;
}
/**
* Enlarge this byte vector so that it can receive n more bytes.
*
* @param size number of additional bytes that this byte vector should be able to receive.
*/
private void enlarge(final int size) {
int length1 = 2 * data.length;
int length2 = length + size;
byte[] newData = new byte[length1 > length2 ? length1 : length2];
System.arraycopy(data, 0, newData, 0, length);
data = newData;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -70,223 +70,223 @@ package org.redkale.asm;
*/
public abstract class ClassVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
/**
* The ASM API version implemented by this visitor. The value of this field must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
/** The class visitor to which this visitor must delegate method calls. May be null. */
protected ClassVisitor cv;
/** The class visitor to which this visitor must delegate method calls. May be null. */
protected ClassVisitor cv;
/**
* Constructs a new {@link ClassVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public ClassVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link ClassVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public ClassVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link ClassVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param cv the class visitor to which this visitor must delegate method calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
this.api = api;
this.cv = cv;
}
/**
* Constructs a new {@link ClassVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param cv the class visitor to which this visitor must delegate method calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
this.api = api;
this.cv = cv;
}
/**
* Visits the header of the class.
*
* @param version the class version.
* @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if the class is
* deprecated.
* @param name the internal name of the class (see {@link Type#getInternalName() getInternalName}).
* @param signature the signature of this class. May be &#60;tt&#62;null&#60;/tt&#62; if the class is not a generic
* one, and does not extend or implement generic classes or interfaces.
* @param superName the internal of name of the super class (see {@link Type#getInternalName() getInternalName}).
* For interfaces, the super class is {@link Object}. May be &#60;tt&#62;null&#60;/tt&#62;, but only for the
* {@link Object} class.
* @param interfaces the internal names of the class's interfaces (see {@link Type#getInternalName()
* getInternalName}). May be &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (cv != null) {
cv.visit(version, access, name, signature, superName, interfaces);
}
}
/**
* Visits the header of the class.
*
* @param version the class version.
* @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if the class is
* deprecated.
* @param name the internal name of the class (see {@link Type#getInternalName() getInternalName}).
* @param signature the signature of this class. May be &#60;tt&#62;null&#60;/tt&#62; if the class is not a generic
* one, and does not extend or implement generic classes or interfaces.
* @param superName the internal of name of the super class (see {@link Type#getInternalName() getInternalName}).
* For interfaces, the super class is {@link Object}. May be &#60;tt&#62;null&#60;/tt&#62;, but only for the
* {@link Object} class.
* @param interfaces the internal names of the class's interfaces (see {@link Type#getInternalName()
* getInternalName}). May be &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (cv != null) {
cv.visit(version, access, name, signature, superName, interfaces);
}
}
/**
* Visits the source of the class.
*
* @param source the name of the source file from which the class was compiled. May be
* &#60;tt&#62;null&#60;/tt&#62;.
* @param debug additional debug information to compute the correspondance between source and compiled elements of
* the class. May be &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visitSource(String source, String debug) {
if (cv != null) {
cv.visitSource(source, debug);
}
}
/**
* Visits the source of the class.
*
* @param source the name of the source file from which the class was compiled. May be
* &#60;tt&#62;null&#60;/tt&#62;.
* @param debug additional debug information to compute the correspondance between source and compiled elements of
* the class. May be &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visitSource(String source, String debug) {
if (cv != null) {
cv.visitSource(source, debug);
}
}
/**
* Visit the module corresponding to the class.
*
* @param name module name
* @param access module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* @param version module version or null.
* @return a visitor to visit the module values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not interested
* in visiting this module.
*/
public ModuleVisitor visitModule(String name, int access, String version) {
if (api < Opcodes.ASM6) {
throw new RuntimeException();
}
if (cv != null) {
return cv.visitModule(name, access, version);
}
return null;
}
/**
* Visit the module corresponding to the class.
*
* @param name module name
* @param access module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* @param version module version or null.
* @return a visitor to visit the module values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not interested
* in visiting this module.
*/
public ModuleVisitor visitModule(String name, int access, String version) {
if (api < Opcodes.ASM6) {
throw new RuntimeException();
}
if (cv != null) {
return cv.visitModule(name, access, version);
}
return null;
}
/**
* Visits the enclosing class of the class. This method must be called only if the class has an enclosing class.
*
* @param owner internal name of the enclosing class of the class.
* @param name the name of the method that contains the class, or &#60;tt&#62;null&#60;/tt&#62; if the class is not
* enclosed in a method of its enclosing class.
* @param desc the descriptor of the method that contains the class, or &#60;tt&#62;null&#60;/tt&#62; if the class
* is not enclosed in a method of its enclosing class.
*/
public void visitOuterClass(String owner, String name, String desc) {
if (cv != null) {
cv.visitOuterClass(owner, name, desc);
}
}
/**
* Visits the enclosing class of the class. This method must be called only if the class has an enclosing class.
*
* @param owner internal name of the enclosing class of the class.
* @param name the name of the method that contains the class, or &#60;tt&#62;null&#60;/tt&#62; if the class is not
* enclosed in a method of its enclosing class.
* @param desc the descriptor of the method that contains the class, or &#60;tt&#62;null&#60;/tt&#62; if the class
* is not enclosed in a method of its enclosing class.
*/
public void visitOuterClass(String owner, String name, String desc) {
if (cv != null) {
cv.visitOuterClass(owner, name, desc);
}
}
/**
* Visits an annotation of the class.
*
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (cv != null) {
return cv.visitAnnotation(desc, visible);
}
return null;
}
/**
* Visits an annotation of the class.
*
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (cv != null) {
return cv.visitAnnotation(desc, visible);
}
return null;
}
/**
* Visits an annotation on a type in the class signature.
*
* @param typeRef a reference to the annotated type. The sort of this type reference must be
* {@link TypeReference#CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
* {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
* {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See {@link TypeReference}.
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or static inner type
* within 'typeRef'. May be &#60;tt&#62;null&#60;/tt&#62; if the annotation targets 'typeRef' as a whole.
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
if (cv != null) {
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits an annotation on a type in the class signature.
*
* @param typeRef a reference to the annotated type. The sort of this type reference must be
* {@link TypeReference#CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
* {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
* {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See {@link TypeReference}.
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or static inner type
* within 'typeRef'. May be &#60;tt&#62;null&#60;/tt&#62; if the annotation targets 'typeRef' as a whole.
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
if (cv != null) {
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits a non standard attribute of the class.
*
* @param attr an attribute.
*/
public void visitAttribute(Attribute attr) {
if (cv != null) {
cv.visitAttribute(attr);
}
}
/**
* Visits a non standard attribute of the class.
*
* @param attr an attribute.
*/
public void visitAttribute(Attribute attr) {
if (cv != null) {
cv.visitAttribute(attr);
}
}
/**
* Visits information about an inner class. This inner class is not necessarily a member of the class being visited.
*
* @param name the internal name of an inner class (see {@link Type#getInternalName() getInternalName}).
* @param outerName the internal name of the class to which the inner class belongs (see
* {@link Type#getInternalName() getInternalName}). May be &#60;tt&#62;null&#60;/tt&#62; for not member classes.
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
* &#60;tt&#62;null&#60;/tt&#62; for anonymous inner classes.
* @param access the access flags of the inner class as originally declared in the enclosing class.
*/
public void visitInnerClass(String name, String outerName, String innerName, int access) {
if (cv != null) {
cv.visitInnerClass(name, outerName, innerName, access);
}
}
/**
* Visits information about an inner class. This inner class is not necessarily a member of the class being visited.
*
* @param name the internal name of an inner class (see {@link Type#getInternalName() getInternalName}).
* @param outerName the internal name of the class to which the inner class belongs (see
* {@link Type#getInternalName() getInternalName}). May be &#60;tt&#62;null&#60;/tt&#62; for not member classes.
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
* &#60;tt&#62;null&#60;/tt&#62; for anonymous inner classes.
* @param access the access flags of the inner class as originally declared in the enclosing class.
*/
public void visitInnerClass(String name, String outerName, String innerName, int access) {
if (cv != null) {
cv.visitInnerClass(name, outerName, innerName, access);
}
}
/**
* Visits a field of the class.
*
* @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if the field is
* synthetic and/or deprecated.
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type Type}).
* @param signature the field's signature. May be &#60;tt&#62;null&#60;/tt&#62; if the field's type does not use
* generic types.
* @param value the field's initial value. This parameter, which may be &#60;tt&#62;null&#60;/tt&#62; if the field
* does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}
* or a {@link String} (for &#60;tt&#62;int&#60;/tt&#62;, &#60;tt&#62;float&#60;/tt&#62;,
* &#60;tt&#62;long&#60;/tt&#62; or &#60;tt&#62;String&#60;/tt&#62; fields respectively). <i>This parameter is
* only used for static fields</i>. Its value is ignored for non static fields, which must be initialized
* through bytecode instructions in constructors or methods.
* @return a visitor to visit field annotations and attributes, or &#60;tt&#62;null&#60;/tt&#62; if this class
* visitor is not interested in visiting these annotations and attributes.
*/
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
if (cv != null) {
return cv.visitField(access, name, desc, signature, value);
}
return null;
}
/**
* Visits a field of the class.
*
* @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if the field is
* synthetic and/or deprecated.
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type Type}).
* @param signature the field's signature. May be &#60;tt&#62;null&#60;/tt&#62; if the field's type does not use
* generic types.
* @param value the field's initial value. This parameter, which may be &#60;tt&#62;null&#60;/tt&#62; if the field
* does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}
* or a {@link String} (for &#60;tt&#62;int&#60;/tt&#62;, &#60;tt&#62;float&#60;/tt&#62;,
* &#60;tt&#62;long&#60;/tt&#62; or &#60;tt&#62;String&#60;/tt&#62; fields respectively). <i>This parameter is
* only used for static fields</i>. Its value is ignored for non static fields, which must be initialized
* through bytecode instructions in constructors or methods.
* @return a visitor to visit field annotations and attributes, or &#60;tt&#62;null&#60;/tt&#62; if this class
* visitor is not interested in visiting these annotations and attributes.
*/
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
if (cv != null) {
return cv.visitField(access, name, desc, signature, value);
}
return null;
}
/**
* Visits a method of the class. This method <i>must</i> return a new {@link MethodVisitor} instance (or
* &#60;tt&#62;null&#60;/tt&#62;) each time it is called, i.e., it should not return a previously returned visitor.
*
* @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if the method is
* synthetic and/or deprecated.
* @param name the method's name.
* @param desc the method's descriptor (see {@link Type Type}).
* @param signature the method's signature. May be &#60;tt&#62;null&#60;/tt&#62; if the method parameters, return
* type and exceptions do not use generic types.
* @param exceptions the internal names of the method's exception classes (see {@link Type#getInternalName()
* getInternalName}). May be &#60;tt&#62;null&#60;/tt&#62;.
* @return an object to visit the byte code of the method, or &#60;tt&#62;null&#60;/tt&#62; if this class visitor is
* not interested in visiting the code of this method.
*/
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (cv != null) {
return cv.visitMethod(access, name, desc, signature, exceptions);
}
return null;
}
/**
* Visits a method of the class. This method <i>must</i> return a new {@link MethodVisitor} instance (or
* &#60;tt&#62;null&#60;/tt&#62;) each time it is called, i.e., it should not return a previously returned visitor.
*
* @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if the method is
* synthetic and/or deprecated.
* @param name the method's name.
* @param desc the method's descriptor (see {@link Type Type}).
* @param signature the method's signature. May be &#60;tt&#62;null&#60;/tt&#62; if the method parameters, return
* type and exceptions do not use generic types.
* @param exceptions the internal names of the method's exception classes (see {@link Type#getInternalName()
* getInternalName}). May be &#60;tt&#62;null&#60;/tt&#62;.
* @return an object to visit the byte code of the method, or &#60;tt&#62;null&#60;/tt&#62; if this class visitor is
* not interested in visiting the code of this method.
*/
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (cv != null) {
return cv.visitMethod(access, name, desc, signature, exceptions);
}
return null;
}
/**
* Visits the end of the class. This method, which is the last one to be called, is used to inform the visitor that
* all the fields and methods of the class have been visited.
*/
public void visitEnd() {
if (cv != null) {
cv.visitEnd();
}
}
/**
* Visits the end of the class. This method, which is the last one to be called, is used to inform the visitor that
* all the fields and methods of the class have been visited.
*/
public void visitEnd() {
if (cv != null) {
cv.visitEnd();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -66,78 +66,78 @@ package org.redkale.asm;
*/
class Context {
/** Prototypes of the attributes that must be parsed for this class. */
Attribute[] attrs;
/** Prototypes of the attributes that must be parsed for this class. */
Attribute[] attrs;
/** The {@link ClassReader} option flags for the parsing of this class. */
int flags;
/** The {@link ClassReader} option flags for the parsing of this class. */
int flags;
/** The buffer used to read strings. */
char[] buffer;
/** The buffer used to read strings. */
char[] buffer;
/** The start index of each bootstrap method. */
int[] bootstrapMethods;
/** The start index of each bootstrap method. */
int[] bootstrapMethods;
/** The access flags of the method currently being parsed. */
int access;
/** The access flags of the method currently being parsed. */
int access;
/** The name of the method currently being parsed. */
String name;
/** The name of the method currently being parsed. */
String name;
/** The descriptor of the method currently being parsed. */
String desc;
/** The descriptor of the method currently being parsed. */
String desc;
/**
* The label objects, indexed by bytecode offset, of the method currently being parsed (only bytecode offsets for
* which a label is needed have a non null associated Label object).
*/
Label[] labels;
/**
* The label objects, indexed by bytecode offset, of the method currently being parsed (only bytecode offsets for
* which a label is needed have a non null associated Label object).
*/
Label[] labels;
/** The target of the type annotation currently being parsed. */
int typeRef;
/** The target of the type annotation currently being parsed. */
int typeRef;
/** The path of the type annotation currently being parsed. */
TypePath typePath;
/** The path of the type annotation currently being parsed. */
TypePath typePath;
/** The offset of the latest stack map frame that has been parsed. */
int offset;
/** The offset of the latest stack map frame that has been parsed. */
int offset;
/**
* The labels corresponding to the start of the local variable ranges in the local variable type annotation
* currently being parsed.
*/
Label[] start;
/**
* The labels corresponding to the start of the local variable ranges in the local variable type annotation
* currently being parsed.
*/
Label[] start;
/**
* The labels corresponding to the end of the local variable ranges in the local variable type annotation currently
* being parsed.
*/
Label[] end;
/**
* The labels corresponding to the end of the local variable ranges in the local variable type annotation currently
* being parsed.
*/
Label[] end;
/**
* The local variable indices for each local variable range in the local variable type annotation currently being
* parsed.
*/
int[] index;
/**
* The local variable indices for each local variable range in the local variable type annotation currently being
* parsed.
*/
int[] index;
/** The encoding of the latest stack map frame that has been parsed. */
int mode;
/** The encoding of the latest stack map frame that has been parsed. */
int mode;
/** The number of locals in the latest stack map frame that has been parsed. */
int localCount;
/** The number of locals in the latest stack map frame that has been parsed. */
int localCount;
/**
* The number locals in the latest stack map frame that has been parsed, minus the number of locals in the previous
* frame.
*/
int localDiff;
/**
* The number locals in the latest stack map frame that has been parsed, minus the number of locals in the previous
* frame.
*/
int localDiff;
/** The local values of the latest stack map frame that has been parsed. */
Object[] local;
/** The local values of the latest stack map frame that has been parsed. */
Object[] local;
/** The stack size of the latest stack map frame that has been parsed. */
int stackCount;
/** The stack size of the latest stack map frame that has been parsed. */
int stackCount;
/** The stack values of the latest stack map frame that has been parsed. */
Object[] stack;
/** The stack values of the latest stack map frame that has been parsed. */
Object[] stack;
}

View File

@@ -67,17 +67,17 @@ package org.redkale.asm;
*/
class CurrentFrame extends Frame {
/**
* Sets this CurrentFrame to the input stack map frame of the next "current" instruction, i.e. the instruction just
* after the given one. It is assumed that the value of this object when this method is called is the stack map
* frame status just before the given instruction is executed.
*/
@Override
void execute(int opcode, int arg, ClassWriter cw, Item item) {
super.execute(opcode, arg, cw, item);
Frame successor = new Frame();
merge(cw, successor, 0);
set(successor);
owner.inputStackTop = 0;
}
/**
* Sets this CurrentFrame to the input stack map frame of the next "current" instruction, i.e. the instruction just
* after the given one. It is assumed that the value of this object when this method is called is the stack map
* frame status just before the given instruction is executed.
*/
@Override
void execute(int opcode, int arg, ClassWriter cw, Item item) {
super.execute(opcode, arg, cw, item);
Frame successor = new Frame();
merge(cw, successor, 0);
set(successor);
owner.inputStackTop = 0;
}
}

View File

@@ -65,30 +65,30 @@ package org.redkale.asm;
*/
class Edge {
/** Denotes a normal control flow graph edge. */
static final int NORMAL = 0;
/** Denotes a normal control flow graph edge. */
static final int NORMAL = 0;
/**
* Denotes a control flow graph edge corresponding to an exception handler. More precisely any {@link Edge} whose
* {@link #info} is strictly positive corresponds to an exception handler. The actual value of {@link #info} is the
* index, in the {@link ClassWriter} type table, of the exception that is catched.
*/
static final int EXCEPTION = 0x7FFFFFFF;
/**
* Denotes a control flow graph edge corresponding to an exception handler. More precisely any {@link Edge} whose
* {@link #info} is strictly positive corresponds to an exception handler. The actual value of {@link #info} is the
* index, in the {@link ClassWriter} type table, of the exception that is catched.
*/
static final int EXCEPTION = 0x7FFFFFFF;
/**
* Information about this control flow graph edge. If {@link ClassWriter#COMPUTE_MAXS} is used this field is the
* (relative) stack size in the basic block from which this edge originates. This size is equal to the stack size at
* the "jump" instruction to which this edge corresponds, relatively to the stack size at the beginning of the
* originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, this field is the kind of this control
* flow graph edge (i.e. NORMAL or EXCEPTION).
*/
int info;
/**
* Information about this control flow graph edge. If {@link ClassWriter#COMPUTE_MAXS} is used this field is the
* (relative) stack size in the basic block from which this edge originates. This size is equal to the stack size at
* the "jump" instruction to which this edge corresponds, relatively to the stack size at the beginning of the
* originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, this field is the kind of this control
* flow graph edge (i.e. NORMAL or EXCEPTION).
*/
int info;
/** The successor block of the basic block from which this edge originates. */
Label successor;
/** The successor block of the basic block from which this edge originates. */
Label successor;
/**
* The next edge in the list of successors of the originating basic block. See {@link Label#successors successors}.
*/
Edge next;
/**
* The next edge in the list of successors of the originating basic block. See {@link Label#successors successors}.
*/
Edge next;
}

View File

@@ -67,89 +67,89 @@ package org.redkale.asm;
*/
public abstract class FieldVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
/**
* The ASM API version implemented by this visitor. The value of this field must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
/** The field visitor to which this visitor must delegate method calls. May be null. */
protected FieldVisitor fv;
/** The field visitor to which this visitor must delegate method calls. May be null. */
protected FieldVisitor fv;
/**
* Constructs a new {@link FieldVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public FieldVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link FieldVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public FieldVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link FieldVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param fv the field visitor to which this visitor must delegate method calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
this.api = api;
this.fv = fv;
}
/**
* Constructs a new {@link FieldVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param fv the field visitor to which this visitor must delegate method calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
this.api = api;
this.fv = fv;
}
/**
* Visits an annotation of the field.
*
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (fv != null) {
return fv.visitAnnotation(desc, visible);
}
return null;
}
/**
* Visits an annotation of the field.
*
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (fv != null) {
return fv.visitAnnotation(desc, visible);
}
return null;
}
/**
* Visits an annotation on the type of the field.
*
* @param typeRef a reference to the annotated type. The sort of this type reference must be
* {@link TypeReference#FIELD FIELD}. See {@link TypeReference}.
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or static inner type
* within 'typeRef'. May be &#60;tt&#62;null&#60;/tt&#62; if the annotation targets 'typeRef' as a whole.
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
if (fv != null) {
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits an annotation on the type of the field.
*
* @param typeRef a reference to the annotated type. The sort of this type reference must be
* {@link TypeReference#FIELD FIELD}. See {@link TypeReference}.
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or static inner type
* within 'typeRef'. May be &#60;tt&#62;null&#60;/tt&#62; if the annotation targets 'typeRef' as a whole.
* @param desc the class descriptor of the annotation class.
* @param visible &#60;tt&#62;true&#60;/tt&#62; if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or &#60;tt&#62;null&#60;/tt&#62; if this visitor is not
* interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
if (fv != null) {
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits a non standard attribute of the field.
*
* @param attr an attribute.
*/
public void visitAttribute(Attribute attr) {
if (fv != null) {
fv.visitAttribute(attr);
}
}
/**
* Visits a non standard attribute of the field.
*
* @param attr an attribute.
*/
public void visitAttribute(Attribute attr) {
if (fv != null) {
fv.visitAttribute(attr);
}
}
/**
* Visits the end of the field. This method, which is the last one to be called, is used to inform the visitor that
* all the annotations and attributes of the field have been visited.
*/
public void visitEnd() {
if (fv != null) {
fv.visitEnd();
}
}
/**
* Visits the end of the field. This method, which is the last one to be called, is used to inform the visitor that
* all the annotations and attributes of the field have been visited.
*/
public void visitEnd() {
if (fv != null) {
fv.visitEnd();
}
}
}

View File

@@ -65,256 +65,256 @@ package org.redkale.asm;
*/
final class FieldWriter extends FieldVisitor {
/** The class writer to which this field must be added. */
private final ClassWriter cw;
/** The class writer to which this field must be added. */
private final ClassWriter cw;
/** Access flags of this field. */
private final int access;
/** Access flags of this field. */
private final int access;
/** The index of the constant pool item that contains the name of this method. */
private final int name;
/** The index of the constant pool item that contains the name of this method. */
private final int name;
/** The index of the constant pool item that contains the descriptor of this field. */
private final int desc;
/** The index of the constant pool item that contains the descriptor of this field. */
private final int desc;
/** The index of the constant pool item that contains the signature of this field. */
private int signature;
/** The index of the constant pool item that contains the signature of this field. */
private int signature;
/** The index of the constant pool item that contains the constant value of this field. */
private int value;
/** The index of the constant pool item that contains the constant value of this field. */
private int value;
/** The runtime visible annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter anns;
/** The runtime visible annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter anns;
/** The runtime invisible annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter ianns;
/** The runtime invisible annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter ianns;
/** The runtime visible type annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter tanns;
/** The runtime visible type annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter tanns;
/** The runtime invisible type annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter itanns;
/** The runtime invisible type annotations of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private AnnotationWriter itanns;
/** The non standard attributes of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private Attribute attrs;
/** The non standard attributes of this field. May be &#60;tt&#62;null&#60;/tt&#62;. */
private Attribute attrs;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
/**
* Constructs a new {@link FieldWriter}.
*
* @param cw the class writer to which this field must be added.
* @param access the field's access flags (see {@link Opcodes}).
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type}).
* @param signature the field's signature. May be &#60;tt&#62;null&#60;/tt&#62;.
* @param value the field's constant value. May be &#60;tt&#62;null&#60;/tt&#62;.
*/
FieldWriter(
final ClassWriter cw,
final int access,
final String name,
final String desc,
final String signature,
final Object value) {
super(Opcodes.ASM6);
if (cw.firstField == null) {
cw.firstField = this;
} else {
cw.lastField.fv = this;
}
cw.lastField = this;
this.cw = cw;
this.access = access;
this.name = cw.newUTF8(name);
this.desc = cw.newUTF8(desc);
if (signature != null) {
this.signature = cw.newUTF8(signature);
}
if (value != null) {
this.value = cw.newConstItem(value).index;
}
}
/**
* Constructs a new {@link FieldWriter}.
*
* @param cw the class writer to which this field must be added.
* @param access the field's access flags (see {@link Opcodes}).
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type}).
* @param signature the field's signature. May be &#60;tt&#62;null&#60;/tt&#62;.
* @param value the field's constant value. May be &#60;tt&#62;null&#60;/tt&#62;.
*/
FieldWriter(
final ClassWriter cw,
final int access,
final String name,
final String desc,
final String signature,
final Object value) {
super(Opcodes.ASM6);
if (cw.firstField == null) {
cw.firstField = this;
} else {
cw.lastField.fv = this;
}
cw.lastField = this;
this.cw = cw;
this.access = access;
this.name = cw.newUTF8(name);
this.desc = cw.newUTF8(desc);
if (signature != null) {
this.signature = cw.newUTF8(signature);
}
if (value != null) {
this.value = cw.newConstItem(value).index;
}
}
// ------------------------------------------------------------------------
// Implementation of the FieldVisitor abstract class
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Implementation of the FieldVisitor abstract class
// ------------------------------------------------------------------------
@Override
public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
ByteVector bv = new ByteVector();
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
if (visible) {
aw.next = anns;
anns = aw;
} else {
aw.next = ianns;
ianns = aw;
}
return aw;
}
@Override
public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
ByteVector bv = new ByteVector();
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
if (visible) {
aw.next = anns;
anns = aw;
} else {
aw.next = ianns;
ianns = aw;
}
return aw;
}
@Override
public AnnotationVisitor visitTypeAnnotation(
final int typeRef, final TypePath typePath, final String desc, final boolean visible) {
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
if (visible) {
aw.next = tanns;
tanns = aw;
} else {
aw.next = itanns;
itanns = aw;
}
return aw;
}
@Override
public AnnotationVisitor visitTypeAnnotation(
final int typeRef, final TypePath typePath, final String desc, final boolean visible) {
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
if (visible) {
aw.next = tanns;
tanns = aw;
} else {
aw.next = itanns;
itanns = aw;
}
return aw;
}
@Override
public void visitAttribute(final Attribute attr) {
attr.next = attrs;
attrs = attr;
}
@Override
public void visitAttribute(final Attribute attr) {
attr.next = attrs;
attrs = attr;
}
@Override
public void visitEnd() {
// do nothing
}
@Override
public void visitEnd() {
// do nothing
}
// ------------------------------------------------------------------------
// Utility methods
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Utility methods
// ------------------------------------------------------------------------
/**
* Returns the size of this field.
*
* @return the size of this field.
*/
int getSize() {
int size = 8;
if (value != 0) {
cw.newUTF8("ConstantValue");
size += 8;
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
cw.newUTF8("Synthetic");
size += 6;
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
size += 6;
}
if (signature != 0) {
cw.newUTF8("Signature");
size += 8;
}
if (anns != null) {
cw.newUTF8("RuntimeVisibleAnnotations");
size += 8 + anns.getSize();
}
if (ianns != null) {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
if (tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize();
}
if (itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize();
}
if (attrs != null) {
size += attrs.getSize(cw, null, 0, -1, -1);
}
return size;
}
/**
* Returns the size of this field.
*
* @return the size of this field.
*/
int getSize() {
int size = 8;
if (value != 0) {
cw.newUTF8("ConstantValue");
size += 8;
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
cw.newUTF8("Synthetic");
size += 6;
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
size += 6;
}
if (signature != 0) {
cw.newUTF8("Signature");
size += 8;
}
if (anns != null) {
cw.newUTF8("RuntimeVisibleAnnotations");
size += 8 + anns.getSize();
}
if (ianns != null) {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
if (tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize();
}
if (itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize();
}
if (attrs != null) {
size += attrs.getSize(cw, null, 0, -1, -1);
}
return size;
}
/**
* Puts the content of this field into the given byte vector.
*
* @param out where the content of this field must be put.
*/
void put(final ByteVector out) {
final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
int mask = Opcodes.ACC_DEPRECATED
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
| ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
int attributeCount = 0;
if (value != 0) {
++attributeCount;
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
++attributeCount;
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
}
if (signature != 0) {
++attributeCount;
}
if (anns != null) {
++attributeCount;
}
if (ianns != null) {
++attributeCount;
}
if (tanns != null) {
++attributeCount;
}
if (itanns != null) {
++attributeCount;
}
if (attrs != null) {
attributeCount += attrs.getCount();
}
out.putShort(attributeCount);
if (value != 0) {
out.putShort(cw.newUTF8("ConstantValue"));
out.putInt(2).putShort(value);
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
out.putShort(cw.newUTF8("Synthetic")).putInt(0);
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
}
if (signature != 0) {
out.putShort(cw.newUTF8("Signature"));
out.putInt(2).putShort(signature);
}
if (anns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
anns.put(out);
}
if (ianns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
}
}
/**
* Puts the content of this field into the given byte vector.
*
* @param out where the content of this field must be put.
*/
void put(final ByteVector out) {
final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
int mask = Opcodes.ACC_DEPRECATED
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
| ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
int attributeCount = 0;
if (value != 0) {
++attributeCount;
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
++attributeCount;
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
}
if (signature != 0) {
++attributeCount;
}
if (anns != null) {
++attributeCount;
}
if (ianns != null) {
++attributeCount;
}
if (tanns != null) {
++attributeCount;
}
if (itanns != null) {
++attributeCount;
}
if (attrs != null) {
attributeCount += attrs.getCount();
}
out.putShort(attributeCount);
if (value != 0) {
out.putShort(cw.newUTF8("ConstantValue"));
out.putInt(2).putShort(value);
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
out.putShort(cw.newUTF8("Synthetic")).putInt(0);
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
}
if (signature != 0) {
out.putShort(cw.newUTF8("Signature"));
out.putInt(2).putShort(signature);
}
if (anns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
anns.put(out);
}
if (ianns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -67,124 +67,124 @@ package org.redkale.asm;
*/
public final class Handle {
/**
* The kind of field or method designated by this Handle. Should be {@link Opcodes#H_GETFIELD},
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
*/
final int tag;
/**
* The kind of field or method designated by this Handle. Should be {@link Opcodes#H_GETFIELD},
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
*/
final int tag;
/** The internal name of the class that owns the field or method designated by this handle. */
final String owner;
/** The internal name of the class that owns the field or method designated by this handle. */
final String owner;
/** The name of the field or method designated by this handle. */
final String name;
/** The name of the field or method designated by this handle. */
final String name;
/** The descriptor of the field or method designated by this handle. */
final String desc;
/** The descriptor of the field or method designated by this handle. */
final String desc;
/** Indicate if the owner is an interface or not. */
final boolean itf;
/** Indicate if the owner is an interface or not. */
final boolean itf;
/**
* Constructs a new field or method handle.
*
* @param tag the kind of field or method designated by this Handle. Must be {@link Opcodes#H_GETFIELD},
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the class that owns the field or method designated by this handle.
* @param name the name of the field or method designated by this handle.
* @param desc the descriptor of the field or method designated by this handle.
* @param itf true if the owner is an interface.
*/
public Handle(int tag, String owner, String name, String desc, boolean itf) {
this.tag = tag;
this.owner = owner;
this.name = name;
this.desc = desc;
this.itf = itf;
}
/**
* Constructs a new field or method handle.
*
* @param tag the kind of field or method designated by this Handle. Must be {@link Opcodes#H_GETFIELD},
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the class that owns the field or method designated by this handle.
* @param name the name of the field or method designated by this handle.
* @param desc the descriptor of the field or method designated by this handle.
* @param itf true if the owner is an interface.
*/
public Handle(int tag, String owner, String name, String desc, boolean itf) {
this.tag = tag;
this.owner = owner;
this.name = name;
this.desc = desc;
this.itf = itf;
}
/**
* Returns the kind of field or method designated by this handle.
*
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
*/
public int getTag() {
return tag;
}
/**
* Returns the kind of field or method designated by this handle.
*
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
*/
public int getTag() {
return tag;
}
/**
* Returns the internal name of the class that owns the field or method designated by this handle.
*
* @return the internal name of the class that owns the field or method designated by this handle.
*/
public String getOwner() {
return owner;
}
/**
* Returns the internal name of the class that owns the field or method designated by this handle.
*
* @return the internal name of the class that owns the field or method designated by this handle.
*/
public String getOwner() {
return owner;
}
/**
* Returns the name of the field or method designated by this handle.
*
* @return the name of the field or method designated by this handle.
*/
public String getName() {
return name;
}
/**
* Returns the name of the field or method designated by this handle.
*
* @return the name of the field or method designated by this handle.
*/
public String getName() {
return name;
}
/**
* Returns the descriptor of the field or method designated by this handle.
*
* @return the descriptor of the field or method designated by this handle.
*/
public String getDesc() {
return desc;
}
/**
* Returns the descriptor of the field or method designated by this handle.
*
* @return the descriptor of the field or method designated by this handle.
*/
public String getDesc() {
return desc;
}
/**
* Returns true if the owner of the field or method designated by this handle is an interface.
*
* @return true if the owner of the field or method designated by this handle is an interface.
*/
public boolean isInterface() {
return itf;
}
/**
* Returns true if the owner of the field or method designated by this handle is an interface.
*
* @return true if the owner of the field or method designated by this handle is an interface.
*/
public boolean isInterface() {
return itf;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Handle)) {
return false;
}
Handle h = (Handle) obj;
return tag == h.tag && itf == h.itf && owner.equals(h.owner) && name.equals(h.name) && desc.equals(h.desc);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Handle)) {
return false;
}
Handle h = (Handle) obj;
return tag == h.tag && itf == h.itf && owner.equals(h.owner) && name.equals(h.name) && desc.equals(h.desc);
}
@Override
public int hashCode() {
return tag + (itf ? 64 : 0) + owner.hashCode() * name.hashCode() * desc.hashCode();
}
@Override
public int hashCode() {
return tag + (itf ? 64 : 0) + owner.hashCode() * name.hashCode() * desc.hashCode();
}
/**
* Returns the textual representation of this handle. The textual representation is:
*
* <pre>
* for a reference to a class:
* owner '.' name desc ' ' '(' tag ')'
* for a reference to an interface:
* owner '.' name desc ' ' '(' tag ' ' itf ')'
* </pre>
*
* . As this format is unambiguous, it can be parsed if necessary.
*/
@Override
public String toString() {
return owner + '.' + name + desc + " (" + tag + (itf ? " itf" : "") + ')';
}
/**
* Returns the textual representation of this handle. The textual representation is:
*
* <pre>
* for a reference to a class:
* owner '.' name desc ' ' '(' tag ')'
* for a reference to an interface:
* owner '.' name desc ' ' '(' tag ' ' itf ')'
* </pre>
*
* . As this format is unambiguous, it can be parsed if necessary.
*/
@Override
public String toString() {
return owner + '.' + name + desc + " (" + tag + (itf ? " itf" : "") + ')';
}
}

View File

@@ -65,74 +65,74 @@ package org.redkale.asm;
*/
class Handler {
/** Beginning of the exception handler's scope (inclusive). */
Label start;
/** Beginning of the exception handler's scope (inclusive). */
Label start;
/** End of the exception handler's scope (exclusive). */
Label end;
/** End of the exception handler's scope (exclusive). */
Label end;
/** Beginning of the exception handler's code. */
Label handler;
/** Beginning of the exception handler's code. */
Label handler;
/**
* Internal name of the type of exceptions handled by this handler, or &#60;tt&#62;null&#60;/tt&#62; to catch any
* exceptions.
*/
String desc;
/**
* Internal name of the type of exceptions handled by this handler, or &#60;tt&#62;null&#60;/tt&#62; to catch any
* exceptions.
*/
String desc;
/**
* Constant pool index of the internal name of the type of exceptions handled by this handler, or 0 to catch any
* exceptions.
*/
int type;
/**
* Constant pool index of the internal name of the type of exceptions handled by this handler, or 0 to catch any
* exceptions.
*/
int type;
/** Next exception handler block info. */
Handler next;
/** Next exception handler block info. */
Handler next;
/**
* Removes the range between start and end from the given exception handlers.
*
* @param h an exception handler list.
* @param start the start of the range to be removed.
* @param end the end of the range to be removed. Maybe null.
* @return the exception handler list with the start-end range removed.
*/
static Handler remove(Handler h, Label start, Label end) {
if (h == null) {
return null;
} else {
h.next = remove(h.next, start, end);
}
int hstart = h.start.position;
int hend = h.end.position;
int s = start.position;
int e = end == null ? Integer.MAX_VALUE : end.position;
// if [hstart,hend[ and [s,e[ intervals intersect...
if (s < hend && e > hstart) {
if (s <= hstart) {
if (e >= hend) {
// [hstart,hend[ fully included in [s,e[, h removed
h = h.next;
} else {
// [hstart,hend[ minus [s,e[ = [e,hend[
h.start = end;
}
} else if (e >= hend) {
// [hstart,hend[ minus [s,e[ = [hstart,s[
h.end = start;
} else {
// [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
Handler g = new Handler();
g.start = end;
g.end = h.end;
g.handler = h.handler;
g.desc = h.desc;
g.type = h.type;
g.next = h.next;
h.end = start;
h.next = g;
}
}
return h;
}
/**
* Removes the range between start and end from the given exception handlers.
*
* @param h an exception handler list.
* @param start the start of the range to be removed.
* @param end the end of the range to be removed. Maybe null.
* @return the exception handler list with the start-end range removed.
*/
static Handler remove(Handler h, Label start, Label end) {
if (h == null) {
return null;
} else {
h.next = remove(h.next, start, end);
}
int hstart = h.start.position;
int hend = h.end.position;
int s = start.position;
int e = end == null ? Integer.MAX_VALUE : end.position;
// if [hstart,hend[ and [s,e[ intervals intersect...
if (s < hend && e > hstart) {
if (s <= hstart) {
if (e >= hend) {
// [hstart,hend[ fully included in [s,e[, h removed
h = h.next;
} else {
// [hstart,hend[ minus [s,e[ = [e,hend[
h.start = end;
}
} else if (e >= hend) {
// [hstart,hend[ minus [s,e[ = [hstart,s[
h.end = start;
} else {
// [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
Handler g = new Handler();
g.start = end;
g.end = h.end;
g.handler = h.handler;
g.desc = h.desc;
g.type = h.type;
g.next = h.next;
h.end = start;
h.next = g;
}
}
return h;
}
}

View File

@@ -65,225 +65,225 @@ package org.redkale.asm;
*/
final class Item {
/** Index of this item in the constant pool. */
int index;
/** Index of this item in the constant pool. */
int index;
/**
* Type of this constant pool item. A single class is used to represent all constant pool item types, in order to
* minimize the bytecode size of this package. The value of this field is one of {@link ClassWriter#INT},
* {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
*
* <p>MethodHandle constant 9 variations are stored using a range of 9 values from {@link ClassWriter#HANDLE_BASE} +
* 1 to {@link ClassWriter#HANDLE_BASE} + 9.
*
* <p>Special Item types are used for Items that are stored in the ClassWriter {@link ClassWriter#typeTable},
* instead of the constant pool, in order to avoid clashes with normal constant pool items in the ClassWriter
* constant pool's hash table. These special item types are {@link ClassWriter#TYPE_NORMAL},
* {@link ClassWriter#TYPE_UNINIT} and {@link ClassWriter#TYPE_MERGED}.
*/
int type;
/**
* Type of this constant pool item. A single class is used to represent all constant pool item types, in order to
* minimize the bytecode size of this package. The value of this field is one of {@link ClassWriter#INT},
* {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
*
* <p>MethodHandle constant 9 variations are stored using a range of 9 values from {@link ClassWriter#HANDLE_BASE} +
* 1 to {@link ClassWriter#HANDLE_BASE} + 9.
*
* <p>Special Item types are used for Items that are stored in the ClassWriter {@link ClassWriter#typeTable},
* instead of the constant pool, in order to avoid clashes with normal constant pool items in the ClassWriter
* constant pool's hash table. These special item types are {@link ClassWriter#TYPE_NORMAL},
* {@link ClassWriter#TYPE_UNINIT} and {@link ClassWriter#TYPE_MERGED}.
*/
int type;
/** Value of this item, for an integer item. */
int intVal;
/** Value of this item, for an integer item. */
int intVal;
/** Value of this item, for a long item. */
long longVal;
/** Value of this item, for a long item. */
long longVal;
/** First part of the value of this item, for items that do not hold a primitive value. */
String strVal1;
/** First part of the value of this item, for items that do not hold a primitive value. */
String strVal1;
/** Second part of the value of this item, for items that do not hold a primitive value. */
String strVal2;
/** Second part of the value of this item, for items that do not hold a primitive value. */
String strVal2;
/** Third part of the value of this item, for items that do not hold a primitive value. */
String strVal3;
/** Third part of the value of this item, for items that do not hold a primitive value. */
String strVal3;
/** The hash code value of this constant pool item. */
int hashCode;
/** The hash code value of this constant pool item. */
int hashCode;
/** Link to another constant pool item, used for collision lists in the constant pool's hash table. */
Item next;
/** Link to another constant pool item, used for collision lists in the constant pool's hash table. */
Item next;
/** Constructs an uninitialized {@link Item}. */
Item() {}
/** Constructs an uninitialized {@link Item}. */
Item() {}
/**
* Constructs an uninitialized {@link Item} for constant pool element at given position.
*
* @param index index of the item to be constructed.
*/
Item(final int index) {
this.index = index;
}
/**
* Constructs an uninitialized {@link Item} for constant pool element at given position.
*
* @param index index of the item to be constructed.
*/
Item(final int index) {
this.index = index;
}
/**
* Constructs a copy of the given item.
*
* @param index index of the item to be constructed.
* @param i the item that must be copied into the item to be constructed.
*/
Item(final int index, final Item i) {
this.index = index;
type = i.type;
intVal = i.intVal;
longVal = i.longVal;
strVal1 = i.strVal1;
strVal2 = i.strVal2;
strVal3 = i.strVal3;
hashCode = i.hashCode;
}
/**
* Constructs a copy of the given item.
*
* @param index index of the item to be constructed.
* @param i the item that must be copied into the item to be constructed.
*/
Item(final int index, final Item i) {
this.index = index;
type = i.type;
intVal = i.intVal;
longVal = i.longVal;
strVal1 = i.strVal1;
strVal2 = i.strVal2;
strVal3 = i.strVal3;
hashCode = i.hashCode;
}
/**
* Sets this item to an integer item.
*
* @param intVal the value of this item.
*/
void set(final int intVal) {
this.type = ClassWriter.INT;
this.intVal = intVal;
this.hashCode = 0x7FFFFFFF & (type + intVal);
}
/**
* Sets this item to an integer item.
*
* @param intVal the value of this item.
*/
void set(final int intVal) {
this.type = ClassWriter.INT;
this.intVal = intVal;
this.hashCode = 0x7FFFFFFF & (type + intVal);
}
/**
* Sets this item to a long item.
*
* @param longVal the value of this item.
*/
void set(final long longVal) {
this.type = ClassWriter.LONG;
this.longVal = longVal;
this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
}
/**
* Sets this item to a long item.
*
* @param longVal the value of this item.
*/
void set(final long longVal) {
this.type = ClassWriter.LONG;
this.longVal = longVal;
this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
}
/**
* Sets this item to a float item.
*
* @param floatVal the value of this item.
*/
void set(final float floatVal) {
this.type = ClassWriter.FLOAT;
this.intVal = Float.floatToRawIntBits(floatVal);
this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
}
/**
* Sets this item to a float item.
*
* @param floatVal the value of this item.
*/
void set(final float floatVal) {
this.type = ClassWriter.FLOAT;
this.intVal = Float.floatToRawIntBits(floatVal);
this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
}
/**
* Sets this item to a double item.
*
* @param doubleVal the value of this item.
*/
void set(final double doubleVal) {
this.type = ClassWriter.DOUBLE;
this.longVal = Double.doubleToRawLongBits(doubleVal);
this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
}
/**
* Sets this item to a double item.
*
* @param doubleVal the value of this item.
*/
void set(final double doubleVal) {
this.type = ClassWriter.DOUBLE;
this.longVal = Double.doubleToRawLongBits(doubleVal);
this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
}
/**
* Sets this item to an item that do not hold a primitive value.
*
* @param type the type of this item.
* @param strVal1 first part of the value of this item.
* @param strVal2 second part of the value of this item.
* @param strVal3 third part of the value of this item.
*/
@SuppressWarnings("fallthrough")
void set(final int type, final String strVal1, final String strVal2, final String strVal3) {
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.CLASS:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.MTYPE:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.TYPE_NORMAL:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return;
case ClassWriter.NAME_TYPE: {
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode());
return;
}
// ClassWriter.FIELD:
// ClassWriter.METH:
// ClassWriter.IMETH:
// ClassWriter.HANDLE_BASE + 1..9
default:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode() * strVal3.hashCode());
}
}
/**
* Sets this item to an item that do not hold a primitive value.
*
* @param type the type of this item.
* @param strVal1 first part of the value of this item.
* @param strVal2 second part of the value of this item.
* @param strVal3 third part of the value of this item.
*/
@SuppressWarnings("fallthrough")
void set(final int type, final String strVal1, final String strVal2, final String strVal3) {
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.CLASS:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.MTYPE:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.TYPE_NORMAL:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return;
case ClassWriter.NAME_TYPE: {
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode());
return;
}
// ClassWriter.FIELD:
// ClassWriter.METH:
// ClassWriter.IMETH:
// ClassWriter.HANDLE_BASE + 1..9
default:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode() * strVal3.hashCode());
}
}
/**
* Sets the item to an InvokeDynamic item.
*
* @param name invokedynamic's name.
* @param desc invokedynamic's desc.
* @param bsmIndex zero based index into the class attribute BootrapMethods.
*/
void set(String name, String desc, int bsmIndex) {
this.type = ClassWriter.INDY;
this.longVal = bsmIndex;
this.strVal1 = name;
this.strVal2 = desc;
this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex * strVal1.hashCode() * strVal2.hashCode());
}
/**
* Sets the item to an InvokeDynamic item.
*
* @param name invokedynamic's name.
* @param desc invokedynamic's desc.
* @param bsmIndex zero based index into the class attribute BootrapMethods.
*/
void set(String name, String desc, int bsmIndex) {
this.type = ClassWriter.INDY;
this.longVal = bsmIndex;
this.strVal1 = name;
this.strVal2 = desc;
this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex * strVal1.hashCode() * strVal2.hashCode());
}
/**
* Sets the item to a BootstrapMethod item.
*
* @param position position in byte in the class attribute BootrapMethods.
* @param hashCode hashcode of the item. This hashcode is processed from the hashcode of the bootstrap method and
* the hashcode of all bootstrap arguments.
*/
void set(int position, int hashCode) {
this.type = ClassWriter.BSM;
this.intVal = position;
this.hashCode = hashCode;
}
/**
* Sets the item to a BootstrapMethod item.
*
* @param position position in byte in the class attribute BootrapMethods.
* @param hashCode hashcode of the item. This hashcode is processed from the hashcode of the bootstrap method and
* the hashcode of all bootstrap arguments.
*/
void set(int position, int hashCode) {
this.type = ClassWriter.BSM;
this.intVal = position;
this.hashCode = hashCode;
}
/**
* Indicates if the given item is equal to this one. <i>This method assumes that the two items have the same
* {@link #type}</i>.
*
* @param i the item to be compared to this one. Both items must have the same {@link #type}.
* @return &#60;tt&#62;true&#60;/tt&#62; if the given item if equal to this one, &#60;tt&#62;false&#60;/tt&#62;
* otherwise.
*/
boolean isEqualTo(final Item i) {
switch (type) {
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.MTYPE:
case ClassWriter.TYPE_NORMAL:
return i.strVal1.equals(strVal1);
case ClassWriter.TYPE_MERGED:
case ClassWriter.LONG:
case ClassWriter.DOUBLE:
return i.longVal == longVal;
case ClassWriter.INT:
case ClassWriter.FLOAT:
return i.intVal == intVal;
case ClassWriter.TYPE_UNINIT:
return i.intVal == intVal && i.strVal1.equals(strVal1);
case ClassWriter.NAME_TYPE:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
case ClassWriter.INDY: {
return i.longVal == longVal && i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
}
// case ClassWriter.FIELD:
// case ClassWriter.METH:
// case ClassWriter.IMETH:
// case ClassWriter.HANDLE_BASE + 1..9
default:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) && i.strVal3.equals(strVal3);
}
}
/**
* Indicates if the given item is equal to this one. <i>This method assumes that the two items have the same
* {@link #type}</i>.
*
* @param i the item to be compared to this one. Both items must have the same {@link #type}.
* @return &#60;tt&#62;true&#60;/tt&#62; if the given item if equal to this one, &#60;tt&#62;false&#60;/tt&#62;
* otherwise.
*/
boolean isEqualTo(final Item i) {
switch (type) {
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.MTYPE:
case ClassWriter.TYPE_NORMAL:
return i.strVal1.equals(strVal1);
case ClassWriter.TYPE_MERGED:
case ClassWriter.LONG:
case ClassWriter.DOUBLE:
return i.longVal == longVal;
case ClassWriter.INT:
case ClassWriter.FLOAT:
return i.intVal == intVal;
case ClassWriter.TYPE_UNINIT:
return i.intVal == intVal && i.strVal1.equals(strVal1);
case ClassWriter.NAME_TYPE:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
case ClassWriter.INDY: {
return i.longVal == longVal && i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
}
// case ClassWriter.FIELD:
// case ClassWriter.METH:
// case ClassWriter.IMETH:
// case ClassWriter.HANDLE_BASE + 1..9
default:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) && i.strVal3.equals(strVal3);
}
}
}

View File

@@ -68,442 +68,442 @@ package org.redkale.asm;
*/
public class Label {
/**
* Indicates if this label is only used for debug attributes. Such a label is not the start of a basic block, the
* target of a jump instruction, or an exception handler. It can be safely ignored in control flow graph analysis
* algorithms (for optimization purposes).
*/
static final int DEBUG = 1;
/**
* Indicates if this label is only used for debug attributes. Such a label is not the start of a basic block, the
* target of a jump instruction, or an exception handler. It can be safely ignored in control flow graph analysis
* algorithms (for optimization purposes).
*/
static final int DEBUG = 1;
/** Indicates if the position of this label is known. */
static final int RESOLVED = 2;
/** Indicates if the position of this label is known. */
static final int RESOLVED = 2;
/** Indicates if this label has been updated, after instruction resizing. */
static final int RESIZED = 4;
/** Indicates if this label has been updated, after instruction resizing. */
static final int RESIZED = 4;
/**
* Indicates if this basic block has been pushed in the basic block stack. See {@link MethodWriter#visitMaxs
* visitMaxs}.
*/
static final int PUSHED = 8;
/**
* Indicates if this basic block has been pushed in the basic block stack. See {@link MethodWriter#visitMaxs
* visitMaxs}.
*/
static final int PUSHED = 8;
/** Indicates if this label is the target of a jump instruction, or the start of an exception handler. */
static final int TARGET = 16;
/** Indicates if this label is the target of a jump instruction, or the start of an exception handler. */
static final int TARGET = 16;
/** Indicates if a stack map frame must be stored for this label. */
static final int STORE = 32;
/** Indicates if a stack map frame must be stored for this label. */
static final int STORE = 32;
/** Indicates if this label corresponds to a reachable basic block. */
static final int REACHABLE = 64;
/** Indicates if this label corresponds to a reachable basic block. */
static final int REACHABLE = 64;
/** Indicates if this basic block ends with a JSR instruction. */
static final int JSR = 128;
/** Indicates if this basic block ends with a JSR instruction. */
static final int JSR = 128;
/** Indicates if this basic block ends with a RET instruction. */
static final int RET = 256;
/** Indicates if this basic block ends with a RET instruction. */
static final int RET = 256;
/** Indicates if this basic block is the start of a subroutine. */
static final int SUBROUTINE = 512;
/** Indicates if this basic block is the start of a subroutine. */
static final int SUBROUTINE = 512;
/** Indicates if this subroutine basic block has been visited by a visitSubroutine(null, ...) call. */
static final int VISITED = 1024;
/** Indicates if this subroutine basic block has been visited by a visitSubroutine(null, ...) call. */
static final int VISITED = 1024;
/** Indicates if this subroutine basic block has been visited by a visitSubroutine(!null, ...) call. */
static final int VISITED2 = 2048;
/** Indicates if this subroutine basic block has been visited by a visitSubroutine(!null, ...) call. */
static final int VISITED2 = 2048;
/**
* Field used to associate user information to a label. Warning: this field is used by the ASM tree package. In
* order to use it with the ASM tree package you must override the
*/
public Object info;
/**
* Field used to associate user information to a label. Warning: this field is used by the ASM tree package. In
* order to use it with the ASM tree package you must override the
*/
public Object info;
/**
* Flags that indicate the status of this label.
*
* @see #DEBUG
* @see #RESOLVED
* @see #RESIZED
* @see #PUSHED
* @see #TARGET
* @see #STORE
* @see #REACHABLE
* @see #JSR
* @see #RET
*/
int status;
/**
* Flags that indicate the status of this label.
*
* @see #DEBUG
* @see #RESOLVED
* @see #RESIZED
* @see #PUSHED
* @see #TARGET
* @see #STORE
* @see #REACHABLE
* @see #JSR
* @see #RET
*/
int status;
/**
* The line number corresponding to this label, if known. If there are several lines, each line is stored in a
* separate label, all linked via their next field (these links are created in ClassReader and removed just before
* visitLabel is called, so that this does not impact the rest of the code).
*/
int line;
/**
* The line number corresponding to this label, if known. If there are several lines, each line is stored in a
* separate label, all linked via their next field (these links are created in ClassReader and removed just before
* visitLabel is called, so that this does not impact the rest of the code).
*/
int line;
/** The position of this label in the code, if known. */
int position;
/** The position of this label in the code, if known. */
int position;
/** Number of forward references to this label, times two. */
private int referenceCount;
/** Number of forward references to this label, times two. */
private int referenceCount;
/**
* Informations about forward references. Each forward reference is described by two consecutive integers in this
* array: the first one is the position of the first byte of the bytecode instruction that contains the forward
* reference, while the second is the position of the first byte of the forward reference itself. In fact the sign
* of the first integer indicates if this reference uses 2 or 4 bytes, and its absolute value gives the position of
* the bytecode instruction. This array is also used as a bitset to store the subroutines to which a basic block
* belongs. This information is needed in {@linked MethodWriter#visitMaxs}, after all forward references have been
* resolved. Hence the same array can be used for both purposes without problems.
*/
private int[] srcAndRefPositions;
/**
* Informations about forward references. Each forward reference is described by two consecutive integers in this
* array: the first one is the position of the first byte of the bytecode instruction that contains the forward
* reference, while the second is the position of the first byte of the forward reference itself. In fact the sign
* of the first integer indicates if this reference uses 2 or 4 bytes, and its absolute value gives the position of
* the bytecode instruction. This array is also used as a bitset to store the subroutines to which a basic block
* belongs. This information is needed in {@linked MethodWriter#visitMaxs}, after all forward references have been
* resolved. Hence the same array can be used for both purposes without problems.
*/
private int[] srcAndRefPositions;
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
/*
* Fields for the control flow and data flow graph analysis algorithms (used
* to compute the maximum stack size or the stack map frames). A control
* flow graph contains one node per "basic block", and one edge per "jump"
* from one basic block to another. Each node (i.e., each basic block) is
* represented by the Label object that corresponds to the first instruction
* of this basic block. Each node also stores the list of its successors in
* the graph, as a linked list of Edge objects.
*
* The control flow analysis algorithms used to compute the maximum stack
* size or the stack map frames are similar and use two steps. The first
* step, during the visit of each instruction, builds information about the
* state of the local variables and the operand stack at the end of each
* basic block, called the "output frame", <i>relatively</i> to the frame
* state at the beginning of the basic block, which is called the "input
* frame", and which is <i>unknown</i> during this step. The second step, in
* {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
* information about the input frame of each basic block, from the input
* state of the first basic block (known from the method signature), and by
* the using the previously computed relative output frames.
*
* The algorithm used to compute the maximum stack size only computes the
* relative output and absolute input stack heights, while the algorithm
* used to compute stack map frames computes relative output frames and
* absolute input frames.
*/
/*
* Fields for the control flow and data flow graph analysis algorithms (used
* to compute the maximum stack size or the stack map frames). A control
* flow graph contains one node per "basic block", and one edge per "jump"
* from one basic block to another. Each node (i.e., each basic block) is
* represented by the Label object that corresponds to the first instruction
* of this basic block. Each node also stores the list of its successors in
* the graph, as a linked list of Edge objects.
*
* The control flow analysis algorithms used to compute the maximum stack
* size or the stack map frames are similar and use two steps. The first
* step, during the visit of each instruction, builds information about the
* state of the local variables and the operand stack at the end of each
* basic block, called the "output frame", <i>relatively</i> to the frame
* state at the beginning of the basic block, which is called the "input
* frame", and which is <i>unknown</i> during this step. The second step, in
* {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
* information about the input frame of each basic block, from the input
* state of the first basic block (known from the method signature), and by
* the using the previously computed relative output frames.
*
* The algorithm used to compute the maximum stack size only computes the
* relative output and absolute input stack heights, while the algorithm
* used to compute stack map frames computes relative output frames and
* absolute input frames.
*/
/**
* Start of the output stack relatively to the input stack. The exact semantics of this field depends on the
* algorithm that is used.
*
* <p>When only the maximum stack size is computed, this field is the number of elements in the input stack.
*
* <p>When the stack map frames are completely computed, this field is the offset of the first output stack element
* relatively to the top of the input stack. This offset is always negative or null. A null offset means that the
* output stack must be appended to the input stack. A -n offset means that the first n output stack elements must
* replace the top n input stack elements, and that the other elements must be appended to the input stack.
*/
int inputStackTop;
/**
* Start of the output stack relatively to the input stack. The exact semantics of this field depends on the
* algorithm that is used.
*
* <p>When only the maximum stack size is computed, this field is the number of elements in the input stack.
*
* <p>When the stack map frames are completely computed, this field is the offset of the first output stack element
* relatively to the top of the input stack. This offset is always negative or null. A null offset means that the
* output stack must be appended to the input stack. A -n offset means that the first n output stack elements must
* replace the top n input stack elements, and that the other elements must be appended to the input stack.
*/
int inputStackTop;
/**
* Maximum height reached by the output stack, relatively to the top of the input stack. This maximum is always
* positive or null.
*/
int outputStackMax;
/**
* Maximum height reached by the output stack, relatively to the top of the input stack. This maximum is always
* positive or null.
*/
int outputStackMax;
/**
* Information about the input and output stack map frames of this basic block. This field is only used when
* {@link ClassWriter#COMPUTE_FRAMES} option is used.
*/
Frame frame;
/**
* Information about the input and output stack map frames of this basic block. This field is only used when
* {@link ClassWriter#COMPUTE_FRAMES} option is used.
*/
Frame frame;
/**
* The successor of this label, in the order they are visited. This linked list does not include labels used for
* debug info only. If {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it does not contain
* successive labels that denote the same bytecode position (in this case only the first label appears in this
* list).
*/
Label successor;
/**
* The successor of this label, in the order they are visited. This linked list does not include labels used for
* debug info only. If {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it does not contain
* successive labels that denote the same bytecode position (in this case only the first label appears in this
* list).
*/
Label successor;
/**
* The successors of this node in the control flow graph. These successors are stored in a linked list of
* {@link Edge Edge} objects, linked to each other by their {@link Edge#next} field.
*/
Edge successors;
/**
* The successors of this node in the control flow graph. These successors are stored in a linked list of
* {@link Edge Edge} objects, linked to each other by their {@link Edge#next} field.
*/
Edge successors;
/**
* The next basic block in the basic block stack. This stack is used in the main loop of the fix point algorithm
* used in the second step of the control flow analysis algorithms. It is also used in {@link #visitSubroutine} to
* avoid using a recursive method, and in ClassReader to temporarily store multiple source lines for a label.
*
* @see MethodWriter#visitMaxs
*/
Label next;
/**
* The next basic block in the basic block stack. This stack is used in the main loop of the fix point algorithm
* used in the second step of the control flow analysis algorithms. It is also used in {@link #visitSubroutine} to
* avoid using a recursive method, and in ClassReader to temporarily store multiple source lines for a label.
*
* @see MethodWriter#visitMaxs
*/
Label next;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
/** Constructs a new label. */
public Label() {
// do nothing
}
/** Constructs a new label. */
public Label() {
// do nothing
}
// ------------------------------------------------------------------------
// Methods to compute offsets and to manage forward references
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Methods to compute offsets and to manage forward references
// ------------------------------------------------------------------------
/**
* Returns the offset corresponding to this label. This offset is computed from the start of the method's bytecode.
* <i>This method is intended for {@link Attribute} sub classes, and is normally not needed by class generators or
* adapters.</i>
*
* @return the offset corresponding to this label.
* @throws IllegalStateException if this label is not resolved yet.
*/
public int getOffset() {
if ((status & RESOLVED) == 0) {
throw new IllegalStateException("Label offset position has not been resolved yet");
}
return position;
}
/**
* Returns the offset corresponding to this label. This offset is computed from the start of the method's bytecode.
* <i>This method is intended for {@link Attribute} sub classes, and is normally not needed by class generators or
* adapters.</i>
*
* @return the offset corresponding to this label.
* @throws IllegalStateException if this label is not resolved yet.
*/
public int getOffset() {
if ((status & RESOLVED) == 0) {
throw new IllegalStateException("Label offset position has not been resolved yet");
}
return position;
}
/**
* Puts a reference to this label in the bytecode of a method. If the position of the label is known, the offset is
* computed and written directly. Otherwise, a null offset is written and a new forward reference is declared for
* this label.
*
* @param owner the code writer that calls this method.
* @param out the bytecode of the method.
* @param source the position of first byte of the bytecode instruction that contains this label.
* @param wideOffset &#60;tt&#62;true&#60;/tt&#62; if the reference must be stored in 4 bytes, or
* &#60;tt&#62;false&#60;/tt&#62; if it must be stored with 2 bytes.
* @throws IllegalArgumentException if this label has not been created by the given code writer.
*/
void put(final MethodWriter owner, final ByteVector out, final int source, final boolean wideOffset) {
if ((status & RESOLVED) == 0) {
if (wideOffset) {
addReference(-1 - source, out.length);
out.putInt(-1);
} else {
addReference(source, out.length);
out.putShort(-1);
}
} else {
if (wideOffset) {
out.putInt(position - source);
} else {
out.putShort(position - source);
}
}
}
/**
* Puts a reference to this label in the bytecode of a method. If the position of the label is known, the offset is
* computed and written directly. Otherwise, a null offset is written and a new forward reference is declared for
* this label.
*
* @param owner the code writer that calls this method.
* @param out the bytecode of the method.
* @param source the position of first byte of the bytecode instruction that contains this label.
* @param wideOffset &#60;tt&#62;true&#60;/tt&#62; if the reference must be stored in 4 bytes, or
* &#60;tt&#62;false&#60;/tt&#62; if it must be stored with 2 bytes.
* @throws IllegalArgumentException if this label has not been created by the given code writer.
*/
void put(final MethodWriter owner, final ByteVector out, final int source, final boolean wideOffset) {
if ((status & RESOLVED) == 0) {
if (wideOffset) {
addReference(-1 - source, out.length);
out.putInt(-1);
} else {
addReference(source, out.length);
out.putShort(-1);
}
} else {
if (wideOffset) {
out.putInt(position - source);
} else {
out.putShort(position - source);
}
}
}
/**
* Adds a forward reference to this label. This method must be called only for a true forward reference, i.e. only
* if this label is not resolved yet. For backward references, the offset of the reference can be, and must be,
* computed and stored directly.
*
* @param sourcePosition the position of the referencing instruction. This position will be used to compute the
* offset of this forward reference.
* @param referencePosition the position where the offset for this forward reference must be stored.
*/
private void addReference(final int sourcePosition, final int referencePosition) {
if (srcAndRefPositions == null) {
srcAndRefPositions = new int[6];
}
if (referenceCount >= srcAndRefPositions.length) {
int[] a = new int[srcAndRefPositions.length + 6];
System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length);
srcAndRefPositions = a;
}
srcAndRefPositions[referenceCount++] = sourcePosition;
srcAndRefPositions[referenceCount++] = referencePosition;
}
/**
* Adds a forward reference to this label. This method must be called only for a true forward reference, i.e. only
* if this label is not resolved yet. For backward references, the offset of the reference can be, and must be,
* computed and stored directly.
*
* @param sourcePosition the position of the referencing instruction. This position will be used to compute the
* offset of this forward reference.
* @param referencePosition the position where the offset for this forward reference must be stored.
*/
private void addReference(final int sourcePosition, final int referencePosition) {
if (srcAndRefPositions == null) {
srcAndRefPositions = new int[6];
}
if (referenceCount >= srcAndRefPositions.length) {
int[] a = new int[srcAndRefPositions.length + 6];
System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length);
srcAndRefPositions = a;
}
srcAndRefPositions[referenceCount++] = sourcePosition;
srcAndRefPositions[referenceCount++] = referencePosition;
}
/**
* Resolves all forward references to this label. This method must be called when this label is added to the
* bytecode of the method, i.e. when its position becomes known. This method fills in the blanks that where left in
* the bytecode by each forward reference previously added to this label.
*
* @param owner the code writer that calls this method.
* @param position the position of this label in the bytecode.
* @param data the bytecode of the method.
* @return &#60;tt&#62;true&#60;/tt&#62; if a blank that was left for this label was too small to store the offset.
* In such a case the corresponding jump instruction is replaced with a pseudo instruction (using unused
* opcodes) using an unsigned two bytes offset. These pseudo instructions will be replaced with standard
* bytecode instructions with wider offsets (4 bytes instead of 2), in ClassReader.
* @throws IllegalArgumentException if this label has already been resolved, or if it has not been created by the
* given code writer.
*/
boolean resolve(final MethodWriter owner, final int position, final byte[] data) {
boolean needUpdate = false;
this.status |= RESOLVED;
this.position = position;
int i = 0;
while (i < referenceCount) {
int source = srcAndRefPositions[i++];
int reference = srcAndRefPositions[i++];
int offset;
if (source >= 0) {
offset = position - source;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
/*
* changes the opcode of the jump instruction, in order to
* be able to find it later (see resizeInstructions in
* MethodWriter). These temporary opcodes are similar to
* jump instruction opcodes, except that the 2 bytes offset
* is unsigned (and can therefore represent values from 0 to
* 65535, which is sufficient since the size of a method is
* limited to 65535 bytes).
*/
int opcode = data[reference - 1] & 0xFF;
if (opcode <= Opcodes.JSR) {
// changes IFEQ ... JSR to opcodes 202 to 217
data[reference - 1] = (byte) (opcode + 49);
} else {
// changes IFNULL and IFNONNULL to opcodes 218 and 219
data[reference - 1] = (byte) (opcode + 20);
}
needUpdate = true;
}
data[reference++] = (byte) (offset >>> 8);
data[reference] = (byte) offset;
} else {
offset = position + source + 1;
data[reference++] = (byte) (offset >>> 24);
data[reference++] = (byte) (offset >>> 16);
data[reference++] = (byte) (offset >>> 8);
data[reference] = (byte) offset;
}
}
return needUpdate;
}
/**
* Resolves all forward references to this label. This method must be called when this label is added to the
* bytecode of the method, i.e. when its position becomes known. This method fills in the blanks that where left in
* the bytecode by each forward reference previously added to this label.
*
* @param owner the code writer that calls this method.
* @param position the position of this label in the bytecode.
* @param data the bytecode of the method.
* @return &#60;tt&#62;true&#60;/tt&#62; if a blank that was left for this label was too small to store the offset.
* In such a case the corresponding jump instruction is replaced with a pseudo instruction (using unused
* opcodes) using an unsigned two bytes offset. These pseudo instructions will be replaced with standard
* bytecode instructions with wider offsets (4 bytes instead of 2), in ClassReader.
* @throws IllegalArgumentException if this label has already been resolved, or if it has not been created by the
* given code writer.
*/
boolean resolve(final MethodWriter owner, final int position, final byte[] data) {
boolean needUpdate = false;
this.status |= RESOLVED;
this.position = position;
int i = 0;
while (i < referenceCount) {
int source = srcAndRefPositions[i++];
int reference = srcAndRefPositions[i++];
int offset;
if (source >= 0) {
offset = position - source;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
/*
* changes the opcode of the jump instruction, in order to
* be able to find it later (see resizeInstructions in
* MethodWriter). These temporary opcodes are similar to
* jump instruction opcodes, except that the 2 bytes offset
* is unsigned (and can therefore represent values from 0 to
* 65535, which is sufficient since the size of a method is
* limited to 65535 bytes).
*/
int opcode = data[reference - 1] & 0xFF;
if (opcode <= Opcodes.JSR) {
// changes IFEQ ... JSR to opcodes 202 to 217
data[reference - 1] = (byte) (opcode + 49);
} else {
// changes IFNULL and IFNONNULL to opcodes 218 and 219
data[reference - 1] = (byte) (opcode + 20);
}
needUpdate = true;
}
data[reference++] = (byte) (offset >>> 8);
data[reference] = (byte) offset;
} else {
offset = position + source + 1;
data[reference++] = (byte) (offset >>> 24);
data[reference++] = (byte) (offset >>> 16);
data[reference++] = (byte) (offset >>> 8);
data[reference] = (byte) offset;
}
}
return needUpdate;
}
/**
* Returns the first label of the series to which this label belongs. For an isolated label or for the first label
* in a series of successive labels, this method returns the label itself. For other labels it returns the first
* label of the series.
*
* @return the first label of the series to which this label belongs.
*/
Label getFirst() {
return frame == null ? this : frame.owner;
}
/**
* Returns the first label of the series to which this label belongs. For an isolated label or for the first label
* in a series of successive labels, this method returns the label itself. For other labels it returns the first
* label of the series.
*
* @return the first label of the series to which this label belongs.
*/
Label getFirst() {
return frame == null ? this : frame.owner;
}
// ------------------------------------------------------------------------
// Methods related to subroutines
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Methods related to subroutines
// ------------------------------------------------------------------------
/**
* Returns true is this basic block belongs to the given subroutine.
*
* @param id a subroutine id.
* @return true is this basic block belongs to the given subroutine.
*/
boolean inSubroutine(final long id) {
if ((status & Label.VISITED) != 0) {
return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
}
return false;
}
/**
* Returns true is this basic block belongs to the given subroutine.
*
* @param id a subroutine id.
* @return true is this basic block belongs to the given subroutine.
*/
boolean inSubroutine(final long id) {
if ((status & Label.VISITED) != 0) {
return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
}
return false;
}
/**
* Returns true if this basic block and the given one belong to a common subroutine.
*
* @param block another basic block.
* @return true if this basic block and the given one belong to a common subroutine.
*/
boolean inSameSubroutine(final Label block) {
if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
return false;
}
for (int i = 0; i < srcAndRefPositions.length; ++i) {
if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
return true;
}
}
return false;
}
/**
* Returns true if this basic block and the given one belong to a common subroutine.
*
* @param block another basic block.
* @return true if this basic block and the given one belong to a common subroutine.
*/
boolean inSameSubroutine(final Label block) {
if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
return false;
}
for (int i = 0; i < srcAndRefPositions.length; ++i) {
if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
return true;
}
}
return false;
}
/**
* Marks this basic block as belonging to the given subroutine.
*
* @param id a subroutine id.
* @param nbSubroutines the total number of subroutines in the method.
*/
void addToSubroutine(final long id, final int nbSubroutines) {
if ((status & VISITED) == 0) {
status |= VISITED;
srcAndRefPositions = new int[nbSubroutines / 32 + 1];
}
srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
}
/**
* Marks this basic block as belonging to the given subroutine.
*
* @param id a subroutine id.
* @param nbSubroutines the total number of subroutines in the method.
*/
void addToSubroutine(final long id, final int nbSubroutines) {
if ((status & VISITED) == 0) {
status |= VISITED;
srcAndRefPositions = new int[nbSubroutines / 32 + 1];
}
srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
}
/**
* Finds the basic blocks that belong to a given subroutine, and marks these blocks as belonging to this subroutine.
* This method follows the control flow graph to find all the blocks that are reachable from the current block
* WITHOUT following any JSR target.
*
* @param JSR a JSR block that jumps to this subroutine. If this JSR is not null it is added to the successor of the
* RET blocks found in the subroutine.
* @param id the id of this subroutine.
* @param nbSubroutines the total number of subroutines in the method.
*/
void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
// user managed stack of labels, to avoid using a recursive method
// (recursivity can lead to stack overflow with very large methods)
Label stack = this;
while (stack != null) {
// removes a label l from the stack
Label l = stack;
stack = l.next;
l.next = null;
/**
* Finds the basic blocks that belong to a given subroutine, and marks these blocks as belonging to this subroutine.
* This method follows the control flow graph to find all the blocks that are reachable from the current block
* WITHOUT following any JSR target.
*
* @param JSR a JSR block that jumps to this subroutine. If this JSR is not null it is added to the successor of the
* RET blocks found in the subroutine.
* @param id the id of this subroutine.
* @param nbSubroutines the total number of subroutines in the method.
*/
void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
// user managed stack of labels, to avoid using a recursive method
// (recursivity can lead to stack overflow with very large methods)
Label stack = this;
while (stack != null) {
// removes a label l from the stack
Label l = stack;
stack = l.next;
l.next = null;
if (JSR != null) {
if ((l.status & VISITED2) != 0) {
continue;
}
l.status |= VISITED2;
// adds JSR to the successors of l, if it is a RET block
if ((l.status & RET) != 0) {
if (!l.inSameSubroutine(JSR)) {
Edge e = new Edge();
e.info = l.inputStackTop;
e.successor = JSR.successors.successor;
e.next = l.successors;
l.successors = e;
}
}
} else {
// if the l block already belongs to subroutine 'id', continue
if (l.inSubroutine(id)) {
continue;
}
// marks the l block as belonging to subroutine 'id'
l.addToSubroutine(id, nbSubroutines);
}
// pushes each successor of l on the stack, except JSR targets
Edge e = l.successors;
while (e != null) {
// if the l block is a JSR block, then 'l.successors.next' leads
// to the JSR target (see {@link #visitJumpInsn}) and must
// therefore not be followed
if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
// pushes e.successor on the stack if it not already added
if (e.successor.next == null) {
e.successor.next = stack;
stack = e.successor;
}
}
e = e.next;
}
}
}
if (JSR != null) {
if ((l.status & VISITED2) != 0) {
continue;
}
l.status |= VISITED2;
// adds JSR to the successors of l, if it is a RET block
if ((l.status & RET) != 0) {
if (!l.inSameSubroutine(JSR)) {
Edge e = new Edge();
e.info = l.inputStackTop;
e.successor = JSR.successors.successor;
e.next = l.successors;
l.successors = e;
}
}
} else {
// if the l block already belongs to subroutine 'id', continue
if (l.inSubroutine(id)) {
continue;
}
// marks the l block as belonging to subroutine 'id'
l.addToSubroutine(id, nbSubroutines);
}
// pushes each successor of l on the stack, except JSR targets
Edge e = l.successors;
while (e != null) {
// if the l block is a JSR block, then 'l.successors.next' leads
// to the JSR target (see {@link #visitJumpInsn}) and must
// therefore not be followed
if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
// pushes e.successor on the stack if it not already added
if (e.successor.next == null) {
e.successor.next = stack;
stack = e.successor;
}
}
e = e.next;
}
}
}
// ------------------------------------------------------------------------
// Overriden Object methods
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Overriden Object methods
// ------------------------------------------------------------------------
/**
* Returns a string representation of this label.
*
* @return a string representation of this label.
*/
@Override
public String toString() {
return "L" + System.identityHashCode(this);
}
/**
* Returns a string representation of this label.
*
* @return a string representation of this label.
*/
@Override
public String toString() {
return "L" + System.identityHashCode(this);
}
}

View File

@@ -16,248 +16,248 @@ import java.util.*;
*/
public class MethodDebugVisitor extends MethodVisitor {
private final MethodVisitor visitor;
private final MethodVisitor visitor;
private boolean debug = false;
private boolean debug = false;
public MethodDebugVisitor setDebug(boolean d) {
debug = d;
return this;
}
public MethodDebugVisitor setDebug(boolean d) {
debug = d;
return this;
}
public void debugLine() {
if (!debug) {
return;
}
System.out.println();
System.out.println();
System.out.println();
}
public void debugLine() {
if (!debug) {
return;
}
System.out.println();
System.out.println();
System.out.println();
}
private final Map<Label, Integer> labels = new LinkedHashMap<>();
private final Map<Label, Integer> labels = new LinkedHashMap<>();
private static final String[] opcodes = new String[200]; // 0 -18
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); // 不可能会发生
}
}
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.ASM6, visitor);
this.visitor = visitor;
}
/** @param visitor MethodVisitor */
public MethodDebugVisitor(MethodVisitor visitor) {
super(Opcodes.ASM6, 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 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 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 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 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 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 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 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 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 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 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 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 visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
visitor.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
if (debug) {
System.out.println("mv.visitInvokeDynamicInsn(\"" + name + "\", \"" + desc + "\", null, null);");
}
}
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
visitor.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
if (debug) {
System.out.println("mv.visitInvokeDynamicInsn(\"" + name + "\", \"" + desc + "\", null, null);");
}
}
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
visitor.visitLocalVariable(name, desc, signature, start, end, index);
if (debug) {
System.out.println("mv.visitLocalVariable(\"" + name + "\", \"" + desc + "\", \"" + signature
+ "\", null, null, " + index + ");");
}
}
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
visitor.visitLocalVariable(name, desc, signature, start, end, index);
if (debug) {
System.out.println("mv.visitLocalVariable(\"" + name + "\", \"" + desc + "\", \"" + signature
+ "\", null, null, " + index + ");");
}
}
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 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 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 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 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 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 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 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 void visitEnd() {
visitor.visitEnd();
if (debug) {
System.out.println("mv.visitEnd();\r\n\r\n\r\n");
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -72,131 +72,131 @@ package org.redkale.asm;
* @author Remi Forax
*/
public abstract class ModuleVisitor {
/** The ASM API version implemented by this visitor. The value of this field must be {@link Opcodes#ASM6}. */
protected final int api;
/** The ASM API version implemented by this visitor. The value of this field must be {@link Opcodes#ASM6}. */
protected final int api;
/** The module visitor to which this visitor must delegate method calls. May be null. */
protected ModuleVisitor mv;
/** The module visitor to which this visitor must delegate method calls. May be null. */
protected ModuleVisitor mv;
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
*/
public ModuleVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
*/
public ModuleVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
* @param mv the module visitor to which this visitor must delegate method calls. May be null.
*/
public ModuleVisitor(final int api, final ModuleVisitor mv) {
if (api != Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
this.mv = mv;
}
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
* @param mv the module visitor to which this visitor must delegate method calls. May be null.
*/
public ModuleVisitor(final int api, final ModuleVisitor mv) {
if (api != Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
this.mv = mv;
}
/**
* Visit the main class of the current module.
*
* @param mainClass the internal name of the main class of the current module.
*/
public void visitMainClass(String mainClass) {
if (mv != null) {
mv.visitMainClass(mainClass);
}
}
/**
* Visit the main class of the current module.
*
* @param mainClass the internal name of the main class of the current module.
*/
public void visitMainClass(String mainClass) {
if (mv != null) {
mv.visitMainClass(mainClass);
}
}
/**
* Visit a package of the current module.
*
* @param packaze the qualified name of a package.
*/
public void visitPackage(String packaze) {
if (mv != null) {
mv.visitPackage(packaze);
}
}
/**
* Visit a package of the current module.
*
* @param packaze the qualified name of a package.
*/
public void visitPackage(String packaze) {
if (mv != null) {
mv.visitPackage(packaze);
}
}
/**
* Visits a dependence of the current module.
*
* @param module the qualified name of the dependence.
* @param access the access flag of the dependence among ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC and
* ACC_MANDATED.
* @param version the module version at compile time or null.
*/
public void visitRequire(String module, int access, String version) {
if (mv != null) {
mv.visitRequire(module, access, version);
}
}
/**
* Visits a dependence of the current module.
*
* @param module the qualified name of the dependence.
* @param access the access flag of the dependence among ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC and
* ACC_MANDATED.
* @param version the module version at compile time or null.
*/
public void visitRequire(String module, int access, String version) {
if (mv != null) {
mv.visitRequire(module, access, version);
}
}
/**
* Visit an exported package of the current module.
*
* @param packaze the qualified name of the exported package.
* @param access the access flag of the exported package, valid values are among {@code ACC_SYNTHETIC} and
* {@code ACC_MANDATED}.
* @param modules the qualified names of the modules that can access to the public classes of the exported package
* or &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visitExport(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitExport(packaze, access, modules);
}
}
/**
* Visit an exported package of the current module.
*
* @param packaze the qualified name of the exported package.
* @param access the access flag of the exported package, valid values are among {@code ACC_SYNTHETIC} and
* {@code ACC_MANDATED}.
* @param modules the qualified names of the modules that can access to the public classes of the exported package
* or &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visitExport(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitExport(packaze, access, modules);
}
}
/**
* Visit an open package of the current module.
*
* @param packaze the qualified name of the opened package.
* @param access the access flag of the opened package, valid values are among {@code ACC_SYNTHETIC} and
* {@code ACC_MANDATED}.
* @param modules the qualified names of the modules that can use deep reflection to the classes of the open package
* or &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visitOpen(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitOpen(packaze, access, modules);
}
}
/**
* Visit an open package of the current module.
*
* @param packaze the qualified name of the opened package.
* @param access the access flag of the opened package, valid values are among {@code ACC_SYNTHETIC} and
* {@code ACC_MANDATED}.
* @param modules the qualified names of the modules that can use deep reflection to the classes of the open package
* or &#60;tt&#62;null&#60;/tt&#62;.
*/
public void visitOpen(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitOpen(packaze, access, modules);
}
}
/**
* Visit a service used by the current module. The name must be the internal name of an interface or a class.
*
* @param service the internal name of the service.
*/
public void visitUse(String service) {
if (mv != null) {
mv.visitUse(service);
}
}
/**
* Visit a service used by the current module. The name must be the internal name of an interface or a class.
*
* @param service the internal name of the service.
*/
public void visitUse(String service) {
if (mv != null) {
mv.visitUse(service);
}
}
/**
* Visit an implementation of a service.
*
* @param service the internal name of the service
* @param providers the internal names of the implementations of the service (there is at least one provider).
*/
public void visitProvide(String service, String... providers) {
if (mv != null) {
mv.visitProvide(service, providers);
}
}
/**
* Visit an implementation of a service.
*
* @param service the internal name of the service
* @param providers the internal names of the implementations of the service (there is at least one provider).
*/
public void visitProvide(String service, String... providers) {
if (mv != null) {
mv.visitProvide(service, providers);
}
}
/**
* Visits the end of the module. This method, which is the last one to be called, is used to inform the visitor that
* everything have been visited.
*/
public void visitEnd() {
if (mv != null) {
mv.visitEnd();
}
}
/**
* Visits the end of the module. This method, which is the last one to be called, is used to inform the visitor that
* everything have been visited.
*/
public void visitEnd() {
if (mv != null) {
mv.visitEnd();
}
}
}

View File

@@ -61,228 +61,228 @@ package org.redkale.asm;
/** @author Remi Forax */
final class ModuleWriter extends ModuleVisitor {
/** The class writer to which this Module attribute must be added. */
private final ClassWriter cw;
/** The class writer to which this Module attribute must be added. */
private final ClassWriter cw;
/** size in byte of the Module attribute. */
int size;
/** size in byte of the Module attribute. */
int size;
/** Number of attributes associated with the current module (Version, ConcealPackages, etc) */
int attributeCount;
/** Number of attributes associated with the current module (Version, ConcealPackages, etc) */
int attributeCount;
/** Size in bytes of the attributes associated with the current module */
int attributesSize;
/** Size in bytes of the attributes associated with the current module */
int attributesSize;
/** module name index in the constant pool */
private final int name;
/** module name index in the constant pool */
private final int name;
/** module access flags */
private final int access;
/** module access flags */
private final int access;
/** module version index in the constant pool or 0 */
private final int version;
/** module version index in the constant pool or 0 */
private final int version;
/** module main class index in the constant pool or 0 */
private int mainClass;
/** module main class index in the constant pool or 0 */
private int mainClass;
/** number of packages */
private int packageCount;
/** number of packages */
private int packageCount;
/**
* The packages in bytecode form. This byte vector only contains the items themselves, the number of items is store
* in packageCount
*/
private ByteVector packages;
/**
* The packages in bytecode form. This byte vector only contains the items themselves, the number of items is store
* in packageCount
*/
private ByteVector packages;
/** number of requires items */
private int requireCount;
/** number of requires items */
private int requireCount;
/**
* The requires items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in requireCount
*/
private ByteVector requires;
/**
* The requires items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in requireCount
*/
private ByteVector requires;
/** number of exports items */
private int exportCount;
/** number of exports items */
private int exportCount;
/**
* The exports items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in exportCount
*/
private ByteVector exports;
/**
* The exports items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in exportCount
*/
private ByteVector exports;
/** number of opens items */
private int openCount;
/** number of opens items */
private int openCount;
/**
* The opens items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in openCount
*/
private ByteVector opens;
/**
* The opens items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in openCount
*/
private ByteVector opens;
/** number of uses items */
private int useCount;
/** number of uses items */
private int useCount;
/**
* The uses items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in useCount
*/
private ByteVector uses;
/**
* The uses items in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in useCount
*/
private ByteVector uses;
/** number of provides items */
private int provideCount;
/** number of provides items */
private int provideCount;
/**
* The uses provides in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in provideCount
*/
private ByteVector provides;
/**
* The uses provides in bytecode form. This byte vector only contains the items themselves, the number of items is
* store in provideCount
*/
private ByteVector provides;
ModuleWriter(final ClassWriter cw, final int name, final int access, final int version) {
super(Opcodes.ASM6);
this.cw = cw;
this.size = 16; // name + access + version + 5 counts
this.name = name;
this.access = access;
this.version = version;
}
ModuleWriter(final ClassWriter cw, final int name, final int access, final int version) {
super(Opcodes.ASM6);
this.cw = cw;
this.size = 16; // name + access + version + 5 counts
this.name = name;
this.access = access;
this.version = version;
}
@Override
public void visitMainClass(String mainClass) {
if (this.mainClass == 0) { // protect against several calls to visitMainClass
cw.newUTF8("ModuleMainClass");
attributeCount++;
attributesSize += 8;
}
this.mainClass = cw.newClass(mainClass);
}
@Override
public void visitMainClass(String mainClass) {
if (this.mainClass == 0) { // protect against several calls to visitMainClass
cw.newUTF8("ModuleMainClass");
attributeCount++;
attributesSize += 8;
}
this.mainClass = cw.newClass(mainClass);
}
@Override
public void visitPackage(String packaze) {
if (packages == null) {
// protect against several calls to visitPackage
cw.newUTF8("ModulePackages");
packages = new ByteVector();
attributeCount++;
attributesSize += 8;
}
packages.putShort(cw.newPackage(packaze));
packageCount++;
attributesSize += 2;
}
@Override
public void visitPackage(String packaze) {
if (packages == null) {
// protect against several calls to visitPackage
cw.newUTF8("ModulePackages");
packages = new ByteVector();
attributeCount++;
attributesSize += 8;
}
packages.putShort(cw.newPackage(packaze));
packageCount++;
attributesSize += 2;
}
@Override
public void visitRequire(String module, int access, String version) {
if (requires == null) {
requires = new ByteVector();
}
requires.putShort(cw.newModule(module)).putShort(access).putShort(version == null ? 0 : cw.newUTF8(version));
requireCount++;
size += 6;
}
@Override
public void visitRequire(String module, int access, String version) {
if (requires == null) {
requires = new ByteVector();
}
requires.putShort(cw.newModule(module)).putShort(access).putShort(version == null ? 0 : cw.newUTF8(version));
requireCount++;
size += 6;
}
@Override
public void visitExport(String packaze, int access, String... modules) {
if (exports == null) {
exports = new ByteVector();
}
exports.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
exports.putShort(0);
size += 6;
} else {
exports.putShort(modules.length);
for (String module : modules) {
exports.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
exportCount++;
}
@Override
public void visitExport(String packaze, int access, String... modules) {
if (exports == null) {
exports = new ByteVector();
}
exports.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
exports.putShort(0);
size += 6;
} else {
exports.putShort(modules.length);
for (String module : modules) {
exports.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
exportCount++;
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
if (opens == null) {
opens = new ByteVector();
}
opens.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
opens.putShort(0);
size += 6;
} else {
opens.putShort(modules.length);
for (String module : modules) {
opens.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
openCount++;
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
if (opens == null) {
opens = new ByteVector();
}
opens.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
opens.putShort(0);
size += 6;
} else {
opens.putShort(modules.length);
for (String module : modules) {
opens.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
openCount++;
}
@Override
public void visitUse(String service) {
if (uses == null) {
uses = new ByteVector();
}
uses.putShort(cw.newClass(service));
useCount++;
size += 2;
}
@Override
public void visitUse(String service) {
if (uses == null) {
uses = new ByteVector();
}
uses.putShort(cw.newClass(service));
useCount++;
size += 2;
}
@Override
public void visitProvide(String service, String... providers) {
if (provides == null) {
provides = new ByteVector();
}
provides.putShort(cw.newClass(service));
provides.putShort(providers.length);
for (String provider : providers) {
provides.putShort(cw.newClass(provider));
}
provideCount++;
size += 4 + 2 * providers.length;
}
@Override
public void visitProvide(String service, String... providers) {
if (provides == null) {
provides = new ByteVector();
}
provides.putShort(cw.newClass(service));
provides.putShort(providers.length);
for (String provider : providers) {
provides.putShort(cw.newClass(provider));
}
provideCount++;
size += 4 + 2 * providers.length;
}
@Override
public void visitEnd() {
// empty
}
@Override
public void visitEnd() {
// empty
}
void putAttributes(ByteVector out) {
if (mainClass != 0) {
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
}
if (packages != null) {
out.putShort(cw.newUTF8("ModulePackages"))
.putInt(2 + 2 * packageCount)
.putShort(packageCount)
.putByteArray(packages.data, 0, packages.length);
}
}
void putAttributes(ByteVector out) {
if (mainClass != 0) {
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
}
if (packages != null) {
out.putShort(cw.newUTF8("ModulePackages"))
.putInt(2 + 2 * packageCount)
.putShort(packageCount)
.putByteArray(packages.data, 0, packages.length);
}
}
void put(ByteVector out) {
out.putInt(size);
out.putShort(name).putShort(access).putShort(version);
out.putShort(requireCount);
if (requires != null) {
out.putByteArray(requires.data, 0, requires.length);
}
out.putShort(exportCount);
if (exports != null) {
out.putByteArray(exports.data, 0, exports.length);
}
out.putShort(openCount);
if (opens != null) {
out.putByteArray(opens.data, 0, opens.length);
}
out.putShort(useCount);
if (uses != null) {
out.putByteArray(uses.data, 0, uses.length);
}
out.putShort(provideCount);
if (provides != null) {
out.putByteArray(provides.data, 0, provides.length);
}
}
void put(ByteVector out) {
out.putInt(size);
out.putShort(name).putShort(access).putShort(version);
out.putShort(requireCount);
if (requires != null) {
out.putByteArray(requires.data, 0, requires.length);
}
out.putShort(exportCount);
if (exports != null) {
out.putByteArray(exports.data, 0, exports.length);
}
out.putShort(openCount);
if (opens != null) {
out.putByteArray(opens.data, 0, opens.length);
}
out.putShort(useCount);
if (uses != null) {
out.putByteArray(uses.data, 0, uses.length);
}
out.putShort(provideCount);
if (provides != null) {
out.putByteArray(provides.data, 0, provides.length);
}
}
}

View File

@@ -69,334 +69,334 @@ package org.redkale.asm;
*/
public interface Opcodes {
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8;
int ASM5 = 5 << 16 | 0 << 8;
int ASM6 = 6 << 16 | 0 << 8;
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8;
int ASM5 = 5 << 16 | 0 << 8;
int ASM6 = 6 << 16 | 0 << 8;
// versions
// versions
int V1_1 = 3 << 16 | 45;
int V1_2 = 0 << 16 | 46;
int V1_3 = 0 << 16 | 47;
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
int V9 = 0 << 16 | 53;
int V10 = 0 << 16 | 54;
int V11 = 0 << 16 | 55;
int V1_1 = 3 << 16 | 45;
int V1_2 = 0 << 16 | 46;
int V1_3 = 0 << 16 | 47;
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
int V9 = 0 << 16 | 53;
int V10 = 0 << 16 | 54;
int V11 = 0 << 16 | 55;
// access flags
// access flags
int ACC_PUBLIC = 0x0001; // class, field, method
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_OPEN = 0x0020; // module
int ACC_TRANSITIVE = 0x0020; // module requires
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
int ACC_STATIC_PHASE = 0x0040; // module requires
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter, module, module *
int ACC_MODULE = 0x8000; // class
int ACC_PUBLIC = 0x0001; // class, field, method
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_OPEN = 0x0020; // module
int ACC_TRANSITIVE = 0x0020; // module requires
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
int ACC_STATIC_PHASE = 0x0040; // module requires
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter, module, module *
int ACC_MODULE = 0x8000; // class
// ASM specific pseudo access flags
// ASM specific pseudo access flags
int ACC_DEPRECATED = 0x20000; // class, field, method
int ACC_DEPRECATED = 0x20000; // class, field, method
// types for NEWARRAY
// types for NEWARRAY
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
// tags for Handle
// tags for Handle
int H_GETFIELD = 1;
int H_GETSTATIC = 2;
int H_PUTFIELD = 3;
int H_PUTSTATIC = 4;
int H_INVOKEVIRTUAL = 5;
int H_INVOKESTATIC = 6;
int H_INVOKESPECIAL = 7;
int H_NEWINVOKESPECIAL = 8;
int H_INVOKEINTERFACE = 9;
int H_GETFIELD = 1;
int H_GETSTATIC = 2;
int H_PUTFIELD = 3;
int H_PUTSTATIC = 4;
int H_INVOKEVIRTUAL = 5;
int H_INVOKESTATIC = 6;
int H_INVOKESPECIAL = 7;
int H_NEWINVOKESPECIAL = 8;
int H_INVOKEINTERFACE = 9;
// stack map frame types
// stack map frame types
/** Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
int F_NEW = -1;
/** Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
int F_NEW = -1;
/** Represents a compressed frame with complete frame data. */
int F_FULL = 0;
/** Represents a compressed frame with complete frame data. */
int F_FULL = 0;
/**
* Represents a compressed frame where locals are the same as the locals in the previous frame, except that
* additional 1-3 locals are defined, and with an empty stack.
*/
int F_APPEND = 1;
/**
* Represents a compressed frame where locals are the same as the locals in the previous frame, except that
* additional 1-3 locals are defined, and with an empty stack.
*/
int F_APPEND = 1;
/**
* Represents a compressed frame where locals are the same as the locals in the previous frame, except that the last
* 1-3 locals are absent and with an empty stack.
*/
int F_CHOP = 2;
/**
* Represents a compressed frame where locals are the same as the locals in the previous frame, except that the last
* 1-3 locals are absent and with an empty stack.
*/
int F_CHOP = 2;
/** Represents a compressed frame with exactly the same locals as the previous frame and with an empty stack. */
int F_SAME = 3;
/** Represents a compressed frame with exactly the same locals as the previous frame and with an empty stack. */
int F_SAME = 3;
/**
* Represents a compressed frame with exactly the same locals as the previous frame and with a single value on the
* stack.
*/
int F_SAME1 = 4;
/**
* Represents a compressed frame with exactly the same locals as the previous frame and with a single value on the
* stack.
*/
int F_SAME1 = 4;
// Do not try to change the following code to use auto-boxing,
// these values are compared by reference and not by value
// The constructor of Integer was deprecated in 9
// but we are stuck with it by backward compatibility
@SuppressWarnings("deprecation")
Integer TOP = new Integer(0);
// Do not try to change the following code to use auto-boxing,
// these values are compared by reference and not by value
// The constructor of Integer was deprecated in 9
// but we are stuck with it by backward compatibility
@SuppressWarnings("deprecation")
Integer TOP = new Integer(0);
@SuppressWarnings("deprecation")
Integer INTEGER = new Integer(1);
@SuppressWarnings("deprecation")
Integer INTEGER = new Integer(1);
@SuppressWarnings("deprecation")
Integer FLOAT = new Integer(2);
@SuppressWarnings("deprecation")
Integer FLOAT = new Integer(2);
@SuppressWarnings("deprecation")
Integer DOUBLE = new Integer(3);
@SuppressWarnings("deprecation")
Integer DOUBLE = new Integer(3);
@SuppressWarnings("deprecation")
Integer LONG = new Integer(4);
@SuppressWarnings("deprecation")
Integer LONG = new Integer(4);
@SuppressWarnings("deprecation")
Integer NULL = new Integer(5);
@SuppressWarnings("deprecation")
Integer NULL = new Integer(5);
@SuppressWarnings("deprecation")
Integer UNINITIALIZED_THIS = new Integer(6);
@SuppressWarnings("deprecation")
Integer UNINITIALIZED_THIS = new Integer(6);
// opcodes // visit method (- = idem)
// opcodes // visit method (- = idem)
int NOP = 0; // visitInsn
int ACONST_NULL = 1; // -
int ICONST_M1 = 2; // -
int ICONST_0 = 3; // -
int ICONST_1 = 4; // -
int ICONST_2 = 5; // -
int ICONST_3 = 6; // -
int ICONST_4 = 7; // -
int ICONST_5 = 8; // -
int LCONST_0 = 9; // -
int LCONST_1 = 10; // -
int FCONST_0 = 11; // -
int FCONST_1 = 12; // -
int FCONST_2 = 13; // -
int DCONST_0 = 14; // -
int DCONST_1 = 15; // -
int BIPUSH = 16; // visitIntInsn
int SIPUSH = 17; // -
int LDC = 18; // visitLdcInsn
// int LDC_W = 19; // -
// int LDC2_W = 20; // -
int ILOAD = 21; // visitVarInsn
int LLOAD = 22; // -
int FLOAD = 23; // -
int DLOAD = 24; // -
int ALOAD = 25; // -
// int ILOAD_0 = 26; // -
// int ILOAD_1 = 27; // -
// int ILOAD_2 = 28; // -
// int ILOAD_3 = 29; // -
// int LLOAD_0 = 30; // -
// int LLOAD_1 = 31; // -
// int LLOAD_2 = 32; // -
// int LLOAD_3 = 33; // -
// int FLOAD_0 = 34; // -
// int FLOAD_1 = 35; // -
// int FLOAD_2 = 36; // -
// int FLOAD_3 = 37; // -
// int DLOAD_0 = 38; // -
// int DLOAD_1 = 39; // -
// int DLOAD_2 = 40; // -
// int DLOAD_3 = 41; // -
// int ALOAD_0 = 42; // -
// int ALOAD_1 = 43; // -
// int ALOAD_2 = 44; // -
// int ALOAD_3 = 45; // -
int IALOAD = 46; // visitInsn
int LALOAD = 47; // -
int FALOAD = 48; // -
int DALOAD = 49; // -
int AALOAD = 50; // -
int BALOAD = 51; // -
int CALOAD = 52; // -
int SALOAD = 53; // -
int ISTORE = 54; // visitVarInsn
int LSTORE = 55; // -
int FSTORE = 56; // -
int DSTORE = 57; // -
int ASTORE = 58; // -
// int ISTORE_0 = 59; // -
// int ISTORE_1 = 60; // -
// int ISTORE_2 = 61; // -
// int ISTORE_3 = 62; // -
// int LSTORE_0 = 63; // -
// int LSTORE_1 = 64; // -
// int LSTORE_2 = 65; // -
// int LSTORE_3 = 66; // -
// int FSTORE_0 = 67; // -
// int FSTORE_1 = 68; // -
// int FSTORE_2 = 69; // -
// int FSTORE_3 = 70; // -
// int DSTORE_0 = 71; // -
// int DSTORE_1 = 72; // -
// int DSTORE_2 = 73; // -
// int DSTORE_3 = 74; // -
// int ASTORE_0 = 75; // -
// int ASTORE_1 = 76; // -
// int ASTORE_2 = 77; // -
// int ASTORE_3 = 78; // -
int IASTORE = 79; // visitInsn
int LASTORE = 80; // -
int FASTORE = 81; // -
int DASTORE = 82; // -
int AASTORE = 83; // -
int BASTORE = 84; // -
int CASTORE = 85; // -
int SASTORE = 86; // -
int POP = 87; // -
int POP2 = 88; // -
int DUP = 89; // -
int DUP_X1 = 90; // -
int DUP_X2 = 91; // -
int DUP2 = 92; // -
int DUP2_X1 = 93; // -
int DUP2_X2 = 94; // -
int SWAP = 95; // -
int IADD = 96; // -
int LADD = 97; // -
int FADD = 98; // -
int DADD = 99; // -
int ISUB = 100; // -
int LSUB = 101; // -
int FSUB = 102; // -
int DSUB = 103; // -
int IMUL = 104; // -
int LMUL = 105; // -
int FMUL = 106; // -
int DMUL = 107; // -
int IDIV = 108; // -
int LDIV = 109; // -
int FDIV = 110; // -
int DDIV = 111; // -
int IREM = 112; // -
int LREM = 113; // -
int FREM = 114; // -
int DREM = 115; // -
int INEG = 116; // -
int LNEG = 117; // -
int FNEG = 118; // -
int DNEG = 119; // -
int ISHL = 120; // -
int LSHL = 121; // -
int ISHR = 122; // -
int LSHR = 123; // -
int IUSHR = 124; // -
int LUSHR = 125; // -
int IAND = 126; // -
int LAND = 127; // -
int IOR = 128; // -
int LOR = 129; // -
int IXOR = 130; // -
int LXOR = 131; // -
int IINC = 132; // visitIincInsn
int I2L = 133; // visitInsn
int I2F = 134; // -
int I2D = 135; // -
int L2I = 136; // -
int L2F = 137; // -
int L2D = 138; // -
int F2I = 139; // -
int F2L = 140; // -
int F2D = 141; // -
int D2I = 142; // -
int D2L = 143; // -
int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
int LCMP = 148; // -
int FCMPL = 149; // -
int FCMPG = 150; // -
int DCMPL = 151; // -
int DCMPG = 152; // -
int IFEQ = 153; // visitJumpInsn
int IFNE = 154; // -
int IFLT = 155; // -
int IFGE = 156; // -
int IFGT = 157; // -
int IFLE = 158; // -
int IF_ICMPEQ = 159; // -
int IF_ICMPNE = 160; // -
int IF_ICMPLT = 161; // -
int IF_ICMPGE = 162; // -
int IF_ICMPGT = 163; // -
int IF_ICMPLE = 164; // -
int IF_ACMPEQ = 165; // -
int IF_ACMPNE = 166; // -
int GOTO = 167; // -
int JSR = 168; // -
int RET = 169; // visitVarInsn
int TABLESWITCH = 170; // visiTableSwitchInsn
int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
int PUTSTATIC = 179; // -
int GETFIELD = 180; // -
int PUTFIELD = 181; // -
int INVOKEVIRTUAL = 182; // visitMethodInsn
int INVOKESPECIAL = 183; // -
int INVOKESTATIC = 184; // -
int INVOKEINTERFACE = 185; // -
int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
int NEW = 187; // visitTypeInsn
int NEWARRAY = 188; // visitIntInsn
int ANEWARRAY = 189; // visitTypeInsn
int ARRAYLENGTH = 190; // visitInsn
int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
int MONITORENTER = 194; // visitInsn
int MONITOREXIT = 195; // -
// int WIDE = 196; // NOT VISITED
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
// int GOTO_W = 200; // -
// int JSR_W = 201; // -
int NOP = 0; // visitInsn
int ACONST_NULL = 1; // -
int ICONST_M1 = 2; // -
int ICONST_0 = 3; // -
int ICONST_1 = 4; // -
int ICONST_2 = 5; // -
int ICONST_3 = 6; // -
int ICONST_4 = 7; // -
int ICONST_5 = 8; // -
int LCONST_0 = 9; // -
int LCONST_1 = 10; // -
int FCONST_0 = 11; // -
int FCONST_1 = 12; // -
int FCONST_2 = 13; // -
int DCONST_0 = 14; // -
int DCONST_1 = 15; // -
int BIPUSH = 16; // visitIntInsn
int SIPUSH = 17; // -
int LDC = 18; // visitLdcInsn
// int LDC_W = 19; // -
// int LDC2_W = 20; // -
int ILOAD = 21; // visitVarInsn
int LLOAD = 22; // -
int FLOAD = 23; // -
int DLOAD = 24; // -
int ALOAD = 25; // -
// int ILOAD_0 = 26; // -
// int ILOAD_1 = 27; // -
// int ILOAD_2 = 28; // -
// int ILOAD_3 = 29; // -
// int LLOAD_0 = 30; // -
// int LLOAD_1 = 31; // -
// int LLOAD_2 = 32; // -
// int LLOAD_3 = 33; // -
// int FLOAD_0 = 34; // -
// int FLOAD_1 = 35; // -
// int FLOAD_2 = 36; // -
// int FLOAD_3 = 37; // -
// int DLOAD_0 = 38; // -
// int DLOAD_1 = 39; // -
// int DLOAD_2 = 40; // -
// int DLOAD_3 = 41; // -
// int ALOAD_0 = 42; // -
// int ALOAD_1 = 43; // -
// int ALOAD_2 = 44; // -
// int ALOAD_3 = 45; // -
int IALOAD = 46; // visitInsn
int LALOAD = 47; // -
int FALOAD = 48; // -
int DALOAD = 49; // -
int AALOAD = 50; // -
int BALOAD = 51; // -
int CALOAD = 52; // -
int SALOAD = 53; // -
int ISTORE = 54; // visitVarInsn
int LSTORE = 55; // -
int FSTORE = 56; // -
int DSTORE = 57; // -
int ASTORE = 58; // -
// int ISTORE_0 = 59; // -
// int ISTORE_1 = 60; // -
// int ISTORE_2 = 61; // -
// int ISTORE_3 = 62; // -
// int LSTORE_0 = 63; // -
// int LSTORE_1 = 64; // -
// int LSTORE_2 = 65; // -
// int LSTORE_3 = 66; // -
// int FSTORE_0 = 67; // -
// int FSTORE_1 = 68; // -
// int FSTORE_2 = 69; // -
// int FSTORE_3 = 70; // -
// int DSTORE_0 = 71; // -
// int DSTORE_1 = 72; // -
// int DSTORE_2 = 73; // -
// int DSTORE_3 = 74; // -
// int ASTORE_0 = 75; // -
// int ASTORE_1 = 76; // -
// int ASTORE_2 = 77; // -
// int ASTORE_3 = 78; // -
int IASTORE = 79; // visitInsn
int LASTORE = 80; // -
int FASTORE = 81; // -
int DASTORE = 82; // -
int AASTORE = 83; // -
int BASTORE = 84; // -
int CASTORE = 85; // -
int SASTORE = 86; // -
int POP = 87; // -
int POP2 = 88; // -
int DUP = 89; // -
int DUP_X1 = 90; // -
int DUP_X2 = 91; // -
int DUP2 = 92; // -
int DUP2_X1 = 93; // -
int DUP2_X2 = 94; // -
int SWAP = 95; // -
int IADD = 96; // -
int LADD = 97; // -
int FADD = 98; // -
int DADD = 99; // -
int ISUB = 100; // -
int LSUB = 101; // -
int FSUB = 102; // -
int DSUB = 103; // -
int IMUL = 104; // -
int LMUL = 105; // -
int FMUL = 106; // -
int DMUL = 107; // -
int IDIV = 108; // -
int LDIV = 109; // -
int FDIV = 110; // -
int DDIV = 111; // -
int IREM = 112; // -
int LREM = 113; // -
int FREM = 114; // -
int DREM = 115; // -
int INEG = 116; // -
int LNEG = 117; // -
int FNEG = 118; // -
int DNEG = 119; // -
int ISHL = 120; // -
int LSHL = 121; // -
int ISHR = 122; // -
int LSHR = 123; // -
int IUSHR = 124; // -
int LUSHR = 125; // -
int IAND = 126; // -
int LAND = 127; // -
int IOR = 128; // -
int LOR = 129; // -
int IXOR = 130; // -
int LXOR = 131; // -
int IINC = 132; // visitIincInsn
int I2L = 133; // visitInsn
int I2F = 134; // -
int I2D = 135; // -
int L2I = 136; // -
int L2F = 137; // -
int L2D = 138; // -
int F2I = 139; // -
int F2L = 140; // -
int F2D = 141; // -
int D2I = 142; // -
int D2L = 143; // -
int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
int LCMP = 148; // -
int FCMPL = 149; // -
int FCMPG = 150; // -
int DCMPL = 151; // -
int DCMPG = 152; // -
int IFEQ = 153; // visitJumpInsn
int IFNE = 154; // -
int IFLT = 155; // -
int IFGE = 156; // -
int IFGT = 157; // -
int IFLE = 158; // -
int IF_ICMPEQ = 159; // -
int IF_ICMPNE = 160; // -
int IF_ICMPLT = 161; // -
int IF_ICMPGE = 162; // -
int IF_ICMPGT = 163; // -
int IF_ICMPLE = 164; // -
int IF_ACMPEQ = 165; // -
int IF_ACMPNE = 166; // -
int GOTO = 167; // -
int JSR = 168; // -
int RET = 169; // visitVarInsn
int TABLESWITCH = 170; // visiTableSwitchInsn
int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
int PUTSTATIC = 179; // -
int GETFIELD = 180; // -
int PUTFIELD = 181; // -
int INVOKEVIRTUAL = 182; // visitMethodInsn
int INVOKESPECIAL = 183; // -
int INVOKESTATIC = 184; // -
int INVOKEINTERFACE = 185; // -
int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
int NEW = 187; // visitTypeInsn
int NEWARRAY = 188; // visitIntInsn
int ANEWARRAY = 189; // visitTypeInsn
int ARRAYLENGTH = 190; // visitInsn
int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
int MONITORENTER = 194; // visitInsn
int MONITOREXIT = 195; // -
// int WIDE = 196; // NOT VISITED
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
// int GOTO_W = 200; // -
// int JSR_W = 201; // -
}

File diff suppressed because it is too large Load Diff

View File

@@ -66,130 +66,130 @@ package org.redkale.asm;
*/
public class TypePath {
/** A type path step that steps into the element type of an array type. See {@link #getStep getStep}. */
public static final int ARRAY_ELEMENT = 0;
/** A type path step that steps into the element type of an array type. See {@link #getStep getStep}. */
public static final int ARRAY_ELEMENT = 0;
/** A type path step that steps into the nested type of a class type. See {@link #getStep getStep}. */
public static final int INNER_TYPE = 1;
/** A type path step that steps into the nested type of a class type. See {@link #getStep getStep}. */
public static final int INNER_TYPE = 1;
/** A type path step that steps into the bound of a wildcard type. See {@link #getStep getStep}. */
public static final int WILDCARD_BOUND = 2;
/** A type path step that steps into the bound of a wildcard type. See {@link #getStep getStep}. */
public static final int WILDCARD_BOUND = 2;
/** A type path step that steps into a type argument of a generic type. See {@link #getStep getStep}. */
public static final int TYPE_ARGUMENT = 3;
/** A type path step that steps into a type argument of a generic type. See {@link #getStep getStep}. */
public static final int TYPE_ARGUMENT = 3;
/** The byte array where the path is stored, in Java class file format. */
byte[] b;
/** The byte array where the path is stored, in Java class file format. */
byte[] b;
/** The offset of the first byte of the type path in 'b'. */
int offset;
/** The offset of the first byte of the type path in 'b'. */
int offset;
/**
* Creates a new type path.
*
* @param b the byte array containing the type path in Java class file format.
* @param offset the offset of the first byte of the type path in 'b'.
*/
TypePath(byte[] b, int offset) {
this.b = b;
this.offset = offset;
}
/**
* Creates a new type path.
*
* @param b the byte array containing the type path in Java class file format.
* @param offset the offset of the first byte of the type path in 'b'.
*/
TypePath(byte[] b, int offset) {
this.b = b;
this.offset = offset;
}
/**
* Returns the length of this path.
*
* @return the length of this path.
*/
public int getLength() {
return b[offset];
}
/**
* Returns the length of this path.
*
* @return the length of this path.
*/
public int getLength() {
return b[offset];
}
/**
* Returns the value of the given step of this path.
*
* @param index an index between 0 and {@link #getLength()}, exclusive.
* @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE INNER_TYPE}, {@link #WILDCARD_BOUND
* WILDCARD_BOUND}, or {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*/
public int getStep(int index) {
return b[offset + 2 * index + 1];
}
/**
* Returns the value of the given step of this path.
*
* @param index an index between 0 and {@link #getLength()}, exclusive.
* @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE INNER_TYPE}, {@link #WILDCARD_BOUND
* WILDCARD_BOUND}, or {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*/
public int getStep(int index) {
return b[offset + 2 * index + 1];
}
/**
* Returns the index of the type argument that the given step is stepping into. This method should only be used for
* steps whose value is {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*
* @param index an index between 0 and {@link #getLength()}, exclusive.
* @return the index of the type argument that the given step is stepping into.
*/
public int getStepArgument(int index) {
return b[offset + 2 * index + 2];
}
/**
* Returns the index of the type argument that the given step is stepping into. This method should only be used for
* steps whose value is {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*
* @param index an index between 0 and {@link #getLength()}, exclusive.
* @return the index of the type argument that the given step is stepping into.
*/
public int getStepArgument(int index) {
return b[offset + 2 * index + 2];
}
/**
* Converts a type path in string form, in the format used by {@link #toString()}, into a TypePath object.
*
* @param typePath a type path in string form, in the format used by {@link #toString()}. May be null or empty.
* @return the corresponding TypePath object, or null if the path is empty.
*/
public static TypePath fromString(final String typePath) {
if (typePath == null || typePath.isEmpty()) {
return null;
}
int n = typePath.length();
ByteVector out = new ByteVector(n);
out.putByte(0);
for (int i = 0; i < n; ) {
char c = typePath.charAt(i++);
if (c == '[') {
out.put11(ARRAY_ELEMENT, 0);
} else if (c == '.') {
out.put11(INNER_TYPE, 0);
} else if (c == '*') {
out.put11(WILDCARD_BOUND, 0);
} else if (c >= '0' && c <= '9') {
int typeArg = c - '0';
while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
typeArg = typeArg * 10 + c - '0';
i += 1;
}
if (i < n && typePath.charAt(i) == ';') {
i += 1;
}
out.put11(TYPE_ARGUMENT, typeArg);
}
}
out.data[0] = (byte) (out.length / 2);
return new TypePath(out.data, 0);
}
/**
* Converts a type path in string form, in the format used by {@link #toString()}, into a TypePath object.
*
* @param typePath a type path in string form, in the format used by {@link #toString()}. May be null or empty.
* @return the corresponding TypePath object, or null if the path is empty.
*/
public static TypePath fromString(final String typePath) {
if (typePath == null || typePath.isEmpty()) {
return null;
}
int n = typePath.length();
ByteVector out = new ByteVector(n);
out.putByte(0);
for (int i = 0; i < n; ) {
char c = typePath.charAt(i++);
if (c == '[') {
out.put11(ARRAY_ELEMENT, 0);
} else if (c == '.') {
out.put11(INNER_TYPE, 0);
} else if (c == '*') {
out.put11(WILDCARD_BOUND, 0);
} else if (c >= '0' && c <= '9') {
int typeArg = c - '0';
while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
typeArg = typeArg * 10 + c - '0';
i += 1;
}
if (i < n && typePath.charAt(i) == ';') {
i += 1;
}
out.put11(TYPE_ARGUMENT, typeArg);
}
}
out.data[0] = (byte) (out.length / 2);
return new TypePath(out.data, 0);
}
/**
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT ARRAY_ELEMENT} steps are represented
* with '[', {@link #INNER_TYPE INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps with '*'
* and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type argument index in decimal form followed by ';'.
*/
@Override
public String toString() {
int length = getLength();
StringBuilder result = new StringBuilder(length * 2);
for (int i = 0; i < length; ++i) {
switch (getStep(i)) {
case ARRAY_ELEMENT:
result.append('[');
break;
case INNER_TYPE:
result.append('.');
break;
case WILDCARD_BOUND:
result.append('*');
break;
case TYPE_ARGUMENT:
result.append(getStepArgument(i)).append(';');
break;
default:
result.append('_');
}
}
return result.toString();
}
/**
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT ARRAY_ELEMENT} steps are represented
* with '[', {@link #INNER_TYPE INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps with '*'
* and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type argument index in decimal form followed by ';'.
*/
@Override
public String toString() {
int length = getLength();
StringBuilder result = new StringBuilder(length * 2);
for (int i = 0; i < length; ++i) {
switch (getStep(i)) {
case ARRAY_ELEMENT:
result.append('[');
break;
case INNER_TYPE:
result.append('.');
break;
case WILDCARD_BOUND:
result.append('*');
break;
case TYPE_ARGUMENT:
result.append(getStepArgument(i)).append(';');
break;
default:
result.append('_');
}
}
return result.toString();
}
}

View File

@@ -68,335 +68,335 @@ package org.redkale.asm;
*/
public class TypeReference {
/** The sort of type references that target a type parameter of a generic class. See {@link #getSort getSort}. */
public static final int CLASS_TYPE_PARAMETER = 0x00;
/** The sort of type references that target a type parameter of a generic class. See {@link #getSort getSort}. */
public static final int CLASS_TYPE_PARAMETER = 0x00;
/** The sort of type references that target a type parameter of a generic method. See {@link #getSort getSort}. */
public static final int METHOD_TYPE_PARAMETER = 0x01;
/** The sort of type references that target a type parameter of a generic method. See {@link #getSort getSort}. */
public static final int METHOD_TYPE_PARAMETER = 0x01;
/**
* The sort of type references that target the super class of a class or one of the interfaces it implements. See
* {@link #getSort getSort}.
*/
public static final int CLASS_EXTENDS = 0x10;
/**
* The sort of type references that target the super class of a class or one of the interfaces it implements. See
* {@link #getSort getSort}.
*/
public static final int CLASS_EXTENDS = 0x10;
/**
* The sort of type references that target a bound of a type parameter of a generic class. See {@link #getSort
* getSort}.
*/
public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
/**
* The sort of type references that target a bound of a type parameter of a generic class. See {@link #getSort
* getSort}.
*/
public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
/**
* The sort of type references that target a bound of a type parameter of a generic method. See {@link #getSort
* getSort}.
*/
public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
/**
* The sort of type references that target a bound of a type parameter of a generic method. See {@link #getSort
* getSort}.
*/
public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
/** The sort of type references that target the type of a field. See {@link #getSort getSort}. */
public static final int FIELD = 0x13;
/** The sort of type references that target the type of a field. See {@link #getSort getSort}. */
public static final int FIELD = 0x13;
/** The sort of type references that target the return type of a method. See {@link #getSort getSort}. */
public static final int METHOD_RETURN = 0x14;
/** The sort of type references that target the return type of a method. See {@link #getSort getSort}. */
public static final int METHOD_RETURN = 0x14;
/** The sort of type references that target the receiver type of a method. See {@link #getSort getSort}. */
public static final int METHOD_RECEIVER = 0x15;
/** The sort of type references that target the receiver type of a method. See {@link #getSort getSort}. */
public static final int METHOD_RECEIVER = 0x15;
/**
* The sort of type references that target the type of a formal parameter of a method. See {@link #getSort getSort}.
*/
public static final int METHOD_FORMAL_PARAMETER = 0x16;
/**
* The sort of type references that target the type of a formal parameter of a method. See {@link #getSort getSort}.
*/
public static final int METHOD_FORMAL_PARAMETER = 0x16;
/**
* The sort of type references that target the type of an exception declared in the throws clause of a method. See
* {@link #getSort getSort}.
*/
public static final int THROWS = 0x17;
/**
* The sort of type references that target the type of an exception declared in the throws clause of a method. See
* {@link #getSort getSort}.
*/
public static final int THROWS = 0x17;
/**
* The sort of type references that target the type of a local variable in a method. See {@link #getSort getSort}.
*/
public static final int LOCAL_VARIABLE = 0x40;
/**
* The sort of type references that target the type of a local variable in a method. See {@link #getSort getSort}.
*/
public static final int LOCAL_VARIABLE = 0x40;
/**
* The sort of type references that target the type of a resource variable in a method. See {@link #getSort
* getSort}.
*/
public static final int RESOURCE_VARIABLE = 0x41;
/**
* The sort of type references that target the type of a resource variable in a method. See {@link #getSort
* getSort}.
*/
public static final int RESOURCE_VARIABLE = 0x41;
/**
* The sort of type references that target the type of the exception of a 'catch' clause in a method. See
* {@link #getSort getSort}.
*/
public static final int EXCEPTION_PARAMETER = 0x42;
/**
* The sort of type references that target the type of the exception of a 'catch' clause in a method. See
* {@link #getSort getSort}.
*/
public static final int EXCEPTION_PARAMETER = 0x42;
/**
* The sort of type references that target the type declared in an 'instanceof' instruction. See {@link #getSort
* getSort}.
*/
public static final int INSTANCEOF = 0x43;
/**
* The sort of type references that target the type declared in an 'instanceof' instruction. See {@link #getSort
* getSort}.
*/
public static final int INSTANCEOF = 0x43;
/**
* The sort of type references that target the type of the object created by a 'new' instruction. See
* {@link #getSort getSort}.
*/
public static final int NEW = 0x44;
/**
* The sort of type references that target the type of the object created by a 'new' instruction. See
* {@link #getSort getSort}.
*/
public static final int NEW = 0x44;
/**
* The sort of type references that target the receiver type of a constructor reference. See {@link #getSort
* getSort}.
*/
public static final int CONSTRUCTOR_REFERENCE = 0x45;
/**
* The sort of type references that target the receiver type of a constructor reference. See {@link #getSort
* getSort}.
*/
public static final int CONSTRUCTOR_REFERENCE = 0x45;
/**
* The sort of type references that target the receiver type of a method reference. See {@link #getSort getSort}.
*/
public static final int METHOD_REFERENCE = 0x46;
/**
* The sort of type references that target the receiver type of a method reference. See {@link #getSort getSort}.
*/
public static final int METHOD_REFERENCE = 0x46;
/**
* The sort of type references that target the type declared in an explicit or implicit cast instruction. See
* {@link #getSort getSort}.
*/
public static final int CAST = 0x47;
/**
* The sort of type references that target the type declared in an explicit or implicit cast instruction. See
* {@link #getSort getSort}.
*/
public static final int CAST = 0x47;
/**
* The sort of type references that target a type parameter of a generic constructor in a constructor call. See
* {@link #getSort getSort}.
*/
public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
/**
* The sort of type references that target a type parameter of a generic constructor in a constructor call. See
* {@link #getSort getSort}.
*/
public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
/**
* The sort of type references that target a type parameter of a generic method in a method call. See
* {@link #getSort getSort}.
*/
public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
/**
* The sort of type references that target a type parameter of a generic method in a method call. See
* {@link #getSort getSort}.
*/
public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
/**
* The sort of type references that target a type parameter of a generic constructor in a constructor reference. See
* {@link #getSort getSort}.
*/
public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
/**
* The sort of type references that target a type parameter of a generic constructor in a constructor reference. See
* {@link #getSort getSort}.
*/
public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
/**
* The sort of type references that target a type parameter of a generic method in a method reference. See
* {@link #getSort getSort}.
*/
public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
/**
* The sort of type references that target a type parameter of a generic method in a method reference. See
* {@link #getSort getSort}.
*/
public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
/** The type reference value in Java class file format. */
private int value;
/** The type reference value in Java class file format. */
private int value;
/**
* Creates a new TypeReference.
*
* @param typeRef the int encoded value of the type reference, as received in a visit method related to type
* annotations, like visitTypeAnnotation.
*/
public TypeReference(int typeRef) {
this.value = typeRef;
}
/**
* Creates a new TypeReference.
*
* @param typeRef the int encoded value of the type reference, as received in a visit method related to type
* annotations, like visitTypeAnnotation.
*/
public TypeReference(int typeRef) {
this.value = typeRef;
}
/**
* Returns a type reference of the given sort.
*
* @param sort {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, {@link #METHOD_RECEIVER METHOD_RECEIVER},
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, {@link #INSTANCEOF
* INSTANCEOF}, {@link #NEW NEW}, {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
* {@link #METHOD_REFERENCE METHOD_REFERENCE}.
* @return a type reference of the given sort.
*/
public static TypeReference newTypeReference(int sort) {
return new TypeReference(sort << 24);
}
/**
* Returns a type reference of the given sort.
*
* @param sort {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, {@link #METHOD_RECEIVER METHOD_RECEIVER},
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, {@link #INSTANCEOF
* INSTANCEOF}, {@link #NEW NEW}, {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
* {@link #METHOD_REFERENCE METHOD_REFERENCE}.
* @return a type reference of the given sort.
*/
public static TypeReference newTypeReference(int sort) {
return new TypeReference(sort << 24);
}
/**
* Returns a reference to a type parameter of a generic class or method.
*
* @param sort {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER}.
* @param paramIndex the type parameter index.
* @return a reference to the given generic class or method type parameter.
*/
public static TypeReference newTypeParameterReference(int sort, int paramIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16));
}
/**
* Returns a reference to a type parameter of a generic class or method.
*
* @param sort {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER}.
* @param paramIndex the type parameter index.
* @return a reference to the given generic class or method type parameter.
*/
public static TypeReference newTypeParameterReference(int sort, int paramIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16));
}
/**
* Returns a reference to a type parameter bound of a generic class or method.
*
* @param sort {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER}.
* @param paramIndex the type parameter index.
* @param boundIndex the type bound index within the above type parameters.
* @return a reference to the given generic class or method type parameter bound.
*/
public static TypeReference newTypeParameterBoundReference(int sort, int paramIndex, int boundIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16) | (boundIndex << 8));
}
/**
* Returns a reference to a type parameter bound of a generic class or method.
*
* @param sort {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER}.
* @param paramIndex the type parameter index.
* @param boundIndex the type bound index within the above type parameters.
* @return a reference to the given generic class or method type parameter bound.
*/
public static TypeReference newTypeParameterBoundReference(int sort, int paramIndex, int boundIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16) | (boundIndex << 8));
}
/**
* Returns a reference to the super class or to an interface of the 'implements' clause of a class.
*
* @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to reference the super
* class of the class.
* @return a reference to the given super type of a class.
*/
public static TypeReference newSuperTypeReference(int itfIndex) {
itfIndex &= 0xFFFF;
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
}
/**
* Returns a reference to the super class or to an interface of the 'implements' clause of a class.
*
* @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to reference the super
* class of the class.
* @return a reference to the given super type of a class.
*/
public static TypeReference newSuperTypeReference(int itfIndex) {
itfIndex &= 0xFFFF;
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
}
/**
* Returns a reference to the type of a formal parameter of a method.
*
* @param paramIndex the formal parameter index.
* @return a reference to the type of the given method formal parameter.
*/
public static TypeReference newFormalParameterReference(int paramIndex) {
return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
}
/**
* Returns a reference to the type of a formal parameter of a method.
*
* @param paramIndex the formal parameter index.
* @return a reference to the type of the given method formal parameter.
*/
public static TypeReference newFormalParameterReference(int paramIndex) {
return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
}
/**
* Returns a reference to the type of an exception, in a 'throws' clause of a method.
*
* @param exceptionIndex the index of an exception in a 'throws' clause of a method.
* @return a reference to the type of the given exception.
*/
public static TypeReference newExceptionReference(int exceptionIndex) {
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
}
/**
* Returns a reference to the type of an exception, in a 'throws' clause of a method.
*
* @param exceptionIndex the index of an exception in a 'throws' clause of a method.
* @return a reference to the type of the given exception.
*/
public static TypeReference newExceptionReference(int exceptionIndex) {
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
}
/**
* Returns a reference to the type of the exception declared in a 'catch' clause of a method.
*
* @param tryCatchBlockIndex the index of a try catch block (using the order in which they are visited with
* visitTryCatchBlock).
* @return a reference to the type of the given exception.
*/
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
}
/**
* Returns a reference to the type of the exception declared in a 'catch' clause of a method.
*
* @param tryCatchBlockIndex the index of a try catch block (using the order in which they are visited with
* visitTryCatchBlock).
* @return a reference to the type of the given exception.
*/
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
}
/**
* Returns a reference to the type of a type argument in a constructor or method call or reference.
*
* @param sort {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}.
* @param argIndex the type argument index.
* @return a reference to the type of the given type argument.
*/
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
return new TypeReference((sort << 24) | argIndex);
}
/**
* Returns a reference to the type of a type argument in a constructor or method call or reference.
*
* @param sort {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}.
* @param argIndex the type argument index.
* @return a reference to the type of the given type argument.
*/
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
return new TypeReference((sort << 24) | argIndex);
}
/**
* Returns the sort of this type reference.
*
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
* {@link #CLASS_EXTENDS CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, {@link #FIELD FIELD}, {@link #METHOD_RETURN
* METHOD_RETURN}, {@link #METHOD_RECEIVER METHOD_RECEIVER}, {@link #METHOD_FORMAL_PARAMETER
* METHOD_FORMAL_PARAMETER}, {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}.
*/
public int getSort() {
return value >>> 24;
}
/**
* Returns the sort of this type reference.
*
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
* {@link #CLASS_EXTENDS CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, {@link #FIELD FIELD}, {@link #METHOD_RETURN
* METHOD_RETURN}, {@link #METHOD_RECEIVER METHOD_RECEIVER}, {@link #METHOD_FORMAL_PARAMETER
* METHOD_FORMAL_PARAMETER}, {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}.
*/
public int getSort() {
return value >>> 24;
}
/**
* Returns the index of the type parameter referenced by this type reference. This method must only be used for type
* references whose sort is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
*
* @return a type parameter index.
*/
public int getTypeParameterIndex() {
return (value & 0x00FF0000) >> 16;
}
/**
* Returns the index of the type parameter referenced by this type reference. This method must only be used for type
* references whose sort is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
*
* @return a type parameter index.
*/
public int getTypeParameterIndex() {
return (value & 0x00FF0000) >> 16;
}
/**
* Returns the index of the type parameter bound, within the type parameter {@link #getTypeParameterIndex},
* referenced by this type reference. This method must only be used for type references whose sort is
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or {@link #METHOD_TYPE_PARAMETER_BOUND
* METHOD_TYPE_PARAMETER_BOUND}.
*
* @return a type parameter bound index.
*/
public int getTypeParameterBoundIndex() {
return (value & 0x0000FF00) >> 8;
}
/**
* Returns the index of the type parameter bound, within the type parameter {@link #getTypeParameterIndex},
* referenced by this type reference. This method must only be used for type references whose sort is
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or {@link #METHOD_TYPE_PARAMETER_BOUND
* METHOD_TYPE_PARAMETER_BOUND}.
*
* @return a type parameter bound index.
*/
public int getTypeParameterBoundIndex() {
return (value & 0x0000FF00) >> 8;
}
/**
* Returns the index of the "super type" of a class that is referenced by this type reference. This method must only
* be used for type references whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
*
* @return the index of an interface in the 'implements' clause of a class, or -1 if this type reference references
* the type of the super class.
*/
public int getSuperTypeIndex() {
return (short) ((value & 0x00FFFF00) >> 8);
}
/**
* Returns the index of the "super type" of a class that is referenced by this type reference. This method must only
* be used for type references whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
*
* @return the index of an interface in the 'implements' clause of a class, or -1 if this type reference references
* the type of the super class.
*/
public int getSuperTypeIndex() {
return (short) ((value & 0x00FFFF00) >> 8);
}
/**
* Returns the index of the formal parameter whose type is referenced by this type reference. This method must only
* be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
*
* @return a formal parameter index.
*/
public int getFormalParameterIndex() {
return (value & 0x00FF0000) >> 16;
}
/**
* Returns the index of the formal parameter whose type is referenced by this type reference. This method must only
* be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
*
* @return a formal parameter index.
*/
public int getFormalParameterIndex() {
return (value & 0x00FF0000) >> 16;
}
/**
* Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced by this type
* reference. This method must only be used for type references whose sort is {@link #THROWS THROWS}.
*
* @return the index of an exception in the 'throws' clause of a method.
*/
public int getExceptionIndex() {
return (value & 0x00FFFF00) >> 8;
}
/**
* Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced by this type
* reference. This method must only be used for type references whose sort is {@link #THROWS THROWS}.
*
* @return the index of an exception in the 'throws' clause of a method.
*/
public int getExceptionIndex() {
return (value & 0x00FFFF00) >> 8;
}
/**
* Returns the index of the try catch block (using the order in which they are visited with visitTryCatchBlock),
* whose 'catch' type is referenced by this type reference. This method must only be used for type references whose
* sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
*
* @return the index of an exception in the 'throws' clause of a method.
*/
public int getTryCatchBlockIndex() {
return (value & 0x00FFFF00) >> 8;
}
/**
* Returns the index of the try catch block (using the order in which they are visited with visitTryCatchBlock),
* whose 'catch' type is referenced by this type reference. This method must only be used for type references whose
* sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
*
* @return the index of an exception in the 'throws' clause of a method.
*/
public int getTryCatchBlockIndex() {
return (value & 0x00FFFF00) >> 8;
}
/**
* Returns the index of the type argument referenced by this type reference. This method must only be used for type
* references whose sort is {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
*
* @return a type parameter index.
*/
public int getTypeArgumentIndex() {
return value & 0xFF;
}
/**
* Returns the index of the type argument referenced by this type reference. This method must only be used for type
* references whose sort is {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
*
* @return a type parameter index.
*/
public int getTypeArgumentIndex() {
return value & 0xFF;
}
/**
* Returns the int encoded value of this type reference, suitable for use in visit methods related to type
* annotations, like visitTypeAnnotation.
*
* @return the int encoded value of this type reference.
*/
public int getValue() {
return value;
}
/**
* Returns the int encoded value of this type reference, suitable for use in visit methods related to type
* annotations, like visitTypeAnnotation.
*
* @return the int encoded value of this type reference.
*/
public int getValue() {
return value;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -38,457 +38,457 @@ import org.redkale.util.Utility;
*/
class AppConfig {
/**
* 当前进程的配置文件, 类型String、URI、File、Path <br>
* 一般命名为: application.xml、application.onlyLogProps 若配置文件不是本地文件, 则File、Path类型的值为null
*/
static final String PARAM_APP_CONF_FILE = "APP_CONF_FILE";
/**
* 当前进程的配置文件, 类型String、URI、File、Path <br>
* 一般命名为: application.xml、application.onlyLogProps 若配置文件不是本地文件, 则File、Path类型的值为null
*/
static final String PARAM_APP_CONF_FILE = "APP_CONF_FILE";
// 是否用于main方法运行
final boolean singletonMode;
// 是否用于main方法运行
final boolean singletonMode;
// 是否用于编译模式运行
final boolean compileMode;
// 是否用于编译模式运行
final boolean compileMode;
// application.xml原始配置信息
AnyValue config;
// application.xml原始配置信息
AnyValue config;
// 是否从/META-INF中读取配置
boolean configFromCache;
// 是否从/META-INF中读取配置
boolean configFromCache;
// 本进程节点ID
String nodeid;
// 本进程节点ID
String nodeid;
// 本进程节点ID
String name;
// 本进程节点ID
String name;
// 本地IP地址
InetSocketAddress localAddress;
// 本地IP地址
InetSocketAddress localAddress;
// 进程根目录
File home;
// 进程根目录
File home;
// 配置文件目录
File confFile;
// 配置文件目录
File confFile;
// 配置文件目录
URI confDir;
// 配置文件目录
URI confDir;
// 根ClassLoader
RedkaleClassLoader classLoader;
// 根ClassLoader
RedkaleClassLoader classLoader;
// Server根ClassLoader
RedkaleClassLoader serverClassLoader;
// Server根ClassLoader
RedkaleClassLoader serverClassLoader;
// 本地文件日志配置项
final Properties locaLogProperties = new Properties();
// 本地文件日志配置项
final Properties locaLogProperties = new Properties();
// 本地文件除logging配置之外的所有的配置项, 包含system.property.、mimetype.property.开头的
final Properties localEnvProperties = new Properties();
// 本地文件除logging配置之外的所有的配置项, 包含system.property.、mimetype.property.开头的
final Properties localEnvProperties = new Properties();
public AppConfig(boolean singletonMode, boolean compileMode) {
this.singletonMode = singletonMode;
this.compileMode = compileMode;
}
public AppConfig(boolean singletonMode, boolean compileMode) {
this.singletonMode = singletonMode;
this.compileMode = compileMode;
}
public static AppConfig create(boolean singletonMode, boolean compileMode) throws IOException {
AppConfig rs = new AppConfig(singletonMode, compileMode);
rs.init(loadAppConfig());
return rs;
}
public static AppConfig create(boolean singletonMode, boolean compileMode) throws IOException {
AppConfig rs = new AppConfig(singletonMode, compileMode);
rs.init(loadAppConfig());
return rs;
}
private void init(AnyValue conf) {
this.config = conf;
this.name = checkName(config.getValue("name", ""));
this.nodeid = checkNodeid(config.getValue("nodeid", String.valueOf(Math.abs(System.nanoTime()))));
this.configFromCache = "true".equals(config.getValue("[config-from-cache]"));
// 初始化classLoader、serverClassLoader
this.initClassLoader();
// 初始化home、confDir、localAddress等信息
this.initAppHome();
// 读取本地参数配置
this.initLocalProperties();
// 读取本地日志配置
this.initLogProperties();
// 读取本地数据库配置
this.initSourceProperties();
}
private void init(AnyValue conf) {
this.config = conf;
this.name = checkName(config.getValue("name", ""));
this.nodeid = checkNodeid(config.getValue("nodeid", String.valueOf(Math.abs(System.nanoTime()))));
this.configFromCache = "true".equals(config.getValue("[config-from-cache]"));
// 初始化classLoader、serverClassLoader
this.initClassLoader();
// 初始化home、confDir、localAddress等信息
this.initAppHome();
// 读取本地参数配置
this.initLocalProperties();
// 读取本地日志配置
this.initLogProperties();
// 读取本地数据库配置
this.initSourceProperties();
}
/** 初始化classLoader、serverClassLoader */
private void initClassLoader() {
ClassLoader currClassLoader = Thread.currentThread().getContextClassLoader();
if (currClassLoader instanceof RedkaleClassLoader) {
this.classLoader = (RedkaleClassLoader) currClassLoader;
} else {
Set<String> cacheClasses = null;
if (!singletonMode && !compileMode) {
try {
InputStream in =
Application.class.getResourceAsStream(RedkaleClassLoader.RESOURCE_CACHE_CLASSES_PATH);
if (in != null) {
BufferedReader reader =
new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8), 1024);
List<String> list = new ArrayList<>();
reader.lines().forEach(list::add);
Collections.sort(list);
if (!list.isEmpty()) {
cacheClasses = new LinkedHashSet<>(list);
}
in.close();
}
} catch (Exception e) {
// do nothing
}
}
if (cacheClasses == null) {
this.classLoader = new RedkaleClassLoader(currClassLoader);
} else {
this.classLoader = new RedkaleClassLoader.RedkaleCacheClassLoader(currClassLoader, cacheClasses);
}
Thread.currentThread().setContextClassLoader(this.classLoader);
}
if (compileMode || this.classLoader instanceof RedkaleClassLoader.RedkaleCacheClassLoader) {
this.serverClassLoader = this.classLoader;
} else {
this.serverClassLoader = new RedkaleClassLoader(this.classLoader);
}
}
/** 初始化classLoader、serverClassLoader */
private void initClassLoader() {
ClassLoader currClassLoader = Thread.currentThread().getContextClassLoader();
if (currClassLoader instanceof RedkaleClassLoader) {
this.classLoader = (RedkaleClassLoader) currClassLoader;
} else {
Set<String> cacheClasses = null;
if (!singletonMode && !compileMode) {
try {
InputStream in =
Application.class.getResourceAsStream(RedkaleClassLoader.RESOURCE_CACHE_CLASSES_PATH);
if (in != null) {
BufferedReader reader =
new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8), 1024);
List<String> list = new ArrayList<>();
reader.lines().forEach(list::add);
Collections.sort(list);
if (!list.isEmpty()) {
cacheClasses = new LinkedHashSet<>(list);
}
in.close();
}
} catch (Exception e) {
// do nothing
}
}
if (cacheClasses == null) {
this.classLoader = new RedkaleClassLoader(currClassLoader);
} else {
this.classLoader = new RedkaleClassLoader.RedkaleCacheClassLoader(currClassLoader, cacheClasses);
}
Thread.currentThread().setContextClassLoader(this.classLoader);
}
if (compileMode || this.classLoader instanceof RedkaleClassLoader.RedkaleCacheClassLoader) {
this.serverClassLoader = this.classLoader;
} else {
this.serverClassLoader = new RedkaleClassLoader(this.classLoader);
}
}
/** 初始化home、confDir、localAddress等信息 */
private void initAppHome() {
final File root = new File(System.getProperty(RESNAME_APP_HOME, ""));
final String rootPath = getCanonicalPath(root);
this.home = new File(rootPath);
String confDir = System.getProperty(RESNAME_APP_CONF_DIR, "conf");
if (confDir.contains("://")
|| confDir.startsWith("file:")
|| confDir.startsWith("resource:")
|| confDir.contains("!")) { // graalvm native-image startwith resource:META-INF
this.confDir = URI.create(confDir);
if (confDir.startsWith("file:")) {
this.confFile = getCanonicalFile(new File(this.confDir.getPath()));
}
} else if (confDir.charAt(0) == '/' || confDir.indexOf(':') > -1) {
this.confFile = getCanonicalFile(new File(confDir));
this.confDir = confFile.toURI();
} else {
this.confFile = new File(getCanonicalPath(new File(this.home, confDir)));
this.confDir = confFile.toURI();
}
String localaddr = config.getValue("address", "").trim();
InetAddress addr = localaddr.isEmpty()
? Utility.localInetAddress()
: new InetSocketAddress(localaddr, config.getIntValue("port")).getAddress();
this.localAddress = new InetSocketAddress(addr, config.getIntValue("port"));
}
/** 初始化home、confDir、localAddress等信息 */
private void initAppHome() {
final File root = new File(System.getProperty(RESNAME_APP_HOME, ""));
final String rootPath = getCanonicalPath(root);
this.home = new File(rootPath);
String confDir = System.getProperty(RESNAME_APP_CONF_DIR, "conf");
if (confDir.contains("://")
|| confDir.startsWith("file:")
|| confDir.startsWith("resource:")
|| confDir.contains("!")) { // graalvm native-image startwith resource:META-INF
this.confDir = URI.create(confDir);
if (confDir.startsWith("file:")) {
this.confFile = getCanonicalFile(new File(this.confDir.getPath()));
}
} else if (confDir.charAt(0) == '/' || confDir.indexOf(':') > -1) {
this.confFile = getCanonicalFile(new File(confDir));
this.confDir = confFile.toURI();
} else {
this.confFile = new File(getCanonicalPath(new File(this.home, confDir)));
this.confDir = confFile.toURI();
}
String localaddr = config.getValue("address", "").trim();
InetAddress addr = localaddr.isEmpty()
? Utility.localInetAddress()
: new InetSocketAddress(localaddr, config.getIntValue("port")).getAddress();
this.localAddress = new InetSocketAddress(addr, config.getIntValue("port"));
}
/** 读取本地参数配置 */
private void initLocalProperties() {
// 环境变量的优先级最高
System.getProperties().forEach((k, v) -> {
if (k.toString().startsWith("redkale.")) {
localEnvProperties.put(k, v);
}
});
AnyValue propsConf = this.config.getAnyValue("properties");
if (propsConf == null) {
final AnyValue resources = config.getAnyValue("resources");
if (resources != null) {
System.err.println("<resources> in application config file is deprecated");
propsConf = resources.getAnyValue("properties");
}
}
if (propsConf != null) { // 设置配置文件中的系统变量
for (AnyValue prop : propsConf.getAnyValues("property")) {
String key = prop.getValue("name", "");
String value = prop.getValue("value");
if (value != null) {
localEnvProperties.put(key, value);
}
}
if (propsConf.getValue("load") != null) { // 加载本地配置项文件
for (String dfload :
propsConf.getValue("load").replace(',', ';').split(";")) {
if (dfload.trim().isEmpty()) {
continue;
}
final URI df = RedkaleClassLoader.getConfResourceAsURI(
configFromCache ? null : this.confDir.toString(), dfload.trim());
if (df == null) {
continue;
}
if (!"file".equals(df.getScheme()) || df.toString().contains("!") || new File(df).isFile()) {
Properties props = new Properties();
try {
InputStream in = df.toURL().openStream();
props.load(in);
in.close();
localEnvProperties.putAll(props);
} catch (Exception e) {
throw new RedkaleException(e);
}
}
}
}
}
// 设置Convert默认配置项
if (System.getProperty("redkale.convert.pool.size") == null
&& localEnvProperties.getProperty("system.property.redkale.convert.pool.size") == null) {
localEnvProperties.put("system.property.redkale.convert.pool.size", "128");
}
if (System.getProperty("redkale.convert.writer.buffer.defsize") == null
&& localEnvProperties.getProperty("system.property.redkale.convert.writer.buffer.defsize") == null) {
localEnvProperties.put("system.property.redkale.convert.writer.buffer.defsize", "4096");
}
}
/** 读取本地参数配置 */
private void initLocalProperties() {
// 环境变量的优先级最高
System.getProperties().forEach((k, v) -> {
if (k.toString().startsWith("redkale.")) {
localEnvProperties.put(k, v);
}
});
AnyValue propsConf = this.config.getAnyValue("properties");
if (propsConf == null) {
final AnyValue resources = config.getAnyValue("resources");
if (resources != null) {
System.err.println("<resources> in application config file is deprecated");
propsConf = resources.getAnyValue("properties");
}
}
if (propsConf != null) { // 设置配置文件中的系统变量
for (AnyValue prop : propsConf.getAnyValues("property")) {
String key = prop.getValue("name", "");
String value = prop.getValue("value");
if (value != null) {
localEnvProperties.put(key, value);
}
}
if (propsConf.getValue("load") != null) { // 加载本地配置项文件
for (String dfload :
propsConf.getValue("load").replace(',', ';').split(";")) {
if (dfload.trim().isEmpty()) {
continue;
}
final URI df = RedkaleClassLoader.getConfResourceAsURI(
configFromCache ? null : this.confDir.toString(), dfload.trim());
if (df == null) {
continue;
}
if (!"file".equals(df.getScheme()) || df.toString().contains("!") || new File(df).isFile()) {
Properties props = new Properties();
try {
InputStream in = df.toURL().openStream();
props.load(in);
in.close();
localEnvProperties.putAll(props);
} catch (Exception e) {
throw new RedkaleException(e);
}
}
}
}
}
// 设置Convert默认配置项
if (System.getProperty("redkale.convert.pool.size") == null
&& localEnvProperties.getProperty("system.property.redkale.convert.pool.size") == null) {
localEnvProperties.put("system.property.redkale.convert.pool.size", "128");
}
if (System.getProperty("redkale.convert.writer.buffer.defsize") == null
&& localEnvProperties.getProperty("system.property.redkale.convert.writer.buffer.defsize") == null) {
localEnvProperties.put("system.property.redkale.convert.writer.buffer.defsize", "4096");
}
}
/** 读取本地DataSource、CacheSource配置 */
private void initSourceProperties() {
if ("file".equals(this.confDir.getScheme())) {
File sourceFile = new File(new File(confDir), "source.properties");
if (sourceFile.isFile() && sourceFile.canRead()) {
Properties props = new Properties();
try {
InputStream in = new FileInputStream(sourceFile);
props.load(in);
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
this.localEnvProperties.putAll(props);
} else {
// 兼容 persistence.xml 【已废弃】
File persist = new File(new File(confDir), "persistence.xml");
if (persist.isFile() && persist.canRead()) {
System.err.println("persistence.xml is deprecated, replaced by source.properties");
try {
InputStream in = new FileInputStream(persist);
this.localEnvProperties.putAll(DataSources.loadSourceProperties(in));
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
}
}
} else { // 从url或jar文件中resources读取
try {
final URI sourceURI = RedkaleClassLoader.getConfResourceAsURI(
configFromCache ? null : this.confDir.toString(), "source.properties");
InputStream in = sourceURI.toURL().openStream();
Properties props = new Properties();
props.load(in);
in.close();
this.localEnvProperties.putAll(props);
} catch (Exception e) {
// 没有文件 跳过
}
}
}
/** 读取本地DataSource、CacheSource配置 */
private void initSourceProperties() {
if ("file".equals(this.confDir.getScheme())) {
File sourceFile = new File(new File(confDir), "source.properties");
if (sourceFile.isFile() && sourceFile.canRead()) {
Properties props = new Properties();
try {
InputStream in = new FileInputStream(sourceFile);
props.load(in);
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
this.localEnvProperties.putAll(props);
} else {
// 兼容 persistence.xml 【已废弃】
File persist = new File(new File(confDir), "persistence.xml");
if (persist.isFile() && persist.canRead()) {
System.err.println("persistence.xml is deprecated, replaced by source.properties");
try {
InputStream in = new FileInputStream(persist);
this.localEnvProperties.putAll(DataSources.loadSourceProperties(in));
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
}
}
} else { // 从url或jar文件中resources读取
try {
final URI sourceURI = RedkaleClassLoader.getConfResourceAsURI(
configFromCache ? null : this.confDir.toString(), "source.properties");
InputStream in = sourceURI.toURL().openStream();
Properties props = new Properties();
props.load(in);
in.close();
this.localEnvProperties.putAll(props);
} catch (Exception e) {
// 没有文件 跳过
}
}
}
/** 读取本地日志配置 */
private void initLogProperties() {
URI logConfURI;
File logConfFile = null;
if (configFromCache) {
logConfURI = RedkaleClassLoader.getConfResourceAsURI(null, "logging.properties");
} else if ("file".equals(confDir.getScheme())) {
logConfFile = new File(confDir.getPath(), "logging.properties");
logConfURI = logConfFile.toURI();
if (!logConfFile.isFile() || !logConfFile.canRead()) {
logConfFile = null;
}
} else {
logConfURI = URI.create(confDir + (confDir.toString().endsWith("/") ? "" : "/") + "logging.properties");
}
if (!"file".equals(confDir.getScheme()) || logConfFile != null) {
try {
InputStream fin = logConfURI.toURL().openStream();
Properties properties0 = new Properties();
properties0.load(fin);
fin.close();
properties0.forEach(locaLogProperties::put);
} catch (IOException e) {
throw new RedkaleException("read logging.properties error", e);
}
}
if (compileMode) {
putReflectionClass(java.lang.Class.class.getName());
putReflectionPublicConstructors(SimpleFormatter.class, SimpleFormatter.class.getName());
putReflectionPublicConstructors(LoggingSearchHandler.class, LoggingSearchHandler.class.getName());
putReflectionPublicConstructors(LoggingFileHandler.class, LoggingFileHandler.class.getName());
putReflectionPublicConstructors(
LoggingFileHandler.LoggingFormater.class, LoggingFileHandler.LoggingFormater.class.getName());
putReflectionPublicConstructors(
LoggingFileHandler.LoggingConsoleHandler.class,
LoggingFileHandler.LoggingConsoleHandler.class.getName());
putReflectionPublicConstructors(
LoggingFileHandler.LoggingSncpFileHandler.class,
LoggingFileHandler.LoggingSncpFileHandler.class.getName());
}
}
/** 读取本地日志配置 */
private void initLogProperties() {
URI logConfURI;
File logConfFile = null;
if (configFromCache) {
logConfURI = RedkaleClassLoader.getConfResourceAsURI(null, "logging.properties");
} else if ("file".equals(confDir.getScheme())) {
logConfFile = new File(confDir.getPath(), "logging.properties");
logConfURI = logConfFile.toURI();
if (!logConfFile.isFile() || !logConfFile.canRead()) {
logConfFile = null;
}
} else {
logConfURI = URI.create(confDir + (confDir.toString().endsWith("/") ? "" : "/") + "logging.properties");
}
if (!"file".equals(confDir.getScheme()) || logConfFile != null) {
try {
InputStream fin = logConfURI.toURL().openStream();
Properties properties0 = new Properties();
properties0.load(fin);
fin.close();
properties0.forEach(locaLogProperties::put);
} catch (IOException e) {
throw new RedkaleException("read logging.properties error", e);
}
}
if (compileMode) {
putReflectionClass(java.lang.Class.class.getName());
putReflectionPublicConstructors(SimpleFormatter.class, SimpleFormatter.class.getName());
putReflectionPublicConstructors(LoggingSearchHandler.class, LoggingSearchHandler.class.getName());
putReflectionPublicConstructors(LoggingFileHandler.class, LoggingFileHandler.class.getName());
putReflectionPublicConstructors(
LoggingFileHandler.LoggingFormater.class, LoggingFileHandler.LoggingFormater.class.getName());
putReflectionPublicConstructors(
LoggingFileHandler.LoggingConsoleHandler.class,
LoggingFileHandler.LoggingConsoleHandler.class.getName());
putReflectionPublicConstructors(
LoggingFileHandler.LoggingSncpFileHandler.class,
LoggingFileHandler.LoggingSncpFileHandler.class.getName());
}
}
/**
* 从本地application.xml或application.properties文件加载配置信息
*
* @return 配置信息
* @throws IOException
*/
static AnyValue loadAppConfig() throws IOException {
final String home = new File(System.getProperty(RESNAME_APP_HOME, ""))
.getCanonicalPath()
.replace('\\', '/');
String sysConfFile = System.getProperty(PARAM_APP_CONF_FILE);
if (sysConfFile != null) {
String text;
if (sysConfFile.contains("://")) {
text = Utility.readThenClose(URI.create(sysConfFile).toURL().openStream());
} else {
File f = new File(sysConfFile);
if (f.isFile() && f.canRead()) {
text = Utility.readThenClose(new FileInputStream(f));
} else {
throw new IOException("Read application conf file (" + sysConfFile + ") error ");
}
}
return text.trim().startsWith("<")
? AnyValue.loadFromXml(text, (k, v) -> v.replace("${" + RESNAME_APP_HOME + "}", home))
.getAnyValue("application")
: AnyValue.loadFromProperties(text).getAnyValue("redkale");
}
String confDir = System.getProperty(RESNAME_APP_CONF_DIR, "conf");
URI appConfFile;
boolean fromCache = false;
if (confDir.contains("://")) { // jar内部资源
appConfFile = URI.create(confDir + (confDir.endsWith("/") ? "" : "/") + "application.xml");
try {
appConfFile.toURL().openStream().close();
} catch (IOException e) { // 没有application.xml就尝试读application.properties
appConfFile = URI.create(confDir + (confDir.endsWith("/") ? "" : "/") + "application.properties");
}
} else if (confDir.charAt(0) == '/' || confDir.indexOf(':') > 0) { // 绝对路径
File f = new File(confDir, "application.xml");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
f = new File(confDir, "application.properties");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.xml"); // 不能传confDir
try {
appConfFile.toURL().openStream().close();
} catch (IOException e) { // 没有application.xml就尝试读application.properties
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.properties");
}
confDir = appConfFile
.toString()
.replace("/application.xml", "")
.replace("/application.properties", "");
fromCache = true;
}
}
} else { // 相对路径
File f = new File(new File(home, confDir), "application.xml");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
f = new File(new File(home, confDir), "application.properties");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.xml"); // 不能传confDir
try {
appConfFile.toURL().openStream().close();
} catch (IOException e) { // 没有application.xml就尝试读application.properties
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.properties");
}
confDir = appConfFile
.toString()
.replace("/application.xml", "")
.replace("/application.properties", "");
fromCache = true;
}
}
}
System.setProperty(RESNAME_APP_CONF_DIR, confDir);
String text = Utility.readThenClose(appConfFile.toURL().openStream());
AnyValue conf;
if (text.trim().startsWith("<")) {
conf = AnyValue.loadFromXml(text, (k, v) -> v.replace("${APP_HOME}", home))
.getAnyValue("application");
} else {
conf = AnyValue.loadFromProperties(text).getAnyValue("redkale");
}
if (fromCache) {
((AnyValueWriter) conf).addValue("[config-from-cache]", "true");
}
/**
* 从本地application.xml或application.properties文件加载配置信息
*
* @return 配置信息
* @throws IOException
*/
static AnyValue loadAppConfig() throws IOException {
final String home = new File(System.getProperty(RESNAME_APP_HOME, ""))
.getCanonicalPath()
.replace('\\', '/');
String sysConfFile = System.getProperty(PARAM_APP_CONF_FILE);
if (sysConfFile != null) {
String text;
if (sysConfFile.contains("://")) {
text = Utility.readThenClose(URI.create(sysConfFile).toURL().openStream());
} else {
File f = new File(sysConfFile);
if (f.isFile() && f.canRead()) {
text = Utility.readThenClose(new FileInputStream(f));
} else {
throw new IOException("Read application conf file (" + sysConfFile + ") error ");
}
}
return text.trim().startsWith("<")
? AnyValue.loadFromXml(text, (k, v) -> v.replace("${" + RESNAME_APP_HOME + "}", home))
.getAnyValue("application")
: AnyValue.loadFromProperties(text).getAnyValue("redkale");
}
String confDir = System.getProperty(RESNAME_APP_CONF_DIR, "conf");
URI appConfFile;
boolean fromCache = false;
if (confDir.contains("://")) { // jar内部资源
appConfFile = URI.create(confDir + (confDir.endsWith("/") ? "" : "/") + "application.xml");
try {
appConfFile.toURL().openStream().close();
} catch (IOException e) { // 没有application.xml就尝试读application.properties
appConfFile = URI.create(confDir + (confDir.endsWith("/") ? "" : "/") + "application.properties");
}
} else if (confDir.charAt(0) == '/' || confDir.indexOf(':') > 0) { // 绝对路径
File f = new File(confDir, "application.xml");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
f = new File(confDir, "application.properties");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.xml"); // 不能传confDir
try {
appConfFile.toURL().openStream().close();
} catch (IOException e) { // 没有application.xml就尝试读application.properties
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.properties");
}
confDir = appConfFile
.toString()
.replace("/application.xml", "")
.replace("/application.properties", "");
fromCache = true;
}
}
} else { // 相对路径
File f = new File(new File(home, confDir), "application.xml");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
f = new File(new File(home, confDir), "application.properties");
if (f.isFile() && f.canRead()) {
appConfFile = f.toURI();
confDir = f.getParentFile().getCanonicalPath();
} else {
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.xml"); // 不能传confDir
try {
appConfFile.toURL().openStream().close();
} catch (IOException e) { // 没有application.xml就尝试读application.properties
appConfFile = RedkaleClassLoader.getConfResourceAsURI(null, "application.properties");
}
confDir = appConfFile
.toString()
.replace("/application.xml", "")
.replace("/application.properties", "");
fromCache = true;
}
}
}
System.setProperty(RESNAME_APP_CONF_DIR, confDir);
String text = Utility.readThenClose(appConfFile.toURL().openStream());
AnyValue conf;
if (text.trim().startsWith("<")) {
conf = AnyValue.loadFromXml(text, (k, v) -> v.replace("${APP_HOME}", home))
.getAnyValue("application");
} else {
conf = AnyValue.loadFromProperties(text).getAnyValue("redkale");
}
if (fromCache) {
((AnyValueWriter) conf).addValue("[config-from-cache]", "true");
}
return conf;
}
return conf;
}
/**
* 检查name是否含特殊字符
*
* @param name
* @return
*/
private static String checkName(String name) {
if (name == null || name.isEmpty()) {
return name;
}
for (char ch : name.toCharArray()) {
if (!((ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| ch == '_'
|| ch == '.'
|| ch == '-')) { // 不能含特殊字符
throw new RedkaleException("name only 0-9 a-z A-Z _ - .");
}
}
return name;
}
/**
* 检查name是否含特殊字符
*
* @param name
* @return
*/
private static String checkName(String name) {
if (name == null || name.isEmpty()) {
return name;
}
for (char ch : name.toCharArray()) {
if (!((ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| ch == '_'
|| ch == '.'
|| ch == '-')) { // 不能含特殊字符
throw new RedkaleException("name only 0-9 a-z A-Z _ - .");
}
}
return name;
}
/**
* 检查node是否含特殊字符
*
* @param name
* @return
*/
private static String checkNodeid(String nodeid) {
if (nodeid == null || nodeid.isEmpty()) {
return nodeid;
}
for (char ch : nodeid.toCharArray()) {
if (!((ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| ch == '_'
|| ch == '.'
|| ch == '-')) { // 不能含特殊字符
throw new RedkaleException("nodeid only 0-9 a-z A-Z _ - .");
}
}
return nodeid;
}
/**
* 检查node是否含特殊字符
*
* @param name
* @return
*/
private static String checkNodeid(String nodeid) {
if (nodeid == null || nodeid.isEmpty()) {
return nodeid;
}
for (char ch : nodeid.toCharArray()) {
if (!((ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| ch == '_'
|| ch == '.'
|| ch == '-')) { // 不能含特殊字符
throw new RedkaleException("nodeid only 0-9 a-z A-Z _ - .");
}
}
return nodeid;
}
private String getCanonicalPath(File file) {
try {
return file.getCanonicalPath();
} catch (IOException e) {
return file.getAbsolutePath();
}
}
private String getCanonicalPath(File file) {
try {
return file.getCanonicalPath();
} catch (IOException e) {
return file.getAbsolutePath();
}
}
private File getCanonicalFile(File file) {
try {
return file.getCanonicalFile();
} catch (IOException e) {
return file;
}
}
private File getCanonicalFile(File file) {
try {
return file.getCanonicalFile();
} catch (IOException e) {
return file;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -17,59 +17,59 @@ import org.redkale.util.AnyValue;
*/
public interface ApplicationListener {
/**
* 初始化方法
*
* @param config 配置参数
*/
default void init(AnyValue config) {}
/**
* 初始化方法
*
* @param config 配置参数
*/
default void init(AnyValue config) {}
/**
* Application在运行start前调用
*
* @param application Application
*/
default void onPreStart(Application application) {}
/**
* Application在运行start前调用
*
* @param application Application
*/
default void onPreStart(Application application) {}
/**
* 服务全部停掉前被调用
*
* @param application Application
*/
default void onServersPreStop(Application application) {}
/**
* 服务全部停掉前被调用
*
* @param application Application
*/
default void onServersPreStop(Application application) {}
/**
* 服务全部停掉后被调用
*
* @param application Application
*/
default void onServersPostStop(Application application) {}
/**
* 服务全部停掉后被调用
*
* @param application Application
*/
default void onServersPostStop(Application application) {}
/**
* Application在运行start后调用
*
* @param application Application
*/
default void onPostStart(Application application) {}
/**
* Application在运行start后调用
*
* @param application Application
*/
default void onPostStart(Application application) {}
/**
* Application在运行Compile前调用
*
* @param application Application
*/
default void onPreCompile(Application application) {}
/**
* Application在运行Compile前调用
*
* @param application Application
*/
default void onPreCompile(Application application) {}
/**
* Application在运行Compile后调用
*
* @param application Application
*/
default void onPostCompile(Application application) {}
/**
* Application在运行Compile后调用
*
* @param application Application
*/
default void onPostCompile(Application application) {}
/**
* Application在运行shutdown前调用
*
* @param application Application
*/
default void onPreShutdown(Application application) {}
/**
* Application在运行shutdown前调用
*
* @param application Application
*/
default void onPreShutdown(Application application) {}
}

View File

@@ -13,40 +13,40 @@ import org.redkale.util.Environment;
/** @author zhangjx */
public abstract class BootModule {
protected final Application application;
protected final Application application;
protected final ResourceFactory resourceFactory;
protected final ResourceFactory resourceFactory;
protected final Environment environment;
protected final Environment environment;
protected BootModule(Application application) {
this.application = application;
this.resourceFactory = Objects.requireNonNull(application.resourceFactory);
this.environment = Objects.requireNonNull(application.getEnvironment());
}
protected BootModule(Application application) {
this.application = application;
this.resourceFactory = Objects.requireNonNull(application.resourceFactory);
this.environment = Objects.requireNonNull(application.getEnvironment());
}
protected void removeEnvValue(String name) {
application.envProperties.remove(name);
}
protected void removeEnvValue(String name) {
application.envProperties.remove(name);
}
protected void putEnvValue(Object name, Object value) {
application.envProperties.put(name, value);
}
protected void putEnvValue(Object name, Object value) {
application.envProperties.put(name, value);
}
protected List<ModuleEngine> getModuleEngines() {
return application.getModuleEngines();
}
protected List<ModuleEngine> getModuleEngines() {
return application.getModuleEngines();
}
protected void reconfigLogging(boolean first, Properties allProps) {
application.loggingModule.reconfigLogging(first, allProps);
}
protected void reconfigLogging(boolean first, Properties allProps) {
application.loggingModule.reconfigLogging(first, allProps);
}
protected void onEnvironmentChanged(String namespace, List<ResourceEvent> events) {
if (namespace != null && namespace.contains("logging")) {
// 日志配置单独处理
application.loggingModule.onEnvironmentUpdated(events);
} else {
application.onEnvironmentChanged(namespace, events);
}
}
protected void onEnvironmentChanged(String namespace, List<ResourceEvent> events) {
if (namespace != null && namespace.contains("logging")) {
// 日志配置单独处理
application.loggingModule.onEnvironmentUpdated(events);
} else {
application.onEnvironmentChanged(namespace, events);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,126 +16,126 @@ import org.redkale.util.Traces;
*/
public abstract class LoggingBaseHandler 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";
// 无threadName、TID
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";
// 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";
// 无threadName、TID
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";
// 有threadName
public static final String FORMATTER_FORMAT2 =
"[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL] [%7$s] %4$s %2$s\r\n%5$s%6$s\r\n";
// 有threadName
public static final String FORMATTER_FORMAT2 =
"[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL] [%7$s] %4$s %2$s\r\n%5$s%6$s\r\n";
// 有threadName、TID
public static final String FORMATTER_FORMAT3 =
"[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL] [%7$s] %8$s %4$s %2$s\r\n%5$s%6$s\r\n";
// 有threadName、TID
public static final String FORMATTER_FORMAT3 =
"[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL] [%7$s] %8$s %4$s %2$s\r\n%5$s%6$s\r\n";
static boolean traceEnable = false; // 防止设置system.property前调用Traces类导致enable提前初始化
static boolean traceEnable = false; // 防止设置system.property前调用Traces类导致enable提前初始化
/** 默认的日志时间格式化类 与SimpleFormatter的区别在于level不使用本地化 */
public static class LoggingFormater extends Formatter {
/** 默认的日志时间格式化类 与SimpleFormatter的区别在于level不使用本地化 */
public static class LoggingFormater extends Formatter {
@Override
public String format(LogRecord log) {
if (log.getThrown() == null
&& log.getMessage() != null
&& log.getMessage().startsWith("------")) {
return formatMessage(log) + "\r\n";
}
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();
}
Object[] params = log.getParameters();
if (params != null) {
if (params.length == 1) {
return String.format(
FORMATTER_FORMAT2,
log.getInstant().toEpochMilli(),
source,
log.getLoggerName(),
log.getLevel().getName(),
message,
throwable,
params[0]);
} else if (params.length == 2) {
return String.format(
FORMATTER_FORMAT3,
log.getInstant().toEpochMilli(),
source,
log.getLoggerName(),
log.getLevel().getName(),
message,
throwable,
params[0],
params[1]);
}
}
return String.format(
FORMATTER_FORMAT,
log.getInstant().toEpochMilli(),
source,
log.getLoggerName(),
log.getLevel().getName(),
message,
throwable);
}
}
@Override
public String format(LogRecord log) {
if (log.getThrown() == null
&& log.getMessage() != null
&& log.getMessage().startsWith("------")) {
return formatMessage(log) + "\r\n";
}
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();
}
Object[] params = log.getParameters();
if (params != null) {
if (params.length == 1) {
return String.format(
FORMATTER_FORMAT2,
log.getInstant().toEpochMilli(),
source,
log.getLoggerName(),
log.getLevel().getName(),
message,
throwable,
params[0]);
} else if (params.length == 2) {
return String.format(
FORMATTER_FORMAT3,
log.getInstant().toEpochMilli(),
source,
log.getLoggerName(),
log.getLevel().getName(),
message,
throwable,
params[0],
params[1]);
}
}
return String.format(
FORMATTER_FORMAT,
log.getInstant().toEpochMilli(),
source,
log.getLoggerName(),
log.getLevel().getName(),
message,
throwable);
}
}
protected static void fillLogRecord(LogRecord log) {
String traceid = null;
if (traceEnable && Traces.enable()) {
traceid = Traces.currentTraceid();
if (traceid == null || traceid.isEmpty()) {
traceid = "[TID:N/A] ";
} else {
traceid = "[TID:" + traceid + "] ";
}
}
if (traceid == null) {
log.setParameters(new String[] {Thread.currentThread().getName()});
} else {
log.setParameters(new String[] {Thread.currentThread().getName(), traceid});
}
}
protected static void fillLogRecord(LogRecord log) {
String traceid = null;
if (traceEnable && Traces.enable()) {
traceid = Traces.currentTraceid();
if (traceid == null || traceid.isEmpty()) {
traceid = "[TID:N/A] ";
} else {
traceid = "[TID:" + traceid + "] ";
}
}
if (traceid == null) {
log.setParameters(new String[] {Thread.currentThread().getName()});
} else {
log.setParameters(new String[] {Thread.currentThread().getName(), traceid});
}
}
public static void initDebugLogConfig() {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(out);
final String handlerName =
LoggingFileHandler.LoggingConsoleHandler.class.getName(); // java.util.logging.ConsoleHandler
ps.println("handlers = " + handlerName);
ps.println(".level = FINEST");
ps.println("jdk.level = INFO");
ps.println("sun.level = INFO");
ps.println("javax.level = INFO");
ps.println("com.sun.level = INFO");
ps.println("io.level = INFO");
ps.println("org.junit.level = INFO");
ps.println(handlerName + ".level = FINEST");
ps.println(handlerName + ".formatter = " + LoggingFormater.class.getName());
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
} catch (Exception e) {
// do nothing
}
}
public static void initDebugLogConfig() {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(out);
final String handlerName =
LoggingFileHandler.LoggingConsoleHandler.class.getName(); // java.util.logging.ConsoleHandler
ps.println("handlers = " + handlerName);
ps.println(".level = FINEST");
ps.println("jdk.level = INFO");
ps.println("sun.level = INFO");
ps.println("javax.level = INFO");
ps.println("com.sun.level = INFO");
ps.println("io.level = INFO");
ps.println("org.junit.level = INFO");
ps.println(handlerName + ".level = FINEST");
ps.println(handlerName + ".formatter = " + LoggingFormater.class.getName());
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
} catch (Exception e) {
// do nothing
}
}
}

View File

@@ -26,378 +26,378 @@ import org.redkale.util.*;
@SuppressWarnings("unchecked")
public class LoggingFileHandler extends LoggingBaseHandler {
/** SNCP的日志输出Handler */
public static class LoggingSncpFileHandler extends LoggingFileHandler {
/** SNCP的日志输出Handler */
public static class LoggingSncpFileHandler extends LoggingFileHandler {
@Override
public String getPrefix() {
return "sncp-";
}
}
@Override
public String getPrefix() {
return "sncp-";
}
}
public static class LoggingConsoleHandler extends ConsoleHandler {
public static class LoggingConsoleHandler extends ConsoleHandler {
private Pattern denyRegx;
private Pattern denyRegx;
public LoggingConsoleHandler() {
super();
setFormatter(new LoggingFormater());
configure();
}
public LoggingConsoleHandler() {
super();
setFormatter(new LoggingFormater());
configure();
}
private void configure() {
LogManager manager = LogManager.getLogManager();
String denyregxstr = manager.getProperty(LoggingConsoleHandler.class.getName() + ".denyregx");
if (denyregxstr == null) {
denyregxstr = manager.getProperty("java.util.logging.ConsoleHandler.denyregx");
}
try {
if (denyregxstr != null && !denyregxstr.trim().isEmpty()) {
this.denyRegx = Pattern.compile(denyregxstr);
}
} catch (Exception e) {
// do nothing
}
}
private void configure() {
LogManager manager = LogManager.getLogManager();
String denyregxstr = manager.getProperty(LoggingConsoleHandler.class.getName() + ".denyregx");
if (denyregxstr == null) {
denyregxstr = manager.getProperty("java.util.logging.ConsoleHandler.denyregx");
}
try {
if (denyregxstr != null && !denyregxstr.trim().isEmpty()) {
this.denyRegx = Pattern.compile(denyregxstr);
}
} catch (Exception e) {
// do nothing
}
}
@Override
public void publish(LogRecord log) {
if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return;
}
fillLogRecord(log);
super.publish(log);
}
}
@Override
public void publish(LogRecord log) {
if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return;
}
fillLogRecord(log);
super.publish(log);
}
}
protected final LinkedBlockingQueue<LogRecord> logQueue = new LinkedBlockingQueue();
protected final LinkedBlockingQueue<LogRecord> logQueue = new LinkedBlockingQueue();
protected String pattern;
protected String pattern;
protected String patternDateFormat; // 需要时间格式化
protected String patternDateFormat; // 需要时间格式化
protected String unusual; // 不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
protected String unusual; // 不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
protected String unusualDateFormat; // 需要时间格式化
protected String unusualDateFormat; // 需要时间格式化
private int limit; // 文件大小限制
private int limit; // 文件大小限制
private final AtomicInteger logIndex = new AtomicInteger();
private final AtomicInteger logIndex = new AtomicInteger();
private final AtomicInteger logUnusualIndex = new AtomicInteger();
private final AtomicInteger logUnusualIndex = new AtomicInteger();
private int count = 1; // 文件限制
private int count = 1; // 文件限制
private long tomorrow;
private long tomorrow;
protected boolean append;
protected boolean append;
protected Pattern denyRegx;
protected Pattern denyRegx;
private final AtomicLong logLength = new AtomicLong();
private final AtomicLong logLength = new AtomicLong();
private final AtomicLong logUnusualLength = new AtomicLong();
private final AtomicLong logUnusualLength = new AtomicLong();
private File logFile;
private File logFile;
private File logUnusualFile;
private File logUnusualFile;
private OutputStream logStream;
private OutputStream logStream;
private OutputStream logUnusualStream;
private OutputStream logUnusualStream;
public LoggingFileHandler() {
updateTomorrow();
configure();
open();
}
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 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().replace("Logging", "") + "-Thread";
new Thread() {
{
setName(name);
setDaemon(true);
}
private void open() {
final String name = "Redkale-Logging-" + getClass().getSimpleName().replace("Logging", "") + "-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) {
Files.delete(logFile.toPath());
}
}
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) {
Files.delete(logUnusualFile.toPath());
}
}
logUnusualStream = null;
}
if (logStream == null) {
logIndex.incrementAndGet();
logFile = new File(
patternDateFormat == null
? pattern
: Times.formatTime(patternDateFormat, -1, System.currentTimeMillis()));
logFile.getParentFile().mkdirs();
logLength.set(logFile.length());
logStream = new FileOutputStream(logFile, append);
}
if (unusual != null && logUnusualStream == null) {
logUnusualIndex.incrementAndGet();
logUnusualFile = new File(
unusualDateFormat == null
? unusual
: Times.formatTime(unusualDateFormat, -1, System.currentTimeMillis()));
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();
}
@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) {
Files.delete(logFile.toPath());
}
}
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) {
Files.delete(logUnusualFile.toPath());
}
}
logUnusualStream = null;
}
if (logStream == null) {
logIndex.incrementAndGet();
logFile = new File(
patternDateFormat == null
? pattern
: Times.formatTime(patternDateFormat, -1, System.currentTimeMillis()));
logFile.getParentFile().mkdirs();
logLength.set(logFile.length());
logStream = new FileOutputStream(logFile, append);
}
if (unusual != null && logUnusualStream == null) {
logUnusualIndex.incrementAndGet();
logUnusualFile = new File(
unusualDateFormat == null
? unusual
: Times.formatTime(unusualDateFormat, -1, System.currentTimeMillis()));
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 "";
}
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-%tm/" + getPrefix() + "log-%td.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;
}
}
if (this.pattern != null && this.pattern.contains("%")) { // 需要时间格式化
this.patternDateFormat = this.pattern;
Times.formatTime(this.patternDateFormat, -1, System.currentTimeMillis()); // 测试时间格式是否正确
}
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;
}
}
if (this.unusual != null && this.unusual.contains("%")) { // 需要时间格式化
this.unusualDateFormat = this.unusual;
Times.formatTime(this.unusualDateFormat, -1, System.currentTimeMillis()); // 测试时间格式是否正确
}
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) {
// do nothing
}
String countstr = manager.getProperty(cname + ".count");
try {
if (countstr != null) {
this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
}
} catch (Exception e) {
// do nothing
}
String appendstr = manager.getProperty(cname + ".append");
try {
if (appendstr != null) {
this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
}
} catch (Exception e) {
// do nothing
}
String levelstr = manager.getProperty(cname + ".level");
try {
if (levelstr != null) {
Level l = Level.parse(levelstr);
setLevel(l != null ? l : Level.ALL);
}
} catch (Exception e) {
// do nothing
}
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) {
// do nothing
}
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) {
// do nothing
}
if (getFormatter() == null) {
setFormatter(new SimpleFormatter());
}
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-%tm/" + getPrefix() + "log-%td.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;
}
}
if (this.pattern != null && this.pattern.contains("%")) { // 需要时间格式化
this.patternDateFormat = this.pattern;
Times.formatTime(this.patternDateFormat, -1, System.currentTimeMillis()); // 测试时间格式是否正确
}
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;
}
}
if (this.unusual != null && this.unusual.contains("%")) { // 需要时间格式化
this.unusualDateFormat = this.unusual;
Times.formatTime(this.unusualDateFormat, -1, System.currentTimeMillis()); // 测试时间格式是否正确
}
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) {
// do nothing
}
String countstr = manager.getProperty(cname + ".count");
try {
if (countstr != null) {
this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
}
} catch (Exception e) {
// do nothing
}
String appendstr = manager.getProperty(cname + ".append");
try {
if (appendstr != null) {
this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
}
} catch (Exception e) {
// do nothing
}
String levelstr = manager.getProperty(cname + ".level");
try {
if (levelstr != null) {
Level l = Level.parse(levelstr);
setLevel(l != null ? l : Level.ALL);
}
} catch (Exception e) {
// do nothing
}
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) {
// do nothing
}
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) {
// do nothing
}
if (getFormatter() == null) {
setFormatter(new SimpleFormatter());
}
String encodingstr = manager.getProperty(cname + ".encoding");
try {
if (encodingstr != null) {
setEncoding(encodingstr);
}
} catch (Exception e) {
// do nothing
}
String encodingstr = manager.getProperty(cname + ".encoding");
try {
if (encodingstr != null) {
setEncoding(encodingstr);
}
} catch (Exception e) {
// do nothing
}
String denyregxstr = manager.getProperty(cname + ".denyregx");
try {
if (denyregxstr != null && !denyregxstr.trim().isEmpty()) {
denyRegx = Pattern.compile(denyregxstr);
}
} catch (Exception e) {
// do nothing
}
}
String denyregxstr = manager.getProperty(cname + ".denyregx");
try {
if (denyregxstr != null && !denyregxstr.trim().isEmpty()) {
denyRegx = Pattern.compile(denyregxstr);
}
} catch (Exception e) {
// do nothing
}
}
@Override
public void publish(LogRecord log) {
if (!isLoggable(log)) {
return;
}
if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return;
}
fillLogRecord(log);
logQueue.offer(log);
}
@Override
public void publish(LogRecord log) {
if (!isLoggable(log)) {
return;
}
if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return;
}
fillLogRecord(log);
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 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);
}
}
}
@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);
}
}
}
}

View File

@@ -31,162 +31,162 @@ import org.redkale.util.Environment;
*/
class LoggingModule extends BootModule {
// 日志配置资源
private final Properties loggingProperties = new Properties();
// 日志配置资源
private final Properties loggingProperties = new Properties();
LoggingModule(Application application) {
super(application);
}
LoggingModule(Application application) {
super(application);
}
/**
* 配置变更
*
* @param events 变更项
*/
public void onEnvironmentUpdated(List<ResourceEvent> events) {
Set<String> loggingRemovedKeys = new HashSet<>();
Properties loggingChangedProps = new Properties();
for (ResourceEvent event : events) {
if (event.newValue() == null) {
if (loggingProperties.containsKey(event.name())) {
loggingRemovedKeys.add(event.name());
}
} else {
loggingChangedProps.put(event.name(), event.newValue());
}
}
if (!loggingRemovedKeys.isEmpty() || !loggingChangedProps.isEmpty()) {
Properties newProps = new Properties(this.loggingProperties);
loggingRemovedKeys.forEach(newProps::remove);
newProps.putAll(loggingChangedProps);
reconfigLogging(false, newProps);
}
}
/**
* 配置变更
*
* @param events 变更项
*/
public void onEnvironmentUpdated(List<ResourceEvent> events) {
Set<String> loggingRemovedKeys = new HashSet<>();
Properties loggingChangedProps = new Properties();
for (ResourceEvent event : events) {
if (event.newValue() == null) {
if (loggingProperties.containsKey(event.name())) {
loggingRemovedKeys.add(event.name());
}
} else {
loggingChangedProps.put(event.name(), event.newValue());
}
}
if (!loggingRemovedKeys.isEmpty() || !loggingChangedProps.isEmpty()) {
Properties newProps = new Properties(this.loggingProperties);
loggingRemovedKeys.forEach(newProps::remove);
newProps.putAll(loggingChangedProps);
reconfigLogging(false, newProps);
}
}
/**
* 设置日志策略
*
* @param first 是否首次设置
* @param allProps 配置项全量
*/
public void reconfigLogging(boolean first, Properties allProps) {
String searchRawHandler = "java.util.logging.SearchHandler";
String searchReadHandler = LoggingSearchHandler.class.getName();
Properties onlyLogProps = new Properties();
Environment envs = this.environment;
allProps.entrySet().forEach(x -> {
String key = x.getKey().toString();
if (key.startsWith("java.util.logging.") || key.contains(".level") || key.equals("handlers")) {
String val = envs.getPropertyValue(x.getValue()
.toString()
.replace("%m", "%tY%tm")
.replace("%d", "%tY%tm%td") // 兼容旧时间格式
.replace(searchRawHandler, searchReadHandler));
onlyLogProps.put(key.replace(searchRawHandler, searchReadHandler), val);
}
});
if (onlyLogProps.getProperty("java.util.logging.FileHandler.formatter") == null) {
if (application.isCompileMode()) {
onlyLogProps.setProperty("java.util.logging.FileHandler.formatter", SimpleFormatter.class.getName());
if (onlyLogProps.getProperty("java.util.logging.SimpleFormatter.format") == null) {
onlyLogProps.setProperty(
"java.util.logging.SimpleFormatter.format",
LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
}
} else {
onlyLogProps.setProperty(
"java.util.logging.FileHandler.formatter", LoggingFileHandler.LoggingFormater.class.getName());
}
}
if (onlyLogProps.getProperty("java.util.logging.ConsoleHandler.formatter") == null) {
if (application.isCompileMode()) {
onlyLogProps.setProperty("java.util.logging.ConsoleHandler.formatter", SimpleFormatter.class.getName());
if (onlyLogProps.getProperty("java.util.logging.SimpleFormatter.format") == null) {
onlyLogProps.setProperty(
"java.util.logging.SimpleFormatter.format",
LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
}
} else {
onlyLogProps.setProperty(
"java.util.logging.ConsoleHandler.formatter",
LoggingFileHandler.LoggingFormater.class.getName());
}
}
if (!application.isCompileMode()) { // ConsoleHandler替换成LoggingConsoleHandler
final String handlers = onlyLogProps.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.ConsoleHandler")) {
final String consoleHandlerClass = LoggingFileHandler.LoggingConsoleHandler.class.getName();
onlyLogProps.setProperty(
"handlers", handlers.replace("java.util.logging.ConsoleHandler", consoleHandlerClass));
Properties prop = new Properties();
String prefix = consoleHandlerClass + ".";
onlyLogProps.entrySet().forEach(x -> {
if (x.getKey().toString().startsWith("java.util.logging.ConsoleHandler.")) {
prop.put(
x.getKey().toString().replace("java.util.logging.ConsoleHandler.", prefix),
x.getValue());
}
});
prop.entrySet().forEach(x -> {
onlyLogProps.put(x.getKey(), x.getValue());
});
}
}
String fileHandlerPattern = onlyLogProps.getProperty("java.util.logging.FileHandler.pattern");
if (fileHandlerPattern != null && fileHandlerPattern.contains("%")) { // 带日期格式
final String fileHandlerClass = LoggingFileHandler.class.getName();
Properties prop = new Properties();
final String handlers = onlyLogProps.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.FileHandler")) {
// singletonrun模式下不输出文件日志
prop.setProperty(
"handlers",
handlers.replace(
"java.util.logging.FileHandler",
application.isSingletonMode() || application.isCompileMode() ? "" : fileHandlerClass));
}
if (!prop.isEmpty()) {
String prefix = fileHandlerClass + ".";
onlyLogProps.entrySet().forEach(x -> {
if (x.getKey().toString().startsWith("java.util.logging.FileHandler.")) {
prop.put(x.getKey().toString().replace("java.util.logging.FileHandler.", prefix), x.getValue());
}
});
prop.entrySet().forEach(x -> onlyLogProps.put(x.getKey(), x.getValue()));
}
if (!application.isCompileMode()) {
onlyLogProps.put(
SncpClient.class.getSimpleName() + ".handlers",
LoggingFileHandler.LoggingSncpFileHandler.class.getName());
}
}
if (application.isCompileMode()) {
onlyLogProps.put("handlers", "java.util.logging.ConsoleHandler");
Map newprop = new HashMap(onlyLogProps);
newprop.forEach((k, v) -> {
if (k.toString().startsWith("java.util.logging.FileHandler.")) {
onlyLogProps.remove(k);
}
});
}
/**
* 设置日志策略
*
* @param first 是否首次设置
* @param allProps 配置项全量
*/
public void reconfigLogging(boolean first, Properties allProps) {
String searchRawHandler = "java.util.logging.SearchHandler";
String searchReadHandler = LoggingSearchHandler.class.getName();
Properties onlyLogProps = new Properties();
Environment envs = this.environment;
allProps.entrySet().forEach(x -> {
String key = x.getKey().toString();
if (key.startsWith("java.util.logging.") || key.contains(".level") || key.equals("handlers")) {
String val = envs.getPropertyValue(x.getValue()
.toString()
.replace("%m", "%tY%tm")
.replace("%d", "%tY%tm%td") // 兼容旧时间格式
.replace(searchRawHandler, searchReadHandler));
onlyLogProps.put(key.replace(searchRawHandler, searchReadHandler), val);
}
});
if (onlyLogProps.getProperty("java.util.logging.FileHandler.formatter") == null) {
if (application.isCompileMode()) {
onlyLogProps.setProperty("java.util.logging.FileHandler.formatter", SimpleFormatter.class.getName());
if (onlyLogProps.getProperty("java.util.logging.SimpleFormatter.format") == null) {
onlyLogProps.setProperty(
"java.util.logging.SimpleFormatter.format",
LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
}
} else {
onlyLogProps.setProperty(
"java.util.logging.FileHandler.formatter", LoggingFileHandler.LoggingFormater.class.getName());
}
}
if (onlyLogProps.getProperty("java.util.logging.ConsoleHandler.formatter") == null) {
if (application.isCompileMode()) {
onlyLogProps.setProperty("java.util.logging.ConsoleHandler.formatter", SimpleFormatter.class.getName());
if (onlyLogProps.getProperty("java.util.logging.SimpleFormatter.format") == null) {
onlyLogProps.setProperty(
"java.util.logging.SimpleFormatter.format",
LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
}
} else {
onlyLogProps.setProperty(
"java.util.logging.ConsoleHandler.formatter",
LoggingFileHandler.LoggingFormater.class.getName());
}
}
if (!application.isCompileMode()) { // ConsoleHandler替换成LoggingConsoleHandler
final String handlers = onlyLogProps.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.ConsoleHandler")) {
final String consoleHandlerClass = LoggingFileHandler.LoggingConsoleHandler.class.getName();
onlyLogProps.setProperty(
"handlers", handlers.replace("java.util.logging.ConsoleHandler", consoleHandlerClass));
Properties prop = new Properties();
String prefix = consoleHandlerClass + ".";
onlyLogProps.entrySet().forEach(x -> {
if (x.getKey().toString().startsWith("java.util.logging.ConsoleHandler.")) {
prop.put(
x.getKey().toString().replace("java.util.logging.ConsoleHandler.", prefix),
x.getValue());
}
});
prop.entrySet().forEach(x -> {
onlyLogProps.put(x.getKey(), x.getValue());
});
}
}
String fileHandlerPattern = onlyLogProps.getProperty("java.util.logging.FileHandler.pattern");
if (fileHandlerPattern != null && fileHandlerPattern.contains("%")) { // 带日期格式
final String fileHandlerClass = LoggingFileHandler.class.getName();
Properties prop = new Properties();
final String handlers = onlyLogProps.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.FileHandler")) {
// singletonrun模式下不输出文件日志
prop.setProperty(
"handlers",
handlers.replace(
"java.util.logging.FileHandler",
application.isSingletonMode() || application.isCompileMode() ? "" : fileHandlerClass));
}
if (!prop.isEmpty()) {
String prefix = fileHandlerClass + ".";
onlyLogProps.entrySet().forEach(x -> {
if (x.getKey().toString().startsWith("java.util.logging.FileHandler.")) {
prop.put(x.getKey().toString().replace("java.util.logging.FileHandler.", prefix), x.getValue());
}
});
prop.entrySet().forEach(x -> onlyLogProps.put(x.getKey(), x.getValue()));
}
if (!application.isCompileMode()) {
onlyLogProps.put(
SncpClient.class.getSimpleName() + ".handlers",
LoggingFileHandler.LoggingSncpFileHandler.class.getName());
}
}
if (application.isCompileMode()) {
onlyLogProps.put("handlers", "java.util.logging.ConsoleHandler");
Map newprop = new HashMap(onlyLogProps);
newprop.forEach((k, v) -> {
if (k.toString().startsWith("java.util.logging.FileHandler.")) {
onlyLogProps.remove(k);
}
});
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(out);
onlyLogProps.forEach((x, y) -> ps.println(x + "=" + y));
try {
LogManager manager = LogManager.getLogManager();
manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
this.loggingProperties.clear();
this.loggingProperties.putAll(onlyLogProps);
Enumeration<String> en = manager.getLoggerNames();
while (en.hasMoreElements()) {
for (Handler handler : manager.getLogger(en.nextElement()).getHandlers()) {
if (handler instanceof LoggingSearchHandler) {
((LoggingSearchHandler) handler).application = application;
}
}
}
} catch (IOException e) { // 不会发生
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(out);
onlyLogProps.forEach((x, y) -> ps.println(x + "=" + y));
try {
LogManager manager = LogManager.getLogManager();
manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
this.loggingProperties.clear();
this.loggingProperties.putAll(onlyLogProps);
Enumeration<String> en = manager.getLoggerNames();
while (en.hasMoreElements()) {
for (Handler handler : manager.getLogger(en.nextElement()).getHandlers()) {
if (handler instanceof LoggingSearchHandler) {
((LoggingSearchHandler) handler).application = application;
}
}
}
} catch (IOException e) { // 不会发生
}
}
}

View File

@@ -29,325 +29,325 @@ import org.redkale.util.*;
*/
public class LoggingSearchHandler extends LoggingBaseHandler {
protected static final String DEFAULT_TABLE_NAME = "log-record";
protected static final String DEFAULT_TABLE_NAME = "log-record";
protected final LinkedBlockingQueue<SearchLogRecord> logqueue = new LinkedBlockingQueue();
protected final LinkedBlockingQueue<SearchLogRecord> logqueue = new LinkedBlockingQueue();
protected final AtomicInteger retryCount = new AtomicInteger(3);
protected final AtomicInteger retryCount = new AtomicInteger(3);
protected String tag = DEFAULT_TABLE_NAME; // 用于表前缀, 默认是
protected String tag = DEFAULT_TABLE_NAME; // 用于表前缀, 默认是
protected String tagDateFormat; // 需要时间格式化
protected String tagDateFormat; // 需要时间格式化
protected String pattern;
protected String pattern;
protected Pattern denyRegx;
protected Pattern denyRegx;
protected String sourceResourceName;
protected String sourceResourceName;
protected SearchSource source;
protected SearchSource source;
// 在LogManager.getLogManager().readConfiguration执行完后通过反射注入Application
protected Application application;
// 在LogManager.getLogManager().readConfiguration执行完后通过反射注入Application
protected Application application;
public LoggingSearchHandler() {
configure();
open();
}
public LoggingSearchHandler() {
configure();
open();
}
private void open() {
final String name = "Redkale-Logging-" + getClass().getSimpleName().replace("Logging", "") + "-Thread";
final int batchSize = 100; // 批量最多100条
final List<SearchLogRecord> logList = new ArrayList<>();
final Formatter formatter = new LoggingBaseHandler.LoggingFormater();
final PrintStream outStream = System.out;
new Thread() {
{
setName(name);
setDaemon(true);
}
private void open() {
final String name = "Redkale-Logging-" + getClass().getSimpleName().replace("Logging", "") + "-Thread";
final int batchSize = 100; // 批量最多100条
final List<SearchLogRecord> logList = new ArrayList<>();
final Formatter formatter = new LoggingBaseHandler.LoggingFormater();
final PrintStream outStream = System.out;
new Thread() {
{
setName(name);
setDaemon(true);
}
@Override
public void run() {
while (true) {
try {
SearchLogRecord log = logqueue.take();
while (source == null && retryCount.get() > 0) initSource();
// ----------------------写日志-------------------------
if (source == null) { // source加载失败
outStream.print(formatter.format(log.rawLog));
} else {
logList.add(log);
int size = batchSize;
while (--size > 0) {
log = logqueue.poll();
if (log == null) {
break;
}
logList.add(log);
}
source.insert(logList);
}
} catch (Exception e) {
ErrorManager err = getErrorManager();
if (err != null) {
err.error(null, e, ErrorManager.WRITE_FAILURE);
}
} finally {
logList.clear();
}
}
}
}.start();
}
@Override
public void run() {
while (true) {
try {
SearchLogRecord log = logqueue.take();
while (source == null && retryCount.get() > 0) initSource();
// ----------------------写日志-------------------------
if (source == null) { // source加载失败
outStream.print(formatter.format(log.rawLog));
} else {
logList.add(log);
int size = batchSize;
while (--size > 0) {
log = logqueue.poll();
if (log == null) {
break;
}
logList.add(log);
}
source.insert(logList);
}
} catch (Exception e) {
ErrorManager err = getErrorManager();
if (err != null) {
err.error(null, e, ErrorManager.WRITE_FAILURE);
}
} finally {
logList.clear();
}
}
}
}.start();
}
private void initSource() {
if (retryCount.get() < 1) {
return;
}
try {
Utility.sleep(3000); // 如果SearchSource自身在打印日志需要停顿一点时间让SearchSource初始化完成
if (application == null) {
Utility.sleep(3000);
}
if (application == null) {
return;
}
this.source = application.getResourceFactory().find(sourceResourceName, SearchSource.class);
if (retryCount.get() == 1 && this.source == null) {
System.err.println("ERROR: not load logging.source(" + sourceResourceName + ")");
}
} catch (Exception t) {
ErrorManager err = getErrorManager();
if (err != null) {
err.error(null, t, ErrorManager.WRITE_FAILURE);
}
} finally {
retryCount.decrementAndGet();
}
}
private void initSource() {
if (retryCount.get() < 1) {
return;
}
try {
Utility.sleep(3000); // 如果SearchSource自身在打印日志需要停顿一点时间让SearchSource初始化完成
if (application == null) {
Utility.sleep(3000);
}
if (application == null) {
return;
}
this.source = application.getResourceFactory().find(sourceResourceName, SearchSource.class);
if (retryCount.get() == 1 && this.source == null) {
System.err.println("ERROR: not load logging.source(" + sourceResourceName + ")");
}
} catch (Exception t) {
ErrorManager err = getErrorManager();
if (err != null) {
err.error(null, t, ErrorManager.WRITE_FAILURE);
}
} finally {
retryCount.decrementAndGet();
}
}
private static boolean checkTagName(String name) { // 只能是字母、数字、短横、点、%、$和下划线
if (name.isEmpty()) {
return false;
}
for (char ch : name.toCharArray()) {
if (ch >= '0' && ch <= '9') {
continue;
}
if (ch >= 'a' && ch <= 'z') {
continue;
}
if (ch >= 'A' && ch <= 'Z') {
continue;
}
if (ch == '_' || ch == '-' || ch == '%' || ch == '$' || ch == '.') {
continue;
}
return false;
}
return true;
}
private static boolean checkTagName(String name) { // 只能是字母、数字、短横、点、%、$和下划线
if (name.isEmpty()) {
return false;
}
for (char ch : name.toCharArray()) {
if (ch >= '0' && ch <= '9') {
continue;
}
if (ch >= 'a' && ch <= 'z') {
continue;
}
if (ch >= 'A' && ch <= 'Z') {
continue;
}
if (ch == '_' || ch == '-' || ch == '%' || ch == '$' || ch == '.') {
continue;
}
return false;
}
return true;
}
private void configure() {
LogManager manager = LogManager.getLogManager();
String cname = getClass().getName();
this.sourceResourceName = manager.getProperty(cname + ".source");
if (this.sourceResourceName == null || this.sourceResourceName.isEmpty()) {
throw new RedkaleException("not found logging.property " + cname + ".source");
}
String tagStr = manager.getProperty(cname + ".tag");
if (tagStr != null && !tagStr.isEmpty()) {
if (!checkTagName(tagStr.replaceAll("\\$\\{.+\\}", ""))) {
throw new RedkaleException("found illegal logging.property " + cname + ".tag = " + tagStr);
}
this.tag = tagStr.replace("${" + RESNAME_APP_NAME + "}", System.getProperty(SYSNAME_APP_NAME, ""));
if (this.tag.contains("%")) {
this.tagDateFormat = this.tag;
Times.formatTime(this.tagDateFormat, -1, System.currentTimeMillis()); // 测试时间格式是否正确
}
}
private void configure() {
LogManager manager = LogManager.getLogManager();
String cname = getClass().getName();
this.sourceResourceName = manager.getProperty(cname + ".source");
if (this.sourceResourceName == null || this.sourceResourceName.isEmpty()) {
throw new RedkaleException("not found logging.property " + cname + ".source");
}
String tagStr = manager.getProperty(cname + ".tag");
if (tagStr != null && !tagStr.isEmpty()) {
if (!checkTagName(tagStr.replaceAll("\\$\\{.+\\}", ""))) {
throw new RedkaleException("found illegal logging.property " + cname + ".tag = " + tagStr);
}
this.tag = tagStr.replace("${" + RESNAME_APP_NAME + "}", System.getProperty(SYSNAME_APP_NAME, ""));
if (this.tag.contains("%")) {
this.tagDateFormat = this.tag;
Times.formatTime(this.tagDateFormat, -1, System.currentTimeMillis()); // 测试时间格式是否正确
}
}
String levelStr = manager.getProperty(cname + ".level");
try {
if (levelStr != null) {
Level l = Level.parse(levelStr);
setLevel(l != null ? l : Level.ALL);
}
} catch (Exception e) {
// do nothing
}
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) {
// do nothing
}
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) {
// do nothing
}
if (getFormatter() == null) {
setFormatter(new SimpleFormatter());
}
String levelStr = manager.getProperty(cname + ".level");
try {
if (levelStr != null) {
Level l = Level.parse(levelStr);
setLevel(l != null ? l : Level.ALL);
}
} catch (Exception e) {
// do nothing
}
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) {
// do nothing
}
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) {
// do nothing
}
if (getFormatter() == null) {
setFormatter(new SimpleFormatter());
}
String encodingStr = manager.getProperty(cname + ".encoding");
try {
if (encodingStr != null) {
setEncoding(encodingStr);
}
} catch (Exception e) {
// do nothing
}
String encodingStr = manager.getProperty(cname + ".encoding");
try {
if (encodingStr != null) {
setEncoding(encodingStr);
}
} catch (Exception e) {
// do nothing
}
String denyRegxStr = manager.getProperty(cname + ".denyregx");
try {
if (denyRegxStr != null && !denyRegxStr.trim().isEmpty()) {
denyRegx = Pattern.compile(denyRegxStr);
}
} catch (Exception e) {
// do nothing
}
}
String denyRegxStr = manager.getProperty(cname + ".denyregx");
try {
if (denyRegxStr != null && !denyRegxStr.trim().isEmpty()) {
denyRegx = Pattern.compile(denyRegxStr);
}
} catch (Exception e) {
// do nothing
}
}
@Override
public void publish(LogRecord log) {
if (!isLoggable(log)) {
return;
}
if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return;
}
if (log.getSourceClassName() != null) {
StackTraceElement[] ses = new Throwable().getStackTrace();
for (int i = 2; i < ses.length; i++) {
if (ses[i].getClassName().startsWith("java.util.logging")) {
continue;
}
log.setSourceClassName(ses[i].getClassName());
log.setSourceMethodName(ses[i].getMethodName());
break;
}
}
String rawTag = tagDateFormat == null
? tag
: Times.formatTime(tagDateFormat, -1, log.getInstant().toEpochMilli());
fillLogRecord(log);
logqueue.offer(new SearchLogRecord(rawTag, log));
}
@Override
public void publish(LogRecord log) {
if (!isLoggable(log)) {
return;
}
if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return;
}
if (log.getSourceClassName() != null) {
StackTraceElement[] ses = new Throwable().getStackTrace();
for (int i = 2; i < ses.length; i++) {
if (ses[i].getClassName().startsWith("java.util.logging")) {
continue;
}
log.setSourceClassName(ses[i].getClassName());
log.setSourceMethodName(ses[i].getMethodName());
break;
}
}
String rawTag = tagDateFormat == null
? tag
: Times.formatTime(tagDateFormat, -1, log.getInstant().toEpochMilli());
fillLogRecord(log);
logqueue.offer(new SearchLogRecord(rawTag, log));
}
@Override
public void flush() {
// do nothing
}
@Override
public void flush() {
// do nothing
}
@Override
public void close() throws SecurityException {
// do nothing
}
@Override
public void close() throws SecurityException {
// do nothing
}
@Entity
@Table(name = DEFAULT_TABLE_NAME)
@DistributeTable(strategy = SearchLogRecord.TableStrategy.class)
public static class SearchLogRecord {
@Entity
@Table(name = DEFAULT_TABLE_NAME)
@DistributeTable(strategy = SearchLogRecord.TableStrategy.class)
public static class SearchLogRecord {
@Id
@ConvertColumn(index = 1)
@SearchColumn(options = "false")
public String logid;
@Id
@ConvertColumn(index = 1)
@SearchColumn(options = "false")
public String logid;
@ConvertColumn(index = 2)
@SearchColumn(options = "false")
public String level;
@ConvertColumn(index = 2)
@SearchColumn(options = "false")
public String level;
@ConvertColumn(index = 3)
@SearchColumn(date = true)
public long timestamp;
@ConvertColumn(index = 3)
@SearchColumn(date = true)
public long timestamp;
@ConvertColumn(index = 4)
@SearchColumn(options = "false")
public String traceid;
@ConvertColumn(index = 4)
@SearchColumn(options = "false")
public String traceid;
@ConvertColumn(index = 5)
public String threadName;
@ConvertColumn(index = 5)
public String threadName;
@ConvertColumn(index = 6)
@SearchColumn(text = true, options = "offsets")
public String loggerName;
@ConvertColumn(index = 6)
@SearchColumn(text = true, options = "offsets")
public String loggerName;
@ConvertColumn(index = 7)
@SearchColumn(text = true, options = "offsets")
public String methodName;
@ConvertColumn(index = 7)
@SearchColumn(text = true, options = "offsets")
public String methodName;
@ConvertColumn(index = 8)
@SearchColumn(text = true, options = "offsets") // , analyzer = "ik_max_word"
public String message; // log.message +"\r\n"+ log.thrown
@ConvertColumn(index = 8)
@SearchColumn(text = true, options = "offsets") // , analyzer = "ik_max_word"
public String message; // log.message +"\r\n"+ log.thrown
@Transient
@ConvertDisabled
LogRecord rawLog;
@Transient
@ConvertDisabled
LogRecord rawLog;
@Transient
@ConvertDisabled
String rawTag;
@Transient
@ConvertDisabled
String rawTag;
public SearchLogRecord() {}
public SearchLogRecord() {}
protected SearchLogRecord(String tag, LogRecord log) {
this.rawLog = log;
this.rawTag = tag;
this.threadName = Thread.currentThread().getName();
this.traceid = LoggingBaseHandler.traceEnable && Traces.enable() ? Traces.currentTraceid() : null;
String msg = log.getMessage();
if (log.getThrown() != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println();
log.getThrown().printStackTrace(pw);
pw.close();
String throwable = sw.toString();
this.message = (msg != null && !msg.isEmpty()) ? (msg + "\r\n" + throwable) : throwable;
} else {
this.message = msg;
}
this.level = log.getLevel().toString();
this.loggerName = log.getLoggerName();
this.methodName = log.getSourceClassName() + " " + log.getSourceMethodName();
this.timestamp = log.getInstant().toEpochMilli();
this.logid = Times.format36time(timestamp) + "_" + Utility.uuid();
}
protected SearchLogRecord(String tag, LogRecord log) {
this.rawLog = log;
this.rawTag = tag;
this.threadName = Thread.currentThread().getName();
this.traceid = LoggingBaseHandler.traceEnable && Traces.enable() ? Traces.currentTraceid() : null;
String msg = log.getMessage();
if (log.getThrown() != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println();
log.getThrown().printStackTrace(pw);
pw.close();
String throwable = sw.toString();
this.message = (msg != null && !msg.isEmpty()) ? (msg + "\r\n" + throwable) : throwable;
} else {
this.message = msg;
}
this.level = log.getLevel().toString();
this.loggerName = log.getLoggerName();
this.methodName = log.getSourceClassName() + " " + log.getSourceMethodName();
this.timestamp = log.getInstant().toEpochMilli();
this.logid = Times.format36time(timestamp) + "_" + Utility.uuid();
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
public static class TableStrategy implements DistributeTableStrategy<SearchLogRecord> {
public static class TableStrategy implements DistributeTableStrategy<SearchLogRecord> {
@Override
public String getTable(String table, SearchLogRecord bean) {
return bean.rawTag;
}
@Override
public String getTable(String table, SearchLogRecord bean) {
return bean.rawTag;
}
@Override
public String getTable(String table, Serializable primary) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getTable(String table, Serializable primary) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String[] getTables(String table, FilterNode node) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
@Override
public String[] getTables(String table, FilterNode node) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
}

View File

@@ -24,156 +24,156 @@ import org.redkale.util.Environment;
*/
public abstract class ModuleEngine {
protected final Logger logger = Logger.getLogger(getClass().getSimpleName());
protected final Logger logger = Logger.getLogger(getClass().getSimpleName());
protected final Application application;
protected final Application application;
protected final ResourceFactory resourceFactory;
protected final ResourceFactory resourceFactory;
protected final Environment environment;
protected final Environment environment;
public ModuleEngine(Application application) {
this.application = application;
this.resourceFactory = Objects.requireNonNull(application.resourceFactory);
this.environment = Objects.requireNonNull(application.getEnvironment());
}
public ModuleEngine(Application application) {
this.application = application;
this.resourceFactory = Objects.requireNonNull(application.resourceFactory);
this.environment = Objects.requireNonNull(application.getEnvironment());
}
/**
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
*
* @param path 配置项路径
* @param key 配置项名称
* @param val1 配置项原值
* @param val2 配置项新值
* @return MergeEnum
*/
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
return null;
}
/**
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
*
* @param path 配置项路径
* @param key 配置项名称
* @param val1 配置项原值
* @param val2 配置项新值
* @return MergeEnum
*/
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
return null;
}
/**
* 动态扩展类的方法
*
* @param remote 是否远程模式
* @param serviceClass 类
* @return 方法动态扩展器
*/
public AsmMethodBoost createAsmMethodBoost(boolean remote, Class serviceClass) {
return null;
}
/**
* 动态扩展类的方法
*
* @param remote 是否远程模式
* @param serviceClass 类
* @return 方法动态扩展器
*/
public AsmMethodBoost createAsmMethodBoost(boolean remote, Class serviceClass) {
return null;
}
/** 进入Application.init方法时被调用 此时状态: 1、远程配置项未获取 2、WorkExecutor未初始化 */
public void onAppPreInit() {
// do nothing
}
/** 进入Application.init方法时被调用 此时状态: 1、远程配置项未获取 2、WorkExecutor未初始化 */
public void onAppPreInit() {
// do nothing
}
/** 结束Application.init方法前被调用 */
public void onAppPostInit() {
// do nothing
}
/** 结束Application.init方法前被调用 */
public void onAppPostInit() {
// do nothing
}
/** 进入Application.start方法被调用 */
public void onAppPreStart() {
// do nothing
}
/** 进入Application.start方法被调用 */
public void onAppPreStart() {
// do nothing
}
/** 结束Application.start方法前被调用 */
public void onAppPostStart() {
// do nothing
}
/** 结束Application.start方法前被调用 */
public void onAppPostStart() {
// do nothing
}
/**
* 配置项加载后被调用
*
* @param allProps 配置项全量
*/
public void onEnvironmentLoaded(Properties allProps) {
// do nothing
}
/**
* 配置项加载后被调用
*
* @param allProps 配置项全量
*/
public void onEnvironmentLoaded(Properties allProps) {
// do nothing
}
/**
* 配置项变更时被调用
*
* @param namespace 命名空间
* @param events 变更项
*/
public void onEnvironmentChanged(String namespace, List<ResourceEvent> events) {
// do nothing
}
/**
* 配置项变更时被调用
*
* @param namespace 命名空间
* @param events 变更项
*/
public void onEnvironmentChanged(String namespace, List<ResourceEvent> events) {
// do nothing
}
/** Application 在运行Compile前调用 */
public void onPreCompile() {
// do nothing
}
/** Application 在运行Compile前调用 */
public void onPreCompile() {
// do nothing
}
/** Application 在运行Compile后调用 */
public void onPostCompile() {
// do nothing
}
/** Application 在运行Compile后调用 */
public void onPostCompile() {
// do nothing
}
/** 服务全部启动前被调用 */
public void onServersPreStart() {
// do nothing
}
/** 服务全部启动前被调用 */
public void onServersPreStart() {
// do nothing
}
/** 服务全部启动后被调用 */
public void onServersPostStart() {
// do nothing
}
/** 服务全部启动后被调用 */
public void onServersPostStart() {
// do nothing
}
/**
* 执行Service.init方法前被调用
*
* @param service Service
*/
public void onServicePreInit(Service service) {
// do nothing
}
/**
* 执行Service.init方法前被调用
*
* @param service Service
*/
public void onServicePreInit(Service service) {
// do nothing
}
/**
* 执行Service.init方法后被调用
*
* @param service Service
*/
public void onServicePostInit(Service service) {
// do nothing
}
/**
* 执行Service.init方法后被调用
*
* @param service Service
*/
public void onServicePostInit(Service service) {
// do nothing
}
/**
* 执行Service.destroy方法前被调用
*
* @param service Service
*/
public void onServicePreDestroy(Service service) {
// do nothing
}
/**
* 执行Service.destroy方法前被调用
*
* @param service Service
*/
public void onServicePreDestroy(Service service) {
// do nothing
}
/**
* 执行Service.destroy方法后被调用
*
* @param service Service
*/
public void onServicePostDestroy(Service service) {
// do nothing
}
/**
* 执行Service.destroy方法后被调用
*
* @param service Service
*/
public void onServicePostDestroy(Service service) {
// do nothing
}
/** 服务全部停掉前被调用 */
public void onServersPreStop() {
// do nothing
}
/** 服务全部停掉前被调用 */
public void onServersPreStop() {
// do nothing
}
/** 服务全部停掉后被调用 */
public void onServersPostStop() {
// do nothing
}
/** 服务全部停掉后被调用 */
public void onServersPostStop() {
// do nothing
}
/** 进入Application.shutdown方法被调用 */
public void onAppPreShutdown() {
// do nothing
}
/** 进入Application.shutdown方法被调用 */
public void onAppPreShutdown() {
// do nothing
}
/** 结束Application.shutdown方法前被调用 */
public void onAppPostShutdown() {
// do nothing
}
/** 结束Application.shutdown方法前被调用 */
public void onAppPostShutdown() {
// do nothing
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,23 +14,23 @@ package org.redkale.boot;
*/
public class NodeInterceptor {
/**
* * Server.start之前调用 <br>
* NodeServer.start的部署是先执行NodeInterceptor.preStart再执行 Server.start 方法
*
* @param server NodeServer
*/
public void preStart(NodeServer server) {
// do nothing
}
/**
* * Server.start之前调用 <br>
* NodeServer.start的部署是先执行NodeInterceptor.preStart再执行 Server.start 方法
*
* @param server NodeServer
*/
public void preStart(NodeServer server) {
// do nothing
}
/**
* Server.shutdown之前调用 <br>
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown再执行 Server.shutdown 方法
*
* @param server NodeServer
*/
public void preShutdown(NodeServer server) {
// do nothing
}
/**
* Server.shutdown之前调用 <br>
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown再执行 Server.shutdown 方法
*
* @param server NodeServer
*/
public void preShutdown(NodeServer server) {
// do nothing
}
}

View File

@@ -19,5 +19,5 @@ import java.lang.annotation.*;
@Documented
public @interface NodeProtocol {
String value();
String value();
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,159 +25,159 @@ import org.redkale.util.*;
@NodeProtocol("SNCP")
public class NodeSncpServer extends NodeServer {
protected final SncpServer sncpServer;
protected final SncpServer sncpServer;
private NodeSncpServer(Application application, AnyValue serconf) {
super(application, createServer(application, serconf));
this.sncpServer = (SncpServer) this.server;
}
private NodeSncpServer(Application application, AnyValue serconf) {
super(application, createServer(application, serconf));
this.sncpServer = (SncpServer) this.server;
}
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
return new NodeSncpServer(application, serconf);
}
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());
}
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();
}
@Override
public InetSocketAddress getSocketAddress() {
return sncpServer == null ? null : sncpServer.getSocketAddress();
}
@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;
List<SncpServlet> servlets = sncpServer.getSncpServlets();
Collections.sort(servlets);
@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;
List<SncpServlet> servlets = sncpServer.getSncpServlets();
Collections.sort(servlets);
int maxTypeLength = 0;
int maxNameLength = 0;
for (SncpServlet en : servlets) {
maxNameLength = Math.max(maxNameLength, en.getResourceName().length() + 1);
maxTypeLength =
Math.max(maxTypeLength, en.getResourceType().getName().length());
}
for (SncpServlet en : servlets) {
if (sb != null) {
sb.append("Load ")
.append(toSimpleString(en, maxTypeLength, maxNameLength))
.append(LINE_SEPARATOR);
}
}
if (sb != null && sb.length() > 0) {
logger.log(Level.FINE, sb.toString());
}
}
int maxTypeLength = 0;
int maxNameLength = 0;
for (SncpServlet en : servlets) {
maxNameLength = Math.max(maxNameLength, en.getResourceName().length() + 1);
maxTypeLength =
Math.max(maxTypeLength, en.getResourceType().getName().length());
}
for (SncpServlet en : servlets) {
if (sb != null) {
sb.append("Load ")
.append(toSimpleString(en, maxTypeLength, maxNameLength))
.append(LINE_SEPARATOR);
}
}
if (sb != null && sb.length() > 0) {
logger.log(Level.FINE, sb.toString());
}
}
private StringBuilder toSimpleString(SncpServlet servlet, int maxTypeLength, int maxNameLength) {
StringBuilder sb = new StringBuilder();
Class serviceType = servlet.getResourceType();
String serviceName = servlet.getResourceName();
int size = servlet.getActionSize();
sb.append(SncpServlet.class.getSimpleName()).append(" (type=").append(serviceType.getName());
int len = maxTypeLength - serviceType.getName().length();
for (int i = 0; i < len; i++) {
sb.append(' ');
}
sb.append(", serviceid=")
.append(servlet.getServiceid())
.append(", name='")
.append(serviceName)
.append("'");
for (int i = 0; i < maxNameLength - serviceName.length(); i++) {
sb.append(' ');
}
sb.append(", actions.size=").append(size > 9 ? "" : " ").append(size).append(")");
return sb;
}
private StringBuilder toSimpleString(SncpServlet servlet, int maxTypeLength, int maxNameLength) {
StringBuilder sb = new StringBuilder();
Class serviceType = servlet.getResourceType();
String serviceName = servlet.getResourceName();
int size = servlet.getActionSize();
sb.append(SncpServlet.class.getSimpleName()).append(" (type=").append(serviceType.getName());
int len = maxTypeLength - serviceType.getName().length();
for (int i = 0; i < len; i++) {
sb.append(' ');
}
sb.append(", serviceid=")
.append(servlet.getServiceid())
.append(", name='")
.append(serviceName)
.append("'");
for (int i = 0; i < maxNameLength - serviceName.length(); i++) {
sb.append(' ');
}
sb.append(", actions.size=").append(size > 9 ? "" : " ").append(size).append(")");
return sb;
}
@Override
public boolean isSNCP() {
return true;
}
@Override
public boolean isSNCP() {
return true;
}
public SncpServer getSncpServer() {
return sncpServer;
}
public SncpServer getSncpServer() {
return sncpServer;
}
@Override
protected void loadFilter(ClassFilter<? extends Filter> filterFilter) throws Exception {
if (sncpServer != null) {
loadSncpFilter(this.serverConf.getAnyValue("fliters"), filterFilter);
}
}
@Override
protected void loadFilter(ClassFilter<? extends Filter> filterFilter) 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;
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
for (FilterEntry<? extends Filter> entry : list) {
Class<SncpFilter> clazz = (Class<SncpFilter>) entry.getType();
if (Utility.isAbstractOrInterface(clazz)) {
continue;
}
if (entry.isExpect()) { // 跳过不自动加载的Filter
continue;
}
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
resourceFactory.inject(filter, this);
AnyValueWriter filterConf = (AnyValueWriter) entry.getProperty();
this.sncpServer.addSncpFilter(filter, filterConf);
if (sb != null) {
sb.append("Load ").append(clazz.getName()).append(LINE_SEPARATOR);
}
}
if (sb != null && sb.length() > 0) {
logger.log(Level.INFO, sb.toString());
}
}
@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;
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
for (FilterEntry<? extends Filter> entry : list) {
Class<SncpFilter> clazz = (Class<SncpFilter>) entry.getType();
if (Utility.isAbstractOrInterface(clazz)) {
continue;
}
if (entry.isExpect()) { // 跳过不自动加载的Filter
continue;
}
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
resourceFactory.inject(filter, this);
AnyValueWriter filterConf = (AnyValueWriter) entry.getProperty();
this.sncpServer.addSncpFilter(filter, filterConf);
if (sb != null) {
sb.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) throws Exception {
RedkaleClassLoader.putReflectionPublicClasses(SncpServlet.class.getName());
if (!application.isSingletonMode()) {
this.servletServices.stream()
.filter(x -> x.getClass().getAnnotation(Local.class) == null) // Local模式的Service不生成SncpServlet
.forEach(x -> {
SncpServlet servlet = sncpServer.addSncpServlet(x);
dynServletMap.put(x, servlet);
String mq = Sncp.getResourceMQ(x);
if (mq != null) {
MessageAgent agent =
application.getResourceFactory().find(mq, MessageAgent.class);
agent.putService(this, x, servlet);
}
});
}
}
@Override
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
RedkaleClassLoader.putReflectionPublicClasses(SncpServlet.class.getName());
if (!application.isSingletonMode()) {
this.servletServices.stream()
.filter(x -> x.getClass().getAnnotation(Local.class) == null) // Local模式的Service不生成SncpServlet
.forEach(x -> {
SncpServlet servlet = sncpServer.addSncpServlet(x);
dynServletMap.put(x, servlet);
String mq = Sncp.getResourceMQ(x);
if (mq != null) {
MessageAgent agent =
application.getResourceFactory().find(mq, MessageAgent.class);
agent.putService(this, x, servlet);
}
});
}
}
@Override
@SuppressWarnings("unchecked")
protected ClassFilter<Filter> createFilterClassFilter() {
return createClassFilter(
null,
null,
SncpFilter.class,
new Class[] {org.redkale.watch.WatchFilter.class},
null,
"filters",
"filter");
}
@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;
}
@Override
protected ClassFilter<Servlet> createServletClassFilter() {
return null;
}
}

View File

@@ -17,36 +17,36 @@ import org.redkale.watch.*;
@NodeProtocol("WATCH")
public class NodeWatchServer extends NodeHttpServer {
public NodeWatchServer(Application application, AnyValue serconf) {
super(application, serconf);
}
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<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<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
@SuppressWarnings("unchecked")
protected ClassFilter<Servlet> createServletClassFilter() {
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
}
@Override
protected List<ClassFilter> createOtherClassFilters() {
return null; // 不调用 super.createOtherClassFilters()
}
@Override
protected List<ClassFilter> createOtherClassFilters() {
return null; // 不调用 super.createOtherClassFilters()
}
@Override
public boolean isWATCH() {
return true;
}
@Override
public boolean isWATCH() {
return true;
}
}

View File

@@ -23,123 +23,123 @@ import org.redkale.util.Utility;
*/
public class PrepareCompiler {
// public static void main(String[] args) throws Exception {
// new PrepareCompiler().run();
// }
public Application run() throws Exception {
// 必须设置redkale.resource.skip.check=true
// 因redkale-maven-plugin的maven-core依赖jsr250会覆盖redkale的javax.annotation.Resource导致无法识别Resource.required方法
System.setProperty("redkale.resource.skip.check", "true");
final Application application = new Application(AppConfig.create(false, true));
application.init();
application.onPreCompile();
application.start();
final boolean hasSncp = application.getNodeServers().stream()
.filter(NodeSncpServer.class::isInstance)
.findFirst()
.isPresent();
// public static void main(String[] args) throws Exception {
// new PrepareCompiler().run();
// }
public Application run() throws Exception {
// 必须设置redkale.resource.skip.check=true
// 因redkale-maven-plugin的maven-core依赖jsr250会覆盖redkale的javax.annotation.Resource导致无法识别Resource.required方法
System.setProperty("redkale.resource.skip.check", "true");
final Application application = new Application(AppConfig.create(false, true));
application.init();
application.onPreCompile();
application.start();
final boolean hasSncp = application.getNodeServers().stream()
.filter(NodeSncpServer.class::isInstance)
.findFirst()
.isPresent();
final ClassFilter<?> entityFilter = new ClassFilter(application.getClassLoader(), Entity.class, Object.class);
final ClassFilter<?> entityFilter2 =
new ClassFilter(application.getClassLoader(), javax.persistence.Entity.class, Object.class);
final ClassFilter<?> beanFilter = new ClassFilter(application.getClassLoader(), Bean.class, Object.class);
final ClassFilter<?> beanFilter2 =
new ClassFilter(application.getClassLoader(), org.redkale.util.Bean.class, Object.class);
final ClassFilter<?> filterFilter = new ClassFilter(application.getClassLoader(), null, FilterBean.class);
final ClassFilter<?> entityFilter = new ClassFilter(application.getClassLoader(), Entity.class, Object.class);
final ClassFilter<?> entityFilter2 =
new ClassFilter(application.getClassLoader(), javax.persistence.Entity.class, Object.class);
final ClassFilter<?> beanFilter = new ClassFilter(application.getClassLoader(), Bean.class, Object.class);
final ClassFilter<?> beanFilter2 =
new ClassFilter(application.getClassLoader(), org.redkale.util.Bean.class, Object.class);
final ClassFilter<?> filterFilter = new ClassFilter(application.getClassLoader(), null, FilterBean.class);
application.loadClassByFilters(entityFilter, beanFilter, filterFilter);
application.loadClassByFilters(entityFilter, beanFilter, filterFilter);
for (FilterEntry en : entityFilter.getFilterEntrys()) {
Class clz = en.getType();
if (Utility.isAbstractOrInterface(clz)) {
continue;
}
try {
List<DataSource> dataSources = application.getResourceFactory().query(DataSource.class);
dataSources.forEach(source -> source.compile(clz));
// 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 : entityFilter2.getFilterEntrys()) {
Class clz = en.getType();
if (Utility.isAbstractOrInterface(clz)) {
continue;
}
try {
List<DataSource> dataSources = application.getResourceFactory().query(DataSource.class);
dataSources.forEach(source -> source.compile(clz));
// 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 (Utility.isAbstractOrInterface(clz)) {
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 : beanFilter2.getFilterEntrys()) {
Class clz = en.getType();
if (Utility.isAbstractOrInterface(clz)) {
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 (Utility.isAbstractOrInterface(clz)) {
continue;
}
try {
FilterNodeBean.load(clz);
} catch (Exception e) {
// do nothing
}
}
application.onPostCompile();
application.shutdown();
return application;
}
for (FilterEntry en : entityFilter.getFilterEntrys()) {
Class clz = en.getType();
if (Utility.isAbstractOrInterface(clz)) {
continue;
}
try {
List<DataSource> dataSources = application.getResourceFactory().query(DataSource.class);
dataSources.forEach(source -> source.compile(clz));
// 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 : entityFilter2.getFilterEntrys()) {
Class clz = en.getType();
if (Utility.isAbstractOrInterface(clz)) {
continue;
}
try {
List<DataSource> dataSources = application.getResourceFactory().query(DataSource.class);
dataSources.forEach(source -> source.compile(clz));
// 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 (Utility.isAbstractOrInterface(clz)) {
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 : beanFilter2.getFilterEntrys()) {
Class clz = en.getType();
if (Utility.isAbstractOrInterface(clz)) {
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 (Utility.isAbstractOrInterface(clz)) {
continue;
}
try {
FilterNodeBean.load(clz);
} catch (Exception e) {
// do nothing
}
}
application.onPostCompile();
application.shutdown();
return application;
}
}

View File

@@ -12,11 +12,11 @@ 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_PARAMS_ILLEGAL = 1600_0001;
/** 执行异常 */
@Comment("执行异常")
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
/** 执行异常 */
@Comment("执行异常")
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
}

View File

@@ -16,69 +16,69 @@ import org.redkale.service.RetResult;
@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_NOT_EXISTS = 1601_0002;
@Comment("Filter类名不合法")
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
@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类名已存在")
public static final int RET_FILTER_EXISTS = 1601_0004;
@Comment("Filter的JAR包不存在")
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
@Comment("Filter的JAR包不存在")
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
@Resource
protected Application application;
@Resource
protected Application application;
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
public RetResult addFilter(
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameRegx = "\\.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 = "addFilter", auth = false, comment = "动态增加Filter")
public RetResult addFilter(
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameRegx = "\\.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 = "test1", auth = false, comment = "预留")
public RetResult test1() {
return RetResult.success();
}
@RestMapping(name = "test2", auth = false, comment = "预留")
public RetResult test2() {
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 = "test3", auth = false, comment = "预留")
public RetResult test3() {
return RetResult.success();
}
@RestMapping(name = "test4", auth = false, comment = "预留")
public RetResult test4() {
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 = "test5", auth = false, comment = "预留")
public RetResult test5() {
return RetResult.success();
}
@RestMapping(name = "test6", auth = false, comment = "预留")
public RetResult test6() {
return RetResult.success();
}
@RestMapping(name = "test6", auth = false, comment = "预留")
public RetResult test6() {
return RetResult.success();
}
}

View File

@@ -19,99 +19,99 @@ import org.redkale.service.RetResult;
@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_NOT_EXISTS = 1602_0001;
@Comment("更改Server监听地址端口失败")
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
@Comment("更改Server监听地址端口失败")
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
@Resource
protected Application application;
@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 = "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 = "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();
}
@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;
}
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;
}
}

View File

@@ -22,241 +22,241 @@ import org.redkale.service.RetResult;
@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;
@Comment("没有找到目标Service")
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
@Resource
protected Application application;
@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 (" + 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 = "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 (" + 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 (" + 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 = "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 (" + 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() + ")");
}
}
@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;
}
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, fileNameRegx = "\\.jar$") byte[] jar) {
// 待开发
return RetResult.success();
}
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
public RetResult loadService(
@RestParam(name = "type", comment = "Service的类名") String type,
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameRegx = "\\.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 = "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 = "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();
}
@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();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -23,63 +23,63 @@ import org.redkale.service.LoadMode;
@Retention(RUNTIME)
public @interface Cached {
/**
* 缓存的key支持参数动态组合比如"key_#{id}"
*
* @return 键
*/
String key();
/**
* 缓存的key支持参数动态组合比如"key_#{id}"
*
* @return 键
*/
String key();
/**
* 缓存的hash, 不能含有':'、'#'、'@'字符
*
* @return hash
*/
String hash() default CacheManager.DEFAULT_HASH;
/**
* 缓存的hash, 不能含有':'、'#'、'@'字符
*
* @return hash
*/
String hash() default CacheManager.DEFAULT_HASH;
/**
* 本地缓存过期时长, 0表示永不过期 -1表示不作本地缓存。<br>
* 参数值支持方式:<br>
* 100: 设置数值 ${env.cache.expires}: 读取系统配置项
*
* @return 过期时长
*/
String localExpire() default "-1";
/**
* 本地缓存过期时长, 0表示永不过期 -1表示不作本地缓存。<br>
* 参数值支持方式:<br>
* 100: 设置数值 ${env.cache.expires}: 读取系统配置项
*
* @return 过期时长
*/
String localExpire() default "-1";
/**
* 远程缓存过期时长, 0表示永不过期 -1表示不作远程缓存。<br>
* 参数值支持方式:<br>
* 100: 设置数值 ${env.cache.expires}: 读取系统配置项
*
* @return 过期时长
*/
String remoteExpire() default "-1";
/**
* 远程缓存过期时长, 0表示永不过期 -1表示不作远程缓存。<br>
* 参数值支持方式:<br>
* 100: 设置数值 ${env.cache.expires}: 读取系统配置项
*
* @return 过期时长
*/
String remoteExpire() default "-1";
/**
* 是否可以缓存null值
*
* @return 是否可以缓存null
*/
boolean nullable() default false;
/**
* 是否可以缓存null值
*
* @return 是否可以缓存null
*/
boolean nullable() default false;
/**
* 过期时长的时间单位
*
* @return 时间单位
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
/**
* 过期时长的时间单位
*
* @return 时间单位
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
/**
* 备注
*
* @return 备注
*/
String comment() default "";
/**
* 备注
*
* @return 备注
*/
String comment() default "";
/**
* Service加载模式
*
* @return 模式
*/
LoadMode mode() default LoadMode.ANY;
/**
* Service加载模式
*
* @return 模式
*/
LoadMode mode() default LoadMode.ANY;
}

View File

@@ -29,128 +29,128 @@ import org.redkale.util.TypeToken;
@ClassDepends
public class CacheAction {
@Resource
private Environment environment;
@Resource
private Environment environment;
@Resource
private CacheManager manager;
@Resource
private CacheManager manager;
private final CacheEntry cached;
private final CacheEntry cached;
// Supplier对象的类型
private final Type resultType;
// Supplier对象的类型
private final Type resultType;
// 缓存方法是否异步
private final boolean async;
// 缓存方法是否异步
private final boolean async;
// 是否可以缓存null
private final boolean nullable;
// 是否可以缓存null
private final boolean nullable;
// 宿主对象的类
private final Class serviceClass;
// 宿主对象的类
private final Class serviceClass;
// 无法获取动态的Method只能存方法名
private final String methodName;
// 无法获取动态的Method只能存方法名
private final String methodName;
// 获取动态的字段名
private final String fieldName;
// 获取动态的字段名
private final String fieldName;
// 方法参数类型
@Nullable
private final Class[] paramTypes;
// 方法参数类型
@Nullable
private final Class[] paramTypes;
// 方法参数名
@Nullable
private final String[] paramNames;
// 方法参数名
@Nullable
private final String[] paramNames;
// 缓存的hash
private String hash;
// 缓存的hash
private String hash;
// 缓存的key
private MultiHashKey dynKey;
// 缓存的key
private MultiHashKey dynKey;
// 本地缓存过期时长Duration.ZERO为永不过期为null表示不本地缓存
private Duration localExpire;
// 本地缓存过期时长Duration.ZERO为永不过期为null表示不本地缓存
private Duration localExpire;
// 远程缓存过期时长Duration.ZERO为永不过期为null表示不远程缓存
private Duration remoteExpire;
// 远程缓存过期时长Duration.ZERO为永不过期为null表示不远程缓存
private Duration remoteExpire;
CacheAction(
CacheEntry cached,
Type returnType,
Class serviceClass,
Class[] paramTypes,
String[] paramNames,
String methodName,
String fieldName) {
this.cached = cached;
this.nullable = cached.isNullable();
this.serviceClass = Objects.requireNonNull(serviceClass);
this.paramTypes = paramTypes;
this.paramNames = paramNames;
this.methodName = Objects.requireNonNull(methodName);
this.fieldName = Objects.requireNonNull(fieldName);
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
}
CacheAction(
CacheEntry cached,
Type returnType,
Class serviceClass,
Class[] paramTypes,
String[] paramNames,
String methodName,
String fieldName) {
this.cached = cached;
this.nullable = cached.isNullable();
this.serviceClass = Objects.requireNonNull(serviceClass);
this.paramTypes = paramTypes;
this.paramNames = paramNames;
this.methodName = Objects.requireNonNull(methodName);
this.fieldName = Objects.requireNonNull(fieldName);
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
}
void init() {
this.hash = cached.getHash().trim().isEmpty() || CacheManager.DEFAULT_HASH.equals(cached.getHash())
? CacheManager.DEFAULT_HASH
: environment.getPropertyValue(cached.getHash());
String key = environment.getPropertyValue(cached.getKey());
this.dynKey = MultiHashKey.create(paramNames, key);
this.localExpire = createDuration(cached.getLocalExpire());
this.remoteExpire = createDuration(cached.getRemoteExpire());
}
void init() {
this.hash = cached.getHash().trim().isEmpty() || CacheManager.DEFAULT_HASH.equals(cached.getHash())
? CacheManager.DEFAULT_HASH
: environment.getPropertyValue(cached.getHash());
String key = environment.getPropertyValue(cached.getKey());
this.dynKey = MultiHashKey.create(paramNames, key);
this.localExpire = createDuration(cached.getLocalExpire());
this.remoteExpire = createDuration(cached.getRemoteExpire());
}
@ClassDepends
public <T> T get(ThrowSupplier<T> supplier, Object... args) {
if (async) {
ThrowSupplier supplier0 = supplier;
return (T) manager.bothGetSetAsync(
hash, dynKey.keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier0);
} else {
return manager.bothGetSet(
hash, dynKey.keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier);
}
}
@ClassDepends
public <T> T get(ThrowSupplier<T> supplier, Object... args) {
if (async) {
ThrowSupplier supplier0 = supplier;
return (T) manager.bothGetSetAsync(
hash, dynKey.keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier0);
} else {
return manager.bothGetSet(
hash, dynKey.keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier);
}
}
private Duration createDuration(String val) {
String str = environment.getPropertyValue(val);
if ("-1".equals(str) || "null".equalsIgnoreCase(str)) {
return null;
} else if ("0".equals(str)) {
return Duration.ZERO;
} else if (str.indexOf('*') > -1) {
long rs = 1;
for (String v : str.split("\\*")) {
if (!v.trim().isEmpty()) {
rs *= Long.parseLong(v.trim());
}
}
if (rs < 0) {
return null;
} else if (rs == 0) {
return Duration.ZERO;
} else {
return Duration.ofMillis(cached.getTimeUnit().toMillis(rs));
}
} else {
return Duration.ofMillis(cached.getTimeUnit().toMillis(Long.parseLong(str)));
}
}
private Duration createDuration(String val) {
String str = environment.getPropertyValue(val);
if ("-1".equals(str) || "null".equalsIgnoreCase(str)) {
return null;
} else if ("0".equals(str)) {
return Duration.ZERO;
} else if (str.indexOf('*') > -1) {
long rs = 1;
for (String v : str.split("\\*")) {
if (!v.trim().isEmpty()) {
rs *= Long.parseLong(v.trim());
}
}
if (rs < 0) {
return null;
} else if (rs == 0) {
return Duration.ZERO;
} else {
return Duration.ofMillis(cached.getTimeUnit().toMillis(rs));
}
} else {
return Duration.ofMillis(cached.getTimeUnit().toMillis(Long.parseLong(str)));
}
}
@Override
public String toString() {
return "{"
+ "\"serviceClass\":" + serviceClass.getName()
+ ",\"methodName\":\"" + methodName + "\""
+ ",\"fieldName\":\"" + fieldName + "\""
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(paramTypes)
+ ",\"paramNames\":" + JsonConvert.root().convertTo(paramNames)
+ ",\"resultType\":\"" + resultType + "\""
+ ",\"cache\":" + cached
+ "}";
}
@Override
public String toString() {
return "{"
+ "\"serviceClass\":" + serviceClass.getName()
+ ",\"methodName\":\"" + methodName + "\""
+ ",\"fieldName\":\"" + fieldName + "\""
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(paramTypes)
+ ",\"paramNames\":" + JsonConvert.root().convertTo(paramNames)
+ ",\"resultType\":\"" + resultType + "\""
+ ",\"cache\":" + cached
+ "}";
}
}

View File

@@ -35,214 +35,214 @@ import org.redkale.util.TypeToken;
/** @author zhangjx */
public class CacheAsmMethodBoost extends AsmMethodBoost {
private static final java.lang.reflect.Type FUTURE_VOID = new TypeToken<CompletableFuture<Void>>() {}.getType();
private static final java.lang.reflect.Type FUTURE_VOID = new TypeToken<CompletableFuture<Void>>() {}.getType();
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class, DynForCache.class);
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class, DynForCache.class);
private Map<String, CacheAction> actionMap;
private Map<String, CacheAction> actionMap;
public CacheAsmMethodBoost(boolean remote, Class serviceType) {
super(remote, serviceType);
}
public CacheAsmMethodBoost(boolean remote, Class serviceType) {
super(remote, serviceType);
}
@Override
public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
return FILTER_ANN;
}
@Override
public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
return FILTER_ANN;
}
@Override
public String doMethod(
ClassLoader classLoader,
ClassWriter cw,
String newDynName,
String fieldPrefix,
List filterAnns,
Method method,
final String newMethodName) {
Map<String, CacheAction> actions = this.actionMap;
if (actions == null) {
actions = new LinkedHashMap<>();
this.actionMap = actions;
}
Cached cached = method.getAnnotation(Cached.class);
if (cached == null) {
return newMethodName;
}
if (!LoadMode.matches(remote, cached.mode())) {
return newMethodName;
}
if (method.getAnnotation(DynForCache.class) != null) {
return newMethodName;
}
if (Modifier.isFinal(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) {
throw new RedkaleException(
"@" + Cached.class.getSimpleName() + " cannot on final or static method, but on " + method);
}
if (!Modifier.isProtected(method.getModifiers()) && !Modifier.isPublic(method.getModifiers())) {
throw new RedkaleException(
"@" + Cached.class.getSimpleName() + " must on protected or public method, but on " + method);
}
if (method.getReturnType() == void.class || FUTURE_VOID.equals(method.getGenericReturnType())) {
throw new RedkaleException("@" + Cached.class.getSimpleName() + " cannot on void method, but on " + method);
}
final int actionIndex = fieldIndex.incrementAndGet();
final String rsMethodName = method.getName() + "_afterCache";
final String dynFieldName = fieldPrefix + "_" + method.getName() + "CacheAction" + actionIndex;
final AsmMethodBean methodBean = getMethodBean(method);
{ // 定义一个新方法调用 this.rsMethodName
final String cacheDynDesc = Type.getDescriptor(DynForCache.class);
final MethodVisitor mv = createMethodVisitor(cw, method, newMethodName, methodBean);
// mv.setDebug(true);
AnnotationVisitor av = mv.visitAnnotation(cacheDynDesc, true);
av.visit("dynField", dynFieldName);
Asms.visitAnnotation(av, cached);
visitRawAnnotation(method, newMethodName, mv, Cached.class, filterAnns);
@Override
public String doMethod(
ClassLoader classLoader,
ClassWriter cw,
String newDynName,
String fieldPrefix,
List filterAnns,
Method method,
final String newMethodName) {
Map<String, CacheAction> actions = this.actionMap;
if (actions == null) {
actions = new LinkedHashMap<>();
this.actionMap = actions;
}
Cached cached = method.getAnnotation(Cached.class);
if (cached == null) {
return newMethodName;
}
if (!LoadMode.matches(remote, cached.mode())) {
return newMethodName;
}
if (method.getAnnotation(DynForCache.class) != null) {
return newMethodName;
}
if (Modifier.isFinal(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) {
throw new RedkaleException(
"@" + Cached.class.getSimpleName() + " cannot on final or static method, but on " + method);
}
if (!Modifier.isProtected(method.getModifiers()) && !Modifier.isPublic(method.getModifiers())) {
throw new RedkaleException(
"@" + Cached.class.getSimpleName() + " must on protected or public method, but on " + method);
}
if (method.getReturnType() == void.class || FUTURE_VOID.equals(method.getGenericReturnType())) {
throw new RedkaleException("@" + Cached.class.getSimpleName() + " cannot on void method, but on " + method);
}
final int actionIndex = fieldIndex.incrementAndGet();
final String rsMethodName = method.getName() + "_afterCache";
final String dynFieldName = fieldPrefix + "_" + method.getName() + "CacheAction" + actionIndex;
final AsmMethodBean methodBean = getMethodBean(method);
{ // 定义一个新方法调用 this.rsMethodName
final String cacheDynDesc = Type.getDescriptor(DynForCache.class);
final MethodVisitor mv = createMethodVisitor(cw, method, newMethodName, methodBean);
// mv.setDebug(true);
AnnotationVisitor av = mv.visitAnnotation(cacheDynDesc, true);
av.visit("dynField", dynFieldName);
Asms.visitAnnotation(av, cached);
visitRawAnnotation(method, newMethodName, mv, Cached.class, filterAnns);
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
List<Integer> insns = visitVarInsnParamTypes(mv, method, 0);
String dynDesc = methodBean.getDesc();
dynDesc = "(L" + newDynName + ";" + dynDesc.substring(1, dynDesc.lastIndexOf(')') + 1)
+ Type.getDescriptor(ThrowSupplier.class);
mv.visitInvokeDynamicInsn("get", dynDesc, Asms.createLambdaMetaHandle(), new Object[] {
org.redkale.asm.Type.getType("()Ljava/lang/Object;"),
new Handle(Opcodes.H_INVOKESPECIAL, newDynName, "lambda$" + actionIndex, methodBean.getDesc(), false),
org.redkale.asm.Type.getType("()" + Type.getDescriptor(method.getReturnType()))
});
mv.visitVarInsn(ASTORE, 1 + method.getParameterCount());
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, dynFieldName, Type.getDescriptor(CacheAction.class));
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
List<Integer> insns = visitVarInsnParamTypes(mv, method, 0);
String dynDesc = methodBean.getDesc();
dynDesc = "(L" + newDynName + ";" + dynDesc.substring(1, dynDesc.lastIndexOf(')') + 1)
+ Type.getDescriptor(ThrowSupplier.class);
mv.visitInvokeDynamicInsn("get", dynDesc, Asms.createLambdaMetaHandle(), new Object[] {
org.redkale.asm.Type.getType("()Ljava/lang/Object;"),
new Handle(Opcodes.H_INVOKESPECIAL, newDynName, "lambda$" + actionIndex, methodBean.getDesc(), false),
org.redkale.asm.Type.getType("()" + Type.getDescriptor(method.getReturnType()))
});
mv.visitVarInsn(ASTORE, 1 + method.getParameterCount());
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, dynFieldName, Type.getDescriptor(CacheAction.class));
mv.visitVarInsn(ALOAD, 1 + method.getParameterCount());
Asms.visitInsn(mv, method.getParameterCount());
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
int insn = 0;
Class[] paramtypes = method.getParameterTypes();
for (int j = 0; j < paramtypes.length; j++) {
final Class pt = paramtypes[j];
mv.visitInsn(DUP);
insn++;
Asms.visitInsn(mv, j);
if (pt.isPrimitive()) {
if (pt == long.class) {
mv.visitVarInsn(LLOAD, insn++);
} else if (pt == float.class) {
mv.visitVarInsn(FLOAD, insn++);
} else if (pt == double.class) {
mv.visitVarInsn(DLOAD, insn++);
} else {
mv.visitVarInsn(ILOAD, insn);
}
Class bigclaz = TypeToken.primitiveToWrapper(pt);
mv.visitMethodInsn(
INVOKESTATIC,
bigclaz.getName().replace('.', '/'),
"valueOf",
"(" + Type.getDescriptor((Class) pt) + ")" + Type.getDescriptor(bigclaz),
false);
} else {
mv.visitVarInsn(ALOAD, insn);
}
mv.visitInsn(AASTORE);
}
String throwFuncDesc = Type.getDescriptor(ThrowSupplier.class);
mv.visitMethodInsn(
INVOKEVIRTUAL,
CacheAction.class.getName().replace('.', '/'),
"get",
"(" + throwFuncDesc + "[Ljava/lang/Object;)Ljava/lang/Object;",
false);
mv.visitTypeInsn(CHECKCAST, method.getReturnType().getName().replace('.', '/'));
mv.visitInsn(ARETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLocalVariable("this", "L" + newDynName + ";", null, l0, l2, 0);
visitParamTypesLocalVariable(mv, method, l0, l2, insns, methodBean);
mv.visitLocalVariable("_redkale_supplier", Type.getDescriptor(ThrowSupplier.class), null, l1, l2, ++insn);
mv.visitVarInsn(ALOAD, 1 + method.getParameterCount());
Asms.visitInsn(mv, method.getParameterCount());
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
int insn = 0;
Class[] paramtypes = method.getParameterTypes();
for (int j = 0; j < paramtypes.length; j++) {
final Class pt = paramtypes[j];
mv.visitInsn(DUP);
insn++;
Asms.visitInsn(mv, j);
if (pt.isPrimitive()) {
if (pt == long.class) {
mv.visitVarInsn(LLOAD, insn++);
} else if (pt == float.class) {
mv.visitVarInsn(FLOAD, insn++);
} else if (pt == double.class) {
mv.visitVarInsn(DLOAD, insn++);
} else {
mv.visitVarInsn(ILOAD, insn);
}
Class bigclaz = TypeToken.primitiveToWrapper(pt);
mv.visitMethodInsn(
INVOKESTATIC,
bigclaz.getName().replace('.', '/'),
"valueOf",
"(" + Type.getDescriptor((Class) pt) + ")" + Type.getDescriptor(bigclaz),
false);
} else {
mv.visitVarInsn(ALOAD, insn);
}
mv.visitInsn(AASTORE);
}
String throwFuncDesc = Type.getDescriptor(ThrowSupplier.class);
mv.visitMethodInsn(
INVOKEVIRTUAL,
CacheAction.class.getName().replace('.', '/'),
"get",
"(" + throwFuncDesc + "[Ljava/lang/Object;)Ljava/lang/Object;",
false);
mv.visitTypeInsn(CHECKCAST, method.getReturnType().getName().replace('.', '/'));
mv.visitInsn(ARETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLocalVariable("this", "L" + newDynName + ";", null, l0, l2, 0);
visitParamTypesLocalVariable(mv, method, l0, l2, insns, methodBean);
mv.visitLocalVariable("_redkale_supplier", Type.getDescriptor(ThrowSupplier.class), null, l1, l2, ++insn);
mv.visitMaxs(20, 20);
mv.visitEnd();
CacheAction action = new CacheAction(
new CacheEntry(cached),
method.getGenericReturnType(),
serviceType,
method.getParameterTypes(),
methodBean.fieldNameArray(),
method.getName(),
dynFieldName);
actions.put(dynFieldName, action);
}
{ // ThrowSupplier
final MethodVisitor mv = cw.visitMethod(
ACC_PRIVATE + ACC_SYNTHETIC, "lambda$" + actionIndex, methodBean.getDesc(), null, new String[] {
"java/lang/Throwable"
});
// mv.setDebug(true);
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
visitVarInsnParamTypes(mv, method, 0);
mv.visitMethodInsn(INVOKESPECIAL, newDynName, rsMethodName, methodBean.getDesc(), false);
mv.visitInsn(ARETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "L" + newDynName + ";", null, l0, l1, 0);
mv.visitMaxs(5, 5);
mv.visitEnd();
}
{ // 定义字段
FieldVisitor fv =
cw.visitField(ACC_PRIVATE, dynFieldName, Type.getDescriptor(CacheAction.class), null, null);
fv.visitEnd();
}
if (actions.size() == 1) {
cw.visitInnerClass(
"java/lang/invoke/MethodHandles$Lookup",
"java/lang/invoke/MethodHandles",
"Lookup",
ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
}
return rsMethodName;
}
mv.visitMaxs(20, 20);
mv.visitEnd();
CacheAction action = new CacheAction(
new CacheEntry(cached),
method.getGenericReturnType(),
serviceType,
method.getParameterTypes(),
methodBean.fieldNameArray(),
method.getName(),
dynFieldName);
actions.put(dynFieldName, action);
}
{ // ThrowSupplier
final MethodVisitor mv = cw.visitMethod(
ACC_PRIVATE + ACC_SYNTHETIC, "lambda$" + actionIndex, methodBean.getDesc(), null, new String[] {
"java/lang/Throwable"
});
// mv.setDebug(true);
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
visitVarInsnParamTypes(mv, method, 0);
mv.visitMethodInsn(INVOKESPECIAL, newDynName, rsMethodName, methodBean.getDesc(), false);
mv.visitInsn(ARETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "L" + newDynName + ";", null, l0, l1, 0);
mv.visitMaxs(5, 5);
mv.visitEnd();
}
{ // 定义字段
FieldVisitor fv =
cw.visitField(ACC_PRIVATE, dynFieldName, Type.getDescriptor(CacheAction.class), null, null);
fv.visitEnd();
}
if (actions.size() == 1) {
cw.visitInnerClass(
"java/lang/invoke/MethodHandles$Lookup",
"java/lang/invoke/MethodHandles",
"Lookup",
ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
}
return rsMethodName;
}
@Override
public void doInstance(ResourceFactory resourceFactory, Object service) {
Class clazz = service.getClass();
if (actionMap == null) { // 为null表示没有调用过doMethod 动态类在编译是已经生成好了
actionMap = new LinkedHashMap<>();
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(clazz);
for (final Method method : clazz.getDeclaredMethods()) {
DynForCache cached = method.getAnnotation(DynForCache.class);
if (cached != null) {
String dynFieldName = cached.dynField();
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
CacheAction action = new CacheAction(
new CacheEntry(cached),
method.getGenericReturnType(),
serviceType,
method.getParameterTypes(),
methodBean.fieldNameArray(),
method.getName(),
dynFieldName);
actionMap.put(dynFieldName, action);
}
}
}
actionMap.forEach((field, action) -> {
try {
Field c = clazz.getDeclaredField(field);
c.setAccessible(true);
resourceFactory.inject(action);
action.init();
c.set(service, action);
RedkaleClassLoader.putReflectionField(clazz.getName(), c);
} catch (Exception e) {
throw new RedkaleException("field (" + field + ") in " + clazz.getName() + " set error", e);
}
});
// do nothing
}
@Override
public void doInstance(ResourceFactory resourceFactory, Object service) {
Class clazz = service.getClass();
if (actionMap == null) { // 为null表示没有调用过doMethod 动态类在编译是已经生成好了
actionMap = new LinkedHashMap<>();
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(clazz);
for (final Method method : clazz.getDeclaredMethods()) {
DynForCache cached = method.getAnnotation(DynForCache.class);
if (cached != null) {
String dynFieldName = cached.dynField();
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
CacheAction action = new CacheAction(
new CacheEntry(cached),
method.getGenericReturnType(),
serviceType,
method.getParameterTypes(),
methodBean.fieldNameArray(),
method.getName(),
dynFieldName);
actionMap.put(dynFieldName, action);
}
}
}
actionMap.forEach((field, action) -> {
try {
Field c = clazz.getDeclaredField(field);
c.setAccessible(true);
resourceFactory.inject(action);
action.init();
c.set(service, action);
RedkaleClassLoader.putReflectionField(clazz.getName(), c);
} catch (Exception e) {
throw new RedkaleException("field (" + field + ") in " + clazz.getName() + " set error", e);
}
});
// do nothing
}
}

View File

@@ -10,88 +10,88 @@ import org.redkale.convert.json.JsonConvert;
/** @author zhangjx */
public class CacheEntry {
private String key;
private String key;
private String hash;
private String hash;
private String localExpire;
private String localExpire;
private String remoteExpire;
private String remoteExpire;
private TimeUnit timeUnit;
private TimeUnit timeUnit;
private boolean nullable;
private boolean nullable;
public CacheEntry() {}
public CacheEntry() {}
public CacheEntry(DynForCache cached) {
this.key = cached.key();
this.hash = cached.hash();
this.localExpire = cached.localExpire();
this.remoteExpire = cached.remoteExpire();
this.timeUnit = cached.timeUnit();
this.nullable = cached.nullable();
}
public CacheEntry(DynForCache cached) {
this.key = cached.key();
this.hash = cached.hash();
this.localExpire = cached.localExpire();
this.remoteExpire = cached.remoteExpire();
this.timeUnit = cached.timeUnit();
this.nullable = cached.nullable();
}
public CacheEntry(Cached cached) {
this.key = cached.key();
this.hash = cached.hash();
this.localExpire = cached.localExpire();
this.remoteExpire = cached.remoteExpire();
this.timeUnit = cached.timeUnit();
this.nullable = cached.nullable();
}
public CacheEntry(Cached cached) {
this.key = cached.key();
this.hash = cached.hash();
this.localExpire = cached.localExpire();
this.remoteExpire = cached.remoteExpire();
this.timeUnit = cached.timeUnit();
this.nullable = cached.nullable();
}
public String getKey() {
return key;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setKey(String key) {
this.key = key;
}
public String getHash() {
return hash;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
public void setHash(String hash) {
this.hash = hash;
}
public String getLocalExpire() {
return localExpire;
}
public String getLocalExpire() {
return localExpire;
}
public void setLocalExpire(String localExpire) {
this.localExpire = localExpire;
}
public void setLocalExpire(String localExpire) {
this.localExpire = localExpire;
}
public String getRemoteExpire() {
return remoteExpire;
}
public String getRemoteExpire() {
return remoteExpire;
}
public void setRemoteExpire(String remoteExpire) {
this.remoteExpire = remoteExpire;
}
public void setRemoteExpire(String remoteExpire) {
this.remoteExpire = remoteExpire;
}
public TimeUnit getTimeUnit() {
return timeUnit;
}
public TimeUnit getTimeUnit() {
return timeUnit;
}
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
public boolean isNullable() {
return nullable;
}
public boolean isNullable() {
return nullable;
}
public void setNullable(boolean nullable) {
this.nullable = nullable;
}
public void setNullable(boolean nullable) {
this.nullable = nullable;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,83 +19,83 @@ import org.redkale.util.RedkaleClassLoader;
/** @author zhangjx */
public class CacheModuleEngine extends ModuleEngine {
// 全局缓存管理器
private CacheManager cacheManager;
// 全局缓存管理器
private CacheManager cacheManager;
private AnyValue config;
private AnyValue config;
public CacheModuleEngine(Application application) {
super(application);
}
public CacheModuleEngine(Application application) {
super(application);
}
/**
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
*
* @param path 配置项路径
* @param key 配置项名称
* @param val1 配置项原值
* @param val2 配置项新值
* @return MergeEnum
*/
@Override
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
if ("".equals(path) && "cache".equals(key)) {
return AnyValue.MergeEnum.REPLACE;
}
return null;
}
/**
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
*
* @param path 配置项路径
* @param key 配置项名称
* @param val1 配置项原值
* @param val2 配置项新值
* @return MergeEnum
*/
@Override
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
if ("".equals(path) && "cache".equals(key)) {
return AnyValue.MergeEnum.REPLACE;
}
return null;
}
/**
* 动态扩展类的方法
*
* @param remote 是否远程模式
* @param serviceClass 类
* @return 方法动态扩展器
*/
@Override
public AsmMethodBoost createAsmMethodBoost(boolean remote, Class serviceClass) {
return new CacheAsmMethodBoost(remote, serviceClass);
}
/**
* 动态扩展类的方法
*
* @param remote 是否远程模式
* @param serviceClass 类
* @return 方法动态扩展器
*/
@Override
public AsmMethodBoost createAsmMethodBoost(boolean remote, Class serviceClass) {
return new CacheAsmMethodBoost(remote, serviceClass);
}
/** 结束Application.init方法前被调用 */
@Override
public void onAppPostInit() {
// 设置缓存管理器
this.config = application.getAppConfig().getAnyValue("cache");
this.cacheManager = createManager(this.config);
if (!application.isCompileMode()) {
this.resourceFactory.inject(this.cacheManager);
if (this.cacheManager instanceof Service) {
((Service) this.cacheManager).init(this.config);
}
}
this.resourceFactory.register("", CacheManager.class, this.cacheManager);
}
/** 结束Application.init方法前被调用 */
@Override
public void onAppPostInit() {
// 设置缓存管理器
this.config = application.getAppConfig().getAnyValue("cache");
this.cacheManager = createManager(this.config);
if (!application.isCompileMode()) {
this.resourceFactory.inject(this.cacheManager);
if (this.cacheManager instanceof Service) {
((Service) this.cacheManager).init(this.config);
}
}
this.resourceFactory.register("", CacheManager.class, this.cacheManager);
}
/** 进入Application.shutdown方法被调用 */
@Override
public void onAppPreShutdown() {
if (!application.isCompileMode() && this.cacheManager instanceof Service) {
((Service) this.cacheManager).destroy(this.config);
}
}
/** 进入Application.shutdown方法被调用 */
@Override
public void onAppPreShutdown() {
if (!application.isCompileMode() && this.cacheManager instanceof Service) {
((Service) this.cacheManager).destroy(this.config);
}
}
private CacheManager createManager(AnyValue conf) {
Iterator<CacheManagerProvider> it = ServiceLoader.load(CacheManagerProvider.class, application.getClassLoader())
.iterator();
RedkaleClassLoader.putServiceLoader(CacheManagerProvider.class);
List<CacheManagerProvider> providers = new ArrayList<>();
while (it.hasNext()) {
CacheManagerProvider provider = it.next();
if (provider != null && provider.acceptsConf(conf)) {
RedkaleClassLoader.putReflectionPublicConstructors(
provider.getClass(), provider.getClass().getName());
providers.add(provider);
}
}
for (CacheManagerProvider provider : InstanceProvider.sort(providers)) {
return provider.createInstance();
}
return CacheManagerService.create(null).enabled(false);
}
private CacheManager createManager(AnyValue conf) {
Iterator<CacheManagerProvider> it = ServiceLoader.load(CacheManagerProvider.class, application.getClassLoader())
.iterator();
RedkaleClassLoader.putServiceLoader(CacheManagerProvider.class);
List<CacheManagerProvider> providers = new ArrayList<>();
while (it.hasNext()) {
CacheManagerProvider provider = it.next();
if (provider != null && provider.acceptsConf(conf)) {
RedkaleClassLoader.putReflectionPublicConstructors(
provider.getClass(), provider.getClass().getName());
providers.add(provider);
}
}
for (CacheManagerProvider provider : InstanceProvider.sort(providers)) {
return provider.createInstance();
}
return CacheManagerService.create(null).enabled(false);
}
}

View File

@@ -17,37 +17,37 @@ import org.redkale.convert.json.JsonConvert;
*/
public class CacheValue<T> {
@ConvertColumn(index = 1)
private T val;
@ConvertColumn(index = 1)
private T val;
public CacheValue() {}
public CacheValue() {}
protected CacheValue(T value) {
this.val = value;
}
protected CacheValue(T value) {
this.val = value;
}
public static <T> CacheValue<T> create(T value) {
return new CacheValue(value);
}
public static <T> CacheValue<T> create(T value) {
return new CacheValue(value);
}
public static boolean isValid(CacheValue val) {
return val != null;
}
public static boolean isValid(CacheValue val) {
return val != null;
}
public static <T> T get(CacheValue val) {
return isValid(val) ? (T) val.getVal() : null;
}
public static <T> T get(CacheValue val) {
return isValid(val) ? (T) val.getVal() : null;
}
public T getVal() {
return val;
}
public T getVal() {
return val;
}
public void setVal(T val) {
this.val = val;
}
public void setVal(T val) {
this.val = val;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -23,19 +23,19 @@ import org.redkale.service.LoadMode;
@Retention(RUNTIME)
public @interface DynForCache {
String dynField();
String dynField();
String key();
String key();
String hash();
String hash();
String localExpire();
String localExpire();
String remoteExpire();
String remoteExpire();
TimeUnit timeUnit();
TimeUnit timeUnit();
boolean nullable();
boolean nullable();
LoadMode mode() default LoadMode.ANY;
LoadMode mode() default LoadMode.ANY;
}

View File

@@ -17,19 +17,19 @@ import java.util.concurrent.CompletableFuture;
*/
public interface ClusterRpcClient<R, P> {
/**
* 发送消息,需要响应
*
* @param message 消息体
* @return 应答消息
*/
public CompletableFuture<P> sendMessage(final R message);
/**
* 发送消息,需要响应
*
* @param message 消息体
* @return 应答消息
*/
public CompletableFuture<P> sendMessage(final R message);
/**
* 发送消息,无需响应
*
* @param message 消息体
* @return 应答
*/
public CompletableFuture<Void> produceMessage(R message);
/**
* 发送消息,无需响应
*
* @param message 消息体
* @return 应答
*/
public CompletableFuture<Void> produceMessage(R message);
}

View File

@@ -22,106 +22,106 @@ import org.redkale.util.RedkaleException;
*/
public abstract class HttpRpcClient implements ClusterRpcClient<WebRequest, HttpResult<byte[]>> {
@Override
public final CompletableFuture<Void> produceMessage(WebRequest request) {
return produceMessage(generateHttpReqTopic(request, null), 0, null, request);
}
@Override
public final CompletableFuture<Void> produceMessage(WebRequest request) {
return produceMessage(generateHttpReqTopic(request, null), 0, null, request);
}
public final CompletableFuture<Void> produceMessage(Serializable userid, WebRequest request) {
return produceMessage(generateHttpReqTopic(request, null), userid, null, request);
}
public final CompletableFuture<Void> produceMessage(Serializable userid, WebRequest request) {
return produceMessage(generateHttpReqTopic(request, null), userid, null, request);
}
public final CompletableFuture<Void> produceMessage(Serializable userid, String groupid, WebRequest request) {
return produceMessage(generateHttpReqTopic(request, null), userid, groupid, request);
}
public final CompletableFuture<Void> produceMessage(Serializable userid, String groupid, WebRequest request) {
return produceMessage(generateHttpReqTopic(request, null), userid, groupid, request);
}
public final CompletableFuture<Void> produceMessage(String topic, WebRequest request) {
return produceMessage(topic, 0, null, request);
}
public final CompletableFuture<Void> produceMessage(String topic, WebRequest request) {
return produceMessage(topic, 0, null, request);
}
@Override
public final CompletableFuture<HttpResult<byte[]>> sendMessage(WebRequest request) {
return sendMessage(generateHttpReqTopic(request, null), 0, null, request);
}
@Override
public final CompletableFuture<HttpResult<byte[]>> sendMessage(WebRequest request) {
return sendMessage(generateHttpReqTopic(request, null), 0, null, request);
}
public final CompletableFuture<HttpResult<byte[]>> sendMessage(Serializable userid, WebRequest request) {
return sendMessage(generateHttpReqTopic(request, null), userid, null, request);
}
public final CompletableFuture<HttpResult<byte[]>> sendMessage(Serializable userid, WebRequest request) {
return sendMessage(generateHttpReqTopic(request, null), userid, null, request);
}
public final CompletableFuture<HttpResult<byte[]>> sendMessage(
Serializable userid, String groupid, WebRequest request) {
return sendMessage(generateHttpReqTopic(request, null), userid, groupid, request);
}
public final CompletableFuture<HttpResult<byte[]>> sendMessage(
Serializable userid, String groupid, WebRequest request) {
return sendMessage(generateHttpReqTopic(request, null), userid, groupid, request);
}
public final CompletableFuture<HttpResult<byte[]>> sendMessage(String topic, WebRequest request) {
return sendMessage(topic, 0, null, request);
}
public final CompletableFuture<HttpResult<byte[]>> sendMessage(String topic, WebRequest request) {
return sendMessage(topic, 0, null, request);
}
public <T> CompletableFuture<T> sendMessage(WebRequest request, Type type) {
return sendMessage(generateHttpReqTopic(request, null), 0, null, request)
.thenApply((HttpResult<byte[]> httbs) -> {
if (!httbs.isSuccess()) {
throw new RedkaleException(httbs.getHeader("retinfo", "Internal Server Error"));
}
if (httbs.getResult() == null) {
return null;
}
return JsonConvert.root().convertFrom(type, httbs.getResult());
});
}
public <T> CompletableFuture<T> sendMessage(WebRequest request, Type type) {
return sendMessage(generateHttpReqTopic(request, null), 0, null, request)
.thenApply((HttpResult<byte[]> httbs) -> {
if (!httbs.isSuccess()) {
throw new RedkaleException(httbs.getHeader("retinfo", "Internal Server Error"));
}
if (httbs.getResult() == null) {
return null;
}
return JsonConvert.root().convertFrom(type, httbs.getResult());
});
}
public <T> CompletableFuture<T> sendMessage(Serializable userid, WebRequest request, Type type) {
return sendMessage(generateHttpReqTopic(request, null), userid, null, request)
.thenApply((HttpResult<byte[]> httbs) -> {
if (!httbs.isSuccess()) {
throw new RedkaleException(httbs.getHeader("retinfo", "Internal Server Error"));
}
if (httbs.getResult() == null) {
return null;
}
return JsonConvert.root().convertFrom(type, httbs.getResult());
});
}
public <T> CompletableFuture<T> sendMessage(Serializable userid, WebRequest request, Type type) {
return sendMessage(generateHttpReqTopic(request, null), userid, null, request)
.thenApply((HttpResult<byte[]> httbs) -> {
if (!httbs.isSuccess()) {
throw new RedkaleException(httbs.getHeader("retinfo", "Internal Server Error"));
}
if (httbs.getResult() == null) {
return null;
}
return JsonConvert.root().convertFrom(type, httbs.getResult());
});
}
public <T> CompletableFuture<T> sendMessage(Serializable userid, String groupid, WebRequest request, Type type) {
return sendMessage(generateHttpReqTopic(request, null), userid, groupid, request)
.thenApply((HttpResult<byte[]> httbs) -> {
if (!httbs.isSuccess()) {
throw new RedkaleException(httbs.getHeader("retinfo", "Internal Server Error"));
}
if (httbs.getResult() == null) {
return null;
}
return JsonConvert.root().convertFrom(type, httbs.getResult());
});
}
public <T> CompletableFuture<T> sendMessage(Serializable userid, String groupid, WebRequest request, Type type) {
return sendMessage(generateHttpReqTopic(request, null), userid, groupid, request)
.thenApply((HttpResult<byte[]> httbs) -> {
if (!httbs.isSuccess()) {
throw new RedkaleException(httbs.getHeader("retinfo", "Internal Server Error"));
}
if (httbs.getResult() == null) {
return null;
}
return JsonConvert.root().convertFrom(type, httbs.getResult());
});
}
// 格式: http.req.user
public String generateHttpReqTopic(String module) {
return Rest.generateHttpReqTopic(module, getNodeid());
}
// 格式: http.req.user
public String generateHttpReqTopic(String module) {
return Rest.generateHttpReqTopic(module, getNodeid());
}
// 格式: http.req.user-n10
public String generateHttpReqTopic(String module, String resname) {
return Rest.generateHttpReqTopic(module, resname, getNodeid());
}
// 格式: http.req.user-n10
public String generateHttpReqTopic(String module, String resname) {
return Rest.generateHttpReqTopic(module, resname, getNodeid());
}
public String generateHttpReqTopic(WebRequest request, String path) {
String module = request.getPath();
if (path != null && !path.isEmpty() && module.startsWith(path)) {
module = module.substring(path.length());
}
module = module.substring(1); // 去掉/
module = module.substring(0, module.indexOf('/'));
String resname = request.getHeader(Rest.REST_HEADER_RESNAME, "");
return Rest.generateHttpReqTopic(module, resname, getNodeid());
}
public String generateHttpReqTopic(WebRequest request, String path) {
String module = request.getPath();
if (path != null && !path.isEmpty() && module.startsWith(path)) {
module = module.substring(path.length());
}
module = module.substring(1); // 去掉/
module = module.substring(0, module.indexOf('/'));
String resname = request.getHeader(Rest.REST_HEADER_RESNAME, "");
return Rest.generateHttpReqTopic(module, resname, getNodeid());
}
public abstract CompletableFuture<HttpResult<byte[]>> sendMessage(
String topic, Serializable userid, String groupid, WebRequest request);
public abstract CompletableFuture<HttpResult<byte[]>> sendMessage(
String topic, Serializable userid, String groupid, WebRequest request);
public abstract CompletableFuture<Void> produceMessage(
String topic, Serializable userid, String groupid, WebRequest request);
public abstract CompletableFuture<Void> produceMessage(
String topic, Serializable userid, String groupid, WebRequest request);
protected abstract String getNodeid();
protected abstract String getNodeid();
}

View File

@@ -29,376 +29,376 @@ import org.redkale.util.*;
*/
public class CacheClusterAgent extends ClusterAgent implements Resourcable {
@Resource(name = Resource.PARENT_NAME)
private CacheSource source;
@Resource(name = Resource.PARENT_NAME)
private CacheSource source;
private String sourceName;
private String sourceName;
protected int ttls = 10; // 定时检查的秒数
protected int ttls = 10; // 定时检查的秒数
protected ScheduledThreadPoolExecutor scheduler;
protected ScheduledThreadPoolExecutor scheduler;
protected ScheduledFuture taskFuture;
protected ScheduledFuture taskFuture;
// 可能被HttpMessageClient用到的服务 key: serviceName例如: cluster.service.http.user
protected final ConcurrentHashMap<String, Set<InetSocketAddress>> httpAddressMap = new ConcurrentHashMap<>();
// 可能被HttpMessageClient用到的服务 key: serviceName例如: cluster.service.http.user
protected final ConcurrentHashMap<String, Set<InetSocketAddress>> httpAddressMap = new ConcurrentHashMap<>();
// 可能被sncp用到的服务 key: serviceName, 例如: cluster.service.sncp.user
protected final ConcurrentHashMap<String, Set<InetSocketAddress>> sncpAddressMap = new ConcurrentHashMap<>();
// 可能被sncp用到的服务 key: serviceName, 例如: cluster.service.sncp.user
protected final ConcurrentHashMap<String, Set<InetSocketAddress>> sncpAddressMap = new ConcurrentHashMap<>();
@Override
public void init(AnyValue config) {
super.init(config);
this.sourceName = getSourceName();
this.ttls = config.getIntValue("ttls", 10);
if (this.ttls < 5) { // 值不能太小
this.ttls = 10;
}
}
@Override
public void init(AnyValue config) {
super.init(config);
this.sourceName = getSourceName();
this.ttls = config.getIntValue("ttls", 10);
if (this.ttls < 5) { // 值不能太小
this.ttls = 10;
}
}
@Override
@ResourceChanged
public void onResourceChange(ResourceEvent[] events) {
StringBuilder sb = new StringBuilder();
int newTtls = this.ttls;
for (ResourceEvent event : events) {
if ("ttls".equals(event.name())) {
newTtls = Integer.parseInt(event.newValue().toString());
if (newTtls < 5) {
sb.append(CacheClusterAgent.class.getSimpleName())
.append("(name=")
.append(resourceName())
.append(") cannot change '")
.append(event.name())
.append("' to '")
.append(event.coverNewValue())
.append("'\r\n");
} else {
sb.append(CacheClusterAgent.class.getSimpleName())
.append("(name=")
.append(resourceName())
.append(") change '")
.append(event.name())
.append("' to '")
.append(event.coverNewValue())
.append("'\r\n");
}
} else {
sb.append(CacheClusterAgent.class.getSimpleName())
.append("(name=")
.append(resourceName())
.append(") skip change '")
.append(event.name())
.append("' to '")
.append(event.coverNewValue())
.append("'\r\n");
}
}
if (newTtls != this.ttls) {
this.ttls = newTtls;
start();
}
if (sb.length() > 0) {
logger.log(Level.INFO, sb.toString());
}
}
@Override
@ResourceChanged
public void onResourceChange(ResourceEvent[] events) {
StringBuilder sb = new StringBuilder();
int newTtls = this.ttls;
for (ResourceEvent event : events) {
if ("ttls".equals(event.name())) {
newTtls = Integer.parseInt(event.newValue().toString());
if (newTtls < 5) {
sb.append(CacheClusterAgent.class.getSimpleName())
.append("(name=")
.append(resourceName())
.append(") cannot change '")
.append(event.name())
.append("' to '")
.append(event.coverNewValue())
.append("'\r\n");
} else {
sb.append(CacheClusterAgent.class.getSimpleName())
.append("(name=")
.append(resourceName())
.append(") change '")
.append(event.name())
.append("' to '")
.append(event.coverNewValue())
.append("'\r\n");
}
} else {
sb.append(CacheClusterAgent.class.getSimpleName())
.append("(name=")
.append(resourceName())
.append(") skip change '")
.append(event.name())
.append("' to '")
.append(event.coverNewValue())
.append("'\r\n");
}
}
if (newTtls != this.ttls) {
this.ttls = newTtls;
start();
}
if (sb.length() > 0) {
logger.log(Level.INFO, sb.toString());
}
}
@Override
public void setConfig(AnyValue config) {
super.setConfig(config);
this.sourceName = getSourceName();
}
@Override
public void setConfig(AnyValue config) {
super.setConfig(config);
this.sourceName = getSourceName();
}
@Override
public void destroy(AnyValue config) {
if (scheduler != null) {
scheduler.shutdownNow();
}
}
@Override
public void destroy(AnyValue config) {
if (scheduler != null) {
scheduler.shutdownNow();
}
}
public String getSourceName() {
return config.getValue("source");
}
public String getSourceName() {
return config.getValue("source");
}
@Override
public String resourceName() {
return sourceName;
}
@Override
public String resourceName() {
return sourceName;
}
@Override // ServiceLoader时判断配置是否符合当前实现类
public boolean acceptsConf(AnyValue config) {
if (config == null) {
return false;
}
return config.getValue("source") != null;
}
@Override // ServiceLoader时判断配置是否符合当前实现类
public boolean acceptsConf(AnyValue config) {
if (config == null) {
return false;
}
return config.getValue("source") != null;
}
@Override
public void start() {
if (this.scheduler == null) {
this.scheduler = Utility.newScheduledExecutor(
1, "Redkale-" + CacheClusterAgent.class.getSimpleName() + "-Check-Thread-%s");
}
if (this.taskFuture != null) {
this.taskFuture.cancel(true);
}
this.taskFuture = this.scheduler.scheduleAtFixedRate(newTask(), ttls, ttls, TimeUnit.SECONDS);
}
@Override
public void start() {
if (this.scheduler == null) {
this.scheduler = Utility.newScheduledExecutor(
1, "Redkale-" + CacheClusterAgent.class.getSimpleName() + "-Check-Thread-%s");
}
if (this.taskFuture != null) {
this.taskFuture.cancel(true);
}
this.taskFuture = this.scheduler.scheduleAtFixedRate(newTask(), ttls, ttls, TimeUnit.SECONDS);
}
private Runnable newTask() {
return () -> {
try {
long s = System.currentTimeMillis();
localEntrys.values().stream().filter(e -> !e.canceled).forEach(this::checkLocalHealth);
remoteEntrys.values().stream()
.filter(entry -> "SNCP".equalsIgnoreCase(entry.protocol))
.forEach(this::updateSncpAddress);
checkApplicationHealth();
checkHttpAddressHealth();
loadSncpAddressHealth();
long e = System.currentTimeMillis() - s;
if (e >= ttls * 9 / 10) {
logger.log(Level.WARNING, getClass().getSimpleName() + ".schedule check-slower cost " + e + " ms");
} else if (e >= ttls / 2) {
logger.log(Level.FINE, getClass().getSimpleName() + ".schedule check-slowly cost " + e + " ms");
} else {
logger.log(Level.FINEST, getClass().getSimpleName() + ".schedule check cost " + e + " ms");
}
} catch (Exception e) {
logger.log(Level.SEVERE, getClass().getSimpleName() + ".schedule check error", e);
}
};
}
private Runnable newTask() {
return () -> {
try {
long s = System.currentTimeMillis();
localEntrys.values().stream().filter(e -> !e.canceled).forEach(this::checkLocalHealth);
remoteEntrys.values().stream()
.filter(entry -> "SNCP".equalsIgnoreCase(entry.protocol))
.forEach(this::updateSncpAddress);
checkApplicationHealth();
checkHttpAddressHealth();
loadSncpAddressHealth();
long e = System.currentTimeMillis() - s;
if (e >= ttls * 9 / 10) {
logger.log(Level.WARNING, getClass().getSimpleName() + ".schedule check-slower cost " + e + " ms");
} else if (e >= ttls / 2) {
logger.log(Level.FINE, getClass().getSimpleName() + ".schedule check-slowly cost " + e + " ms");
} else {
logger.log(Level.FINEST, getClass().getSimpleName() + ".schedule check cost " + e + " ms");
}
} catch (Exception e) {
logger.log(Level.SEVERE, getClass().getSimpleName() + ".schedule check error", e);
}
};
}
protected void loadSncpAddressHealth() {
List<String> keys = source.keysStartsWith("cluster.sncp:");
keys.forEach(serviceName -> {
try {
this.sncpAddressMap.put(serviceName, queryAddress(serviceName).get(3, TimeUnit.SECONDS));
} catch (Exception e) {
logger.log(Level.SEVERE, "loadSncpAddressHealth check " + serviceName + " error", e);
}
});
}
protected void loadSncpAddressHealth() {
List<String> keys = source.keysStartsWith("cluster.sncp:");
keys.forEach(serviceName -> {
try {
this.sncpAddressMap.put(serviceName, queryAddress(serviceName).get(3, TimeUnit.SECONDS));
} catch (Exception e) {
logger.log(Level.SEVERE, "loadSncpAddressHealth 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 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.resname = entry.resourceName;
newaddr.nodeid = this.nodeid;
newaddr.time = System.currentTimeMillis();
source.hset(entry.checkName, entry.checkid, AddressEntry.class, newaddr);
}
protected void checkLocalHealth(final ClusterEntry entry) {
AddressEntry newaddr = new AddressEntry();
newaddr.addr = entry.address;
newaddr.resname = entry.resourceName;
newaddr.nodeid = this.nodeid;
newaddr.time = System.currentTimeMillis();
source.hset(entry.checkName, entry.checkid, AddressEntry.class, newaddr);
}
@Override // 获取SNCP远程服务的可用ip列表
public CompletableFuture<Set<InetSocketAddress>> querySncpAddress(String protocol, String module, String resname) {
final String serviceName = generateSncpServiceName(protocol, module, resname);
Set<InetSocketAddress> rs = sncpAddressMap.get(serviceName);
if (rs != null) {
return CompletableFuture.completedFuture(rs);
}
return queryAddress(serviceName).thenApply(t -> {
sncpAddressMap.put(serviceName, t);
return t;
});
}
@Override // 获取SNCP远程服务的可用ip列表
public CompletableFuture<Set<InetSocketAddress>> querySncpAddress(String protocol, String module, String resname) {
final String serviceName = generateSncpServiceName(protocol, module, resname);
Set<InetSocketAddress> rs = sncpAddressMap.get(serviceName);
if (rs != null) {
return CompletableFuture.completedFuture(rs);
}
return queryAddress(serviceName).thenApply(t -> {
sncpAddressMap.put(serviceName, t);
return t;
});
}
@Override // 获取HTTP远程服务的可用ip列表
public CompletableFuture<Set<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
final String serviceName = generateHttpServiceName(protocol, module, resname);
Set<InetSocketAddress> rs = httpAddressMap.get(serviceName);
if (rs != null) {
return CompletableFuture.completedFuture(rs);
}
return queryAddress(serviceName).thenApply(t -> {
httpAddressMap.put(serviceName, t);
return t;
});
}
@Override // 获取HTTP远程服务的可用ip列表
public CompletableFuture<Set<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
final String serviceName = generateHttpServiceName(protocol, module, resname);
Set<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<Set<InetSocketAddress>> queryAddress(final ClusterEntry entry) {
return queryAddress(entry.serviceName);
}
@Override
protected CompletableFuture<Set<InetSocketAddress>> queryAddress(final ClusterEntry entry) {
return queryAddress(entry.serviceName);
}
private CompletableFuture<Set<InetSocketAddress>> queryAddress(final String serviceName) {
return queryAddress0(serviceName, new HashSet<>(), new AtomicLong());
}
private CompletableFuture<Set<InetSocketAddress>> queryAddress(final String serviceName) {
return queryAddress0(serviceName, new HashSet<>(), new AtomicLong());
}
private CompletableFuture<Set<InetSocketAddress>> queryAddress0(
String serviceName, Set<InetSocketAddress> set, AtomicLong cursor) {
final CompletableFuture<Map<String, AddressEntry>> future =
source.hscanAsync(serviceName, AddressEntry.class, cursor, 10000);
return future.thenCompose(map -> {
map.forEach((n, v) -> {
if (v != null && (System.currentTimeMillis() - v.time) / 1000 <= ttls) {
set.add(v.addr);
}
});
if (cursor.get() == 0) {
return CompletableFuture.completedFuture(set);
} else {
return queryAddress0(serviceName, set, cursor);
}
});
}
private CompletableFuture<Set<InetSocketAddress>> queryAddress0(
String serviceName, Set<InetSocketAddress> set, AtomicLong cursor) {
final CompletableFuture<Map<String, AddressEntry>> future =
source.hscanAsync(serviceName, AddressEntry.class, cursor, 10000);
return future.thenCompose(map -> {
map.forEach((n, v) -> {
if (v != null && (System.currentTimeMillis() - v.time) / 1000 <= ttls) {
set.add(v.addr);
}
});
if (cursor.get() == 0) {
return CompletableFuture.completedFuture(set);
} else {
return queryAddress0(serviceName, set, cursor);
}
});
}
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 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);
}
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 RedkaleException("application.nodeid=" + nodeid + " exists in cluster");
}
deregister(application);
@Override
public void register(Application application) {
if (isApplicationHealth()) {
throw new RedkaleException("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);
}
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 serviceid = generateApplicationServiceId();
String serviceName = generateApplicationServiceName();
source.hdel(serviceName, serviceid);
}
@Override
public void deregister(Application application) {
String serviceid = generateApplicationServiceId();
String serviceName = generateApplicationServiceName();
source.hdel(serviceName, serviceid);
}
@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.resname = clusterEntry.resourceName;
entry.nodeid = this.nodeid;
entry.time = System.currentTimeMillis();
source.hset(clusterEntry.serviceName, clusterEntry.serviceid, AddressEntry.class, entry);
return clusterEntry;
}
@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.resname = clusterEntry.resourceName;
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);
}
@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 (Objects.equals(entry.serviceName, serviceName) && Objects.equals(entry.serviceid, serviceid)) {
currEntry = entry;
break;
}
}
if (currEntry == null) {
for (final ClusterEntry entry : remoteEntrys.values()) {
if (Objects.equals(entry.serviceName, serviceName) && Objects.equals(entry.serviceid, serviceid)) {
currEntry = entry;
break;
}
}
}
source.hdel(serviceName, serviceid);
if (realCanceled && currEntry != null) {
currEntry.canceled = 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 (Objects.equals(entry.serviceName, serviceName) && Objects.equals(entry.serviceid, serviceid)) {
currEntry = entry;
break;
}
}
if (currEntry == null) {
for (final ClusterEntry entry : remoteEntrys.values()) {
if (Objects.equals(entry.serviceName, serviceName) && Objects.equals(entry.serviceid, serviceid)) {
currEntry = entry;
break;
}
}
}
source.hdel(serviceName, serviceid);
if (realCanceled && currEntry != null) {
currEntry.canceled = true;
}
}
@Override
protected String generateApplicationServiceName() {
return "cluster:app:" + super.generateApplicationServiceName();
}
@Override
protected String generateApplicationServiceName() {
return "cluster:app:" + super.generateApplicationServiceName();
}
@Override
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
return "cluster:service:" + super.generateServiceName(ns, protocol, service);
}
@Override
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
return "cluster:service:" + super.generateServiceName(ns, protocol, service);
}
@Override
public String generateHttpServiceName(String protocol, String module, String resname) {
return "cluster:service:" + super.generateHttpServiceName(protocol, module, resname);
}
@Override
public String generateHttpServiceName(String protocol, String module, String resname) {
return "cluster:service:" + super.generateHttpServiceName(protocol, module, resname);
}
@Override
public String generateSncpServiceName(String protocol, String restype, String resname) {
return "cluster:service:" + super.generateSncpServiceName(protocol, restype, resname);
}
@Override
public String generateSncpServiceName(String protocol, String restype, String resname) {
return "cluster:service:" + super.generateSncpServiceName(protocol, restype, resname);
}
@Override
protected String generateApplicationCheckName() {
return generateApplicationServiceName();
}
@Override
protected String generateApplicationCheckName() {
return generateApplicationServiceName();
}
@Override
protected String generateApplicationCheckId() {
return generateApplicationServiceId();
}
@Override
protected String generateApplicationCheckId() {
return generateApplicationServiceId();
}
@Override
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
return generateServiceName(ns, protocol, service);
}
@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);
}
@Override
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
return generateServiceId(ns, protocol, service);
}
public static class AddressEntry {
public static class AddressEntry {
public InetSocketAddress addr;
public InetSocketAddress addr;
public String nodeid;
public String nodeid;
public long time;
public long time;
public String resname;
public String resname;
public AddressEntry refresh() {
this.time = System.currentTimeMillis();
return this;
}
public AddressEntry refresh() {
this.time = System.currentTimeMillis();
return this;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
}

View File

@@ -35,393 +35,393 @@ import org.redkale.util.*;
*/
public abstract class ClusterAgent {
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
@Resource(name = RESNAME_APP_NODEID)
protected String nodeid;
@Resource(name = RESNAME_APP_NAME)
protected String appName = "";
@Resource(name = RESNAME_APP_ADDR)
protected InetSocketAddress appAddress;
@Resource(required = false)
protected Application application;
protected String name;
protected boolean waits;
@Nullable
protected String[] protocols; // 必须全大写
protected int[] ports;
protected AnyValue config;
protected Set<String> tags;
// key: serviceid
protected final ConcurrentHashMap<String, ClusterEntry> localEntrys = new ConcurrentHashMap<>();
// key: serviceid
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();
this.protocols = Utility.isEmpty(ps) ? null : 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();
}
}
Set<String> tags0 = new HashSet<>();
for (String str : config.getValue("tags", "").split(";|,")) {
if (!str.trim().isEmpty()) {
tags0.add(str.trim());
}
}
if (!tags0.isEmpty()) {
this.tags = tags0;
}
}
@ResourceChanged
public abstract void onResourceChange(ResourceEvent[] events);
public void destroy(AnyValue config) {}
/**
* ServiceLoader时判断配置是否符合当前实现类
*
* @param config 节点配置
* @return boolean
*/
public abstract boolean acceptsConf(AnyValue config);
public boolean containsProtocol(String protocol) {
if (Utility.isEmpty(protocol)) {
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 void start() {}
public int intervalCheckSeconds() {
return 10;
}
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,
Set<Service> servletServices) {
if (servletServices.isEmpty()) {
return;
}
// 注册本地模式
for (Service service : servletServices) {
if (!canRegister(ns, protocol, service)) {
continue;
}
ClusterEntry htentry = register(ns, protocol, service);
localEntrys.put(htentry.serviceid, htentry);
}
// 远程模式加载IP列表, 只支持SNCP协议
if (ns.isSNCP()) {
for (Service service : remoteServices) {
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
updateSncpAddress(entry);
remoteEntrys.put(entry.serviceid, entry);
}
}
}
// 注销服务, 在NodeService调用Service.destroy 方法之前调用
public void deregister(
NodeServer ns,
String protocol,
Set<Service> localServices,
Set<Service> remoteServices,
Set<Service> servletServices) {
// 注销本地模式 远程模式不注册
for (Service service : servletServices) {
if (!canRegister(ns, protocol, service)) {
continue;
}
deregister(ns, protocol, service);
}
afterDeregister(ns, protocol);
}
protected boolean canRegister(NodeServer ns, String protocol, Service service) {
if (service.getClass().getAnnotation(Component.class) != null) {
return false;
}
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;
}
org.redkale.util.AutoLoad al2 = service.getClass().getAnnotation(org.redkale.util.AutoLoad.class);
if (al2 != null && !al2.value() && service.getClass().getAnnotation(Local.class) != null) {
return false;
}
if (service instanceof WebSocketNode) {
if (((WebSocketNode) service).getLocalWebSocketEngine() == null) {
return false;
}
}
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
if (entry.serviceName.trim().endsWith(".")) {
return false;
}
return true;
}
protected void afterDeregister(NodeServer ns, String protocol) {
if (!this.waits) {
return;
}
int s = intervalCheckSeconds();
if (s > 0) { // 暂停,弥补其他依赖本进程服务的周期偏差
Utility.sleep(s * 1000);
logger.info(this.getClass().getSimpleName() + " wait for " + s * 1000 + "ms after deregister");
}
}
// 获取HTTP远程服务的可用ip列表
public abstract CompletableFuture<Set<InetSocketAddress>> queryHttpAddress(
String protocol, String module, String resname);
// 获取SNCP远程服务的可用ip列表 restype: resourceType.getName()
public abstract CompletableFuture<Set<InetSocketAddress>> querySncpAddress(
String protocol, String restype, String resname);
// 获取远程服务的可用ip列表
protected abstract CompletableFuture<Set<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 updateSncpAddress(ClusterEntry entry) {
if (application == null) {
return;
}
Service service = entry.serviceRef.get();
if (service == null) {
return;
}
try {
Set<InetSocketAddress> addrs = ClusterAgent.this.queryAddress(entry).join();
SncpRpcGroups rpcGroups = application.getSncpRpcGroups();
rpcGroups.putClusterAddress(entry.resourceid, addrs);
} catch (Exception e) {
logger.log(Level.SEVERE, entry + " updateSncpAddress error", e);
}
}
protected String urlEncode(String value) {
return value == null ? null : URLEncoder.encode(value, StandardCharsets.UTF_8);
}
protected String generateApplicationServiceName() {
return Utility.isEmpty(appName) ? "node" : appName;
}
protected String generateApplicationServiceType() {
return "nodes";
}
protected String generateApplicationServiceId() {
return generateApplicationServiceName() + "@" + this.nodeid;
}
protected String generateApplicationCheckName() {
return "check-" + generateApplicationServiceName();
}
protected String generateApplicationCheckId() {
return "check-" + generateApplicationServiceId();
}
protected String generateApplicationHost() {
return this.appAddress.getHostString();
}
protected int generateApplicationPort() {
return this.appAddress.getPort();
}
public String generateSncpServiceName(String protocol, String restype, String resname) {
return protocol.toLowerCase() + ":" + restype + (Utility.isEmpty(resname) ? "" : ("-" + resname));
}
// 也会提供给HttpMessageClusterAgent适用
public String generateHttpServiceName(String protocol, String module, String resname) {
return protocol.toLowerCase() + ":" + module + (Utility.isEmpty(resname) ? "" : ("-" + 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 (!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;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Nullable
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 {
// serviceName+nodeid为主 服务的单个实例
public String serviceid;
// 以协议+Rest资源名为主 服务类名
public String serviceName;
public final String resourceType;
public final String resourceName;
public final String resourceid;
public String checkid;
public String checkName;
// http or sncp
public String protocol;
// TCP or UDP
public String netProtocol;
@ConvertDisabled
public WeakReference<Service> serviceRef;
public InetSocketAddress address;
public boolean canceled;
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);
Class restype = Sncp.getResourceType(service);
this.resourceType = restype.getName();
this.resourceName = Sncp.getResourceName(service);
this.resourceid = Sncp.resourceid(resourceName, restype);
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() : "TCP";
}
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
@Resource(name = RESNAME_APP_NODEID)
protected String nodeid;
@Resource(name = RESNAME_APP_NAME)
protected String appName = "";
@Resource(name = RESNAME_APP_ADDR)
protected InetSocketAddress appAddress;
@Resource(required = false)
protected Application application;
protected String name;
protected boolean waits;
@Nullable
protected String[] protocols; // 必须全大写
protected int[] ports;
protected AnyValue config;
protected Set<String> tags;
// key: serviceid
protected final ConcurrentHashMap<String, ClusterEntry> localEntrys = new ConcurrentHashMap<>();
// key: serviceid
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();
this.protocols = Utility.isEmpty(ps) ? null : 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();
}
}
Set<String> tags0 = new HashSet<>();
for (String str : config.getValue("tags", "").split(";|,")) {
if (!str.trim().isEmpty()) {
tags0.add(str.trim());
}
}
if (!tags0.isEmpty()) {
this.tags = tags0;
}
}
@ResourceChanged
public abstract void onResourceChange(ResourceEvent[] events);
public void destroy(AnyValue config) {}
/**
* ServiceLoader时判断配置是否符合当前实现类
*
* @param config 节点配置
* @return boolean
*/
public abstract boolean acceptsConf(AnyValue config);
public boolean containsProtocol(String protocol) {
if (Utility.isEmpty(protocol)) {
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 void start() {}
public int intervalCheckSeconds() {
return 10;
}
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,
Set<Service> servletServices) {
if (servletServices.isEmpty()) {
return;
}
// 注册本地模式
for (Service service : servletServices) {
if (!canRegister(ns, protocol, service)) {
continue;
}
ClusterEntry htentry = register(ns, protocol, service);
localEntrys.put(htentry.serviceid, htentry);
}
// 远程模式加载IP列表, 只支持SNCP协议
if (ns.isSNCP()) {
for (Service service : remoteServices) {
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
updateSncpAddress(entry);
remoteEntrys.put(entry.serviceid, entry);
}
}
}
// 注销服务, 在NodeService调用Service.destroy 方法之前调用
public void deregister(
NodeServer ns,
String protocol,
Set<Service> localServices,
Set<Service> remoteServices,
Set<Service> servletServices) {
// 注销本地模式 远程模式不注册
for (Service service : servletServices) {
if (!canRegister(ns, protocol, service)) {
continue;
}
deregister(ns, protocol, service);
}
afterDeregister(ns, protocol);
}
protected boolean canRegister(NodeServer ns, String protocol, Service service) {
if (service.getClass().getAnnotation(Component.class) != null) {
return false;
}
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;
}
org.redkale.util.AutoLoad al2 = service.getClass().getAnnotation(org.redkale.util.AutoLoad.class);
if (al2 != null && !al2.value() && service.getClass().getAnnotation(Local.class) != null) {
return false;
}
if (service instanceof WebSocketNode) {
if (((WebSocketNode) service).getLocalWebSocketEngine() == null) {
return false;
}
}
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
if (entry.serviceName.trim().endsWith(".")) {
return false;
}
return true;
}
protected void afterDeregister(NodeServer ns, String protocol) {
if (!this.waits) {
return;
}
int s = intervalCheckSeconds();
if (s > 0) { // 暂停,弥补其他依赖本进程服务的周期偏差
Utility.sleep(s * 1000);
logger.info(this.getClass().getSimpleName() + " wait for " + s * 1000 + "ms after deregister");
}
}
// 获取HTTP远程服务的可用ip列表
public abstract CompletableFuture<Set<InetSocketAddress>> queryHttpAddress(
String protocol, String module, String resname);
// 获取SNCP远程服务的可用ip列表 restype: resourceType.getName()
public abstract CompletableFuture<Set<InetSocketAddress>> querySncpAddress(
String protocol, String restype, String resname);
// 获取远程服务的可用ip列表
protected abstract CompletableFuture<Set<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 updateSncpAddress(ClusterEntry entry) {
if (application == null) {
return;
}
Service service = entry.serviceRef.get();
if (service == null) {
return;
}
try {
Set<InetSocketAddress> addrs = ClusterAgent.this.queryAddress(entry).join();
SncpRpcGroups rpcGroups = application.getSncpRpcGroups();
rpcGroups.putClusterAddress(entry.resourceid, addrs);
} catch (Exception e) {
logger.log(Level.SEVERE, entry + " updateSncpAddress error", e);
}
}
protected String urlEncode(String value) {
return value == null ? null : URLEncoder.encode(value, StandardCharsets.UTF_8);
}
protected String generateApplicationServiceName() {
return Utility.isEmpty(appName) ? "node" : appName;
}
protected String generateApplicationServiceType() {
return "nodes";
}
protected String generateApplicationServiceId() {
return generateApplicationServiceName() + "@" + this.nodeid;
}
protected String generateApplicationCheckName() {
return "check-" + generateApplicationServiceName();
}
protected String generateApplicationCheckId() {
return "check-" + generateApplicationServiceId();
}
protected String generateApplicationHost() {
return this.appAddress.getHostString();
}
protected int generateApplicationPort() {
return this.appAddress.getPort();
}
public String generateSncpServiceName(String protocol, String restype, String resname) {
return protocol.toLowerCase() + ":" + restype + (Utility.isEmpty(resname) ? "" : ("-" + resname));
}
// 也会提供给HttpMessageClusterAgent适用
public String generateHttpServiceName(String protocol, String module, String resname) {
return protocol.toLowerCase() + ":" + module + (Utility.isEmpty(resname) ? "" : ("-" + 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 (!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;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Nullable
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 {
// serviceName+nodeid为主 服务的单个实例
public String serviceid;
// 以协议+Rest资源名为主 服务类名
public String serviceName;
public final String resourceType;
public final String resourceName;
public final String resourceid;
public String checkid;
public String checkName;
// http or sncp
public String protocol;
// TCP or UDP
public String netProtocol;
@ConvertDisabled
public WeakReference<Service> serviceRef;
public InetSocketAddress address;
public boolean canceled;
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);
Class restype = Sncp.getResourceType(service);
this.resourceType = restype.getName();
this.resourceName = Sncp.getResourceName(service);
this.resourceid = Sncp.resourceid(resourceName, restype);
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() : "TCP";
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
}

View File

@@ -23,231 +23,231 @@ import org.redkale.util.RedkaleClassLoader;
/** @author zhangjx */
public class ClusterModuleEngine extends ModuleEngine {
// 第三方服务配置资源
// @since 2.8.0
private Properties clusterProperties = new Properties();
// 第三方服务配置资源
// @since 2.8.0
private Properties clusterProperties = new Properties();
// 第三方服务发现管理接口
// @since 2.1.0
private ClusterAgent clusterAgent;
// 第三方服务发现管理接口
// @since 2.1.0
private ClusterAgent clusterAgent;
public ClusterModuleEngine(Application application) {
super(application);
}
public ClusterModuleEngine(Application application) {
super(application);
}
/** 结束Application.init方法前被调用 */
@Override
public void onAppPostInit() {
ClusterAgent cluster = null;
AnyValue clusterConf = application.getAppConfig().getAnyValue("cluster");
if (clusterConf != null) {
try {
String classVal = environment.getPropertyValue(
clusterConf.getValue("type", clusterConf.getValue("value"))); // 兼容value字段
if (classVal == null
|| classVal.isEmpty()
|| classVal.indexOf('.') < 0) { // 不包含.表示非类名,比如值: consul, nacos
Iterator<ClusterAgentProvider> it = ServiceLoader.load(
ClusterAgentProvider.class, application.getClassLoader())
.iterator();
RedkaleClassLoader.putServiceLoader(ClusterAgentProvider.class);
while (it.hasNext()) {
ClusterAgentProvider provider = it.next();
if (provider != null) {
RedkaleClassLoader.putReflectionPublicConstructors(
provider.getClass(), provider.getClass().getName()); // loader class
}
if (provider != null && provider.acceptsConf(clusterConf)) {
cluster = provider.createInstance();
cluster.setConfig(clusterConf);
break;
}
}
if (cluster == null) {
ClusterAgent cacheClusterAgent = new CacheClusterAgent();
if (cacheClusterAgent.acceptsConf(clusterConf)) {
cluster = cacheClusterAgent;
cluster.setConfig(clusterConf);
}
}
if (cluster == null) {
logger.log(
Level.SEVERE,
"load application cluster resource, but not found name='type' value error: "
+ clusterConf);
}
} else {
Class type = application.getClassLoader().loadClass(classVal);
if (!ClusterAgent.class.isAssignableFrom(type)) {
logger.log(
Level.SEVERE,
"load application cluster resource, but not found " + ClusterAgent.class.getSimpleName()
+ " implements class error: " + clusterConf);
} else {
RedkaleClassLoader.putReflectionDeclaredConstructors(type, type.getName());
cluster = (ClusterAgent) type.getDeclaredConstructor().newInstance();
cluster.setConfig(clusterConf);
}
}
// 此时不能执行cluster.init因内置的对象可能依赖config.properties配置项
} catch (Exception e) {
logger.log(Level.SEVERE, "load application cluster resource error: " + clusterConf, e);
}
}
this.clusterAgent = cluster;
/** 结束Application.init方法前被调用 */
@Override
public void onAppPostInit() {
ClusterAgent cluster = null;
AnyValue clusterConf = application.getAppConfig().getAnyValue("cluster");
if (clusterConf != null) {
try {
String classVal = environment.getPropertyValue(
clusterConf.getValue("type", clusterConf.getValue("value"))); // 兼容value字段
if (classVal == null
|| classVal.isEmpty()
|| classVal.indexOf('.') < 0) { // 不包含.表示非类名,比如值: consul, nacos
Iterator<ClusterAgentProvider> it = ServiceLoader.load(
ClusterAgentProvider.class, application.getClassLoader())
.iterator();
RedkaleClassLoader.putServiceLoader(ClusterAgentProvider.class);
while (it.hasNext()) {
ClusterAgentProvider provider = it.next();
if (provider != null) {
RedkaleClassLoader.putReflectionPublicConstructors(
provider.getClass(), provider.getClass().getName()); // loader class
}
if (provider != null && provider.acceptsConf(clusterConf)) {
cluster = provider.createInstance();
cluster.setConfig(clusterConf);
break;
}
}
if (cluster == null) {
ClusterAgent cacheClusterAgent = new CacheClusterAgent();
if (cacheClusterAgent.acceptsConf(clusterConf)) {
cluster = cacheClusterAgent;
cluster.setConfig(clusterConf);
}
}
if (cluster == null) {
logger.log(
Level.SEVERE,
"load application cluster resource, but not found name='type' value error: "
+ clusterConf);
}
} else {
Class type = application.getClassLoader().loadClass(classVal);
if (!ClusterAgent.class.isAssignableFrom(type)) {
logger.log(
Level.SEVERE,
"load application cluster resource, but not found " + ClusterAgent.class.getSimpleName()
+ " implements class error: " + clusterConf);
} else {
RedkaleClassLoader.putReflectionDeclaredConstructors(type, type.getName());
cluster = (ClusterAgent) type.getDeclaredConstructor().newInstance();
cluster.setConfig(clusterConf);
}
}
// 此时不能执行cluster.init因内置的对象可能依赖config.properties配置项
} catch (Exception e) {
logger.log(Level.SEVERE, "load application cluster resource error: " + clusterConf, e);
}
}
this.clusterAgent = cluster;
if (this.clusterAgent != null) {
if (logger.isLoggable(Level.FINER)) {
logger.log(
Level.FINER,
"ClusterAgent (type = " + this.clusterAgent.getClass().getSimpleName() + ") initing");
}
long s = System.currentTimeMillis();
if (this.clusterAgent instanceof CacheClusterAgent) {
String sourceName =
((CacheClusterAgent) clusterAgent).getSourceName(); // 必须在inject前调用需要赋值Resourcable.name
SourceManager sourceManager = application.getResourceFactory().find(SourceManager.class);
sourceManager.loadCacheSource(sourceName, false);
}
this.resourceFactory.inject(clusterAgent);
clusterAgent.init(clusterAgent.getConfig());
this.resourceFactory.register(ClusterAgent.class, clusterAgent);
logger.info("ClusterAgent (type = " + this.clusterAgent.getClass().getSimpleName() + ") init in "
+ (System.currentTimeMillis() - s) + " ms");
}
}
if (this.clusterAgent != null) {
if (logger.isLoggable(Level.FINER)) {
logger.log(
Level.FINER,
"ClusterAgent (type = " + this.clusterAgent.getClass().getSimpleName() + ") initing");
}
long s = System.currentTimeMillis();
if (this.clusterAgent instanceof CacheClusterAgent) {
String sourceName =
((CacheClusterAgent) clusterAgent).getSourceName(); // 必须在inject前调用需要赋值Resourcable.name
SourceManager sourceManager = application.getResourceFactory().find(SourceManager.class);
sourceManager.loadCacheSource(sourceName, false);
}
this.resourceFactory.inject(clusterAgent);
clusterAgent.init(clusterAgent.getConfig());
this.resourceFactory.register(ClusterAgent.class, clusterAgent);
logger.info("ClusterAgent (type = " + this.clusterAgent.getClass().getSimpleName() + ") init in "
+ (System.currentTimeMillis() - s) + " ms");
}
}
/** 配置项加载后被调用 */
@Override
public void onEnvironmentLoaded(Properties allProps) {
allProps.forEach((key, val) -> {
if (key.toString().startsWith("redkale.cluster.")) {
this.clusterProperties.put(key, val);
}
});
}
/** 配置项加载后被调用 */
@Override
public void onEnvironmentLoaded(Properties allProps) {
allProps.forEach((key, val) -> {
if (key.toString().startsWith("redkale.cluster.")) {
this.clusterProperties.put(key, val);
}
});
}
/**
* 配置项变更时被调用
*
* @param namespace 命名空间
* @param events 变更项
*/
@Override
public void onEnvironmentChanged(String namespace, List<ResourceEvent> events) {
Set<String> clusterRemovedKeys = new HashSet<>();
Properties clusterChangedProps = new Properties();
/**
* 配置项变更时被调用
*
* @param namespace 命名空间
* @param events 变更项
*/
@Override
public void onEnvironmentChanged(String namespace, List<ResourceEvent> events) {
Set<String> clusterRemovedKeys = new HashSet<>();
Properties clusterChangedProps = new Properties();
for (ResourceEvent<String> event : events) {
if (event.name().startsWith("redkale.cluster.")) {
if (!Objects.equals(event.newValue(), this.clusterProperties.getProperty(event.name()))) {
if (event.newValue() == null) {
if (this.clusterProperties.containsKey(event.name())) {
clusterRemovedKeys.add(event.name());
}
} else {
clusterChangedProps.put(event.name(), event.newValue());
}
}
}
}
// 第三方服务注册配置项的变更
if (!clusterChangedProps.isEmpty() || !clusterRemovedKeys.isEmpty()) {
if (this.clusterAgent != null) {
final AnyValueWriter old =
(AnyValueWriter) application.getAppConfig().getAnyValue("cluster");
Properties newProps = new Properties();
newProps.putAll(clusterProperties);
List<ResourceEvent> changeEvents = new ArrayList<>();
clusterChangedProps.forEach((k, v) -> {
final String key = k.toString();
newProps.put(k, v);
changeEvents.add(ResourceEvent.create(
key.substring("redkale.cluster.".length()), v, this.clusterProperties.getProperty(key)));
});
clusterRemovedKeys.forEach(k -> {
final String key = k;
newProps.remove(k);
changeEvents.add(ResourceEvent.create(
key.substring("redkale.cluster.".length()), null, this.clusterProperties.getProperty(key)));
});
if (!changeEvents.isEmpty()) {
AnyValueWriter back = old.copy();
try {
old.replace(AnyValue.loadFromProperties(newProps)
.getAnyValue("redkale")
.getAnyValue("cluster"));
clusterAgent.onResourceChange(changeEvents.toArray(new ResourceEvent[changeEvents.size()]));
} catch (RuntimeException e) {
old.replace(back); // 还原配置
throw e;
}
}
} else {
StringBuilder sb = new StringBuilder();
clusterChangedProps.forEach((k, v) -> {
sb.append(ClusterAgent.class.getSimpleName())
.append(" skip change '")
.append(k)
.append("'\r\n");
});
clusterRemovedKeys.forEach(k -> {
sb.append(ClusterAgent.class.getSimpleName())
.append(" skip change '")
.append(k)
.append("'\r\n");
});
if (sb.length() > 0) {
logger.log(Level.INFO, sb.toString());
}
}
clusterRemovedKeys.forEach(k -> this.clusterProperties.remove(k));
this.clusterProperties.putAll(clusterChangedProps);
}
}
for (ResourceEvent<String> event : events) {
if (event.name().startsWith("redkale.cluster.")) {
if (!Objects.equals(event.newValue(), this.clusterProperties.getProperty(event.name()))) {
if (event.newValue() == null) {
if (this.clusterProperties.containsKey(event.name())) {
clusterRemovedKeys.add(event.name());
}
} else {
clusterChangedProps.put(event.name(), event.newValue());
}
}
}
}
// 第三方服务注册配置项的变更
if (!clusterChangedProps.isEmpty() || !clusterRemovedKeys.isEmpty()) {
if (this.clusterAgent != null) {
final AnyValueWriter old =
(AnyValueWriter) application.getAppConfig().getAnyValue("cluster");
Properties newProps = new Properties();
newProps.putAll(clusterProperties);
List<ResourceEvent> changeEvents = new ArrayList<>();
clusterChangedProps.forEach((k, v) -> {
final String key = k.toString();
newProps.put(k, v);
changeEvents.add(ResourceEvent.create(
key.substring("redkale.cluster.".length()), v, this.clusterProperties.getProperty(key)));
});
clusterRemovedKeys.forEach(k -> {
final String key = k;
newProps.remove(k);
changeEvents.add(ResourceEvent.create(
key.substring("redkale.cluster.".length()), null, this.clusterProperties.getProperty(key)));
});
if (!changeEvents.isEmpty()) {
AnyValueWriter back = old.copy();
try {
old.replace(AnyValue.loadFromProperties(newProps)
.getAnyValue("redkale")
.getAnyValue("cluster"));
clusterAgent.onResourceChange(changeEvents.toArray(new ResourceEvent[changeEvents.size()]));
} catch (RuntimeException e) {
old.replace(back); // 还原配置
throw e;
}
}
} else {
StringBuilder sb = new StringBuilder();
clusterChangedProps.forEach((k, v) -> {
sb.append(ClusterAgent.class.getSimpleName())
.append(" skip change '")
.append(k)
.append("'\r\n");
});
clusterRemovedKeys.forEach(k -> {
sb.append(ClusterAgent.class.getSimpleName())
.append(" skip change '")
.append(k)
.append("'\r\n");
});
if (sb.length() > 0) {
logger.log(Level.INFO, sb.toString());
}
}
clusterRemovedKeys.forEach(k -> this.clusterProperties.remove(k));
this.clusterProperties.putAll(clusterChangedProps);
}
}
/**
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
*
* @param path 配置项路径
* @param key 配置项名称
* @param val1 配置项原值
* @param val2 配置项新值
* @return MergeEnum
*/
@Override
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
if ("".equals(path) && "cluster".equals(key)) {
return AnyValue.MergeEnum.REPLACE;
}
return null;
}
/**
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
*
* @param path 配置项路径
* @param key 配置项名称
* @param val1 配置项原值
* @param val2 配置项新值
* @return MergeEnum
*/
@Override
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
if ("".equals(path) && "cluster".equals(key)) {
return AnyValue.MergeEnum.REPLACE;
}
return null;
}
/** 进入Application.start方法被调用 */
@Override
public void onAppPreStart() {
if (!application.isSingletonMode() && !application.isCompileMode() && this.clusterAgent != null) {
this.clusterAgent.register(application);
}
}
/** 进入Application.start方法被调用 */
@Override
public void onAppPreStart() {
if (!application.isSingletonMode() && !application.isCompileMode() && this.clusterAgent != null) {
this.clusterAgent.register(application);
}
}
/** 服务全部启动后被调用 */
public void onServersPostStart() {
if (this.clusterAgent != null) {
this.clusterAgent.start();
}
}
/** 服务全部启动后被调用 */
public void onServersPostStart() {
if (this.clusterAgent != null) {
this.clusterAgent.start();
}
}
/** 服务全部停掉后被调用 */
public void onServersPostStop() {
if (!application.isCompileMode() && clusterAgent != null) {
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "ClusterAgent destroying");
}
long s = System.currentTimeMillis();
clusterAgent.deregister(application);
clusterAgent.destroy(clusterAgent.getConfig());
logger.info("ClusterAgent destroy in " + (System.currentTimeMillis() - s) + " ms");
}
}
/** 服务全部停掉后被调用 */
public void onServersPostStop() {
if (!application.isCompileMode() && clusterAgent != null) {
if (logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "ClusterAgent destroying");
}
long s = System.currentTimeMillis();
clusterAgent.deregister(application);
clusterAgent.destroy(clusterAgent.getConfig());
logger.info("ClusterAgent destroy in " + (System.currentTimeMillis() - s) + " ms");
}
}
}

View File

@@ -28,201 +28,201 @@ import org.redkale.util.Utility;
*/
public class HttpClusterRpcClient extends HttpRpcClient {
// jdk.internal.net.http.common.Utils.DISALLOWED_HEADERS_SET
private static final Set<String> DISALLOWED_HEADERS_SET = Utility.ofSet(
"connection",
"content-length",
"date",
"expect",
"from",
"host",
"origin",
"referer",
"upgrade",
"via",
"warning");
// jdk.internal.net.http.common.Utils.DISALLOWED_HEADERS_SET
private static final Set<String> DISALLOWED_HEADERS_SET = Utility.ofSet(
"connection",
"content-length",
"date",
"expect",
"from",
"host",
"origin",
"referer",
"upgrade",
"via",
"warning");
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
protected final HttpLocalRpcClient localClient;
protected final HttpLocalRpcClient localClient;
protected final ConcurrentHashMap<String, Boolean> topicServletMap = new ConcurrentHashMap<>();
protected final ConcurrentHashMap<String, Boolean> topicServletMap = new ConcurrentHashMap<>();
protected ClusterAgent clusterAgent;
protected ClusterAgent clusterAgent;
@Resource(name = "cluster.httpClient", required = false)
protected WebClient webClient;
@Resource(name = "cluster.httpClient", required = false)
protected WebClient webClient;
@Resource(name = "cluster.httpClient", required = false)
protected java.net.http.HttpClient httpClient;
@Resource(name = "cluster.httpClient", required = false)
protected java.net.http.HttpClient httpClient;
public HttpClusterRpcClient(Application application, String resourceName, ClusterAgent clusterAgent) {
Objects.requireNonNull(clusterAgent);
this.localClient = new HttpLocalRpcClient(application, resourceName);
this.clusterAgent = clusterAgent;
}
public HttpClusterRpcClient(Application application, String resourceName, ClusterAgent clusterAgent) {
Objects.requireNonNull(clusterAgent);
this.localClient = new HttpLocalRpcClient(application, resourceName);
this.clusterAgent = clusterAgent;
}
@Override
protected String getNodeid() {
return localClient.getNodeid();
}
@Override
protected String getNodeid() {
return localClient.getNodeid();
}
@Override
public CompletableFuture<HttpResult<byte[]>> sendMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
if (topicServletMap.computeIfAbsent(topic, t -> localClient.findHttpServlet(t) != null)) {
return localClient.sendMessage(topic, userid, groupid, request);
} else {
return httpAsync(false, userid, request);
}
}
@Override
public CompletableFuture<HttpResult<byte[]>> sendMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
if (topicServletMap.computeIfAbsent(topic, t -> localClient.findHttpServlet(t) != null)) {
return localClient.sendMessage(topic, userid, groupid, request);
} else {
return httpAsync(false, userid, request);
}
}
@Override
public CompletableFuture<Void> produceMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
if (topicServletMap.computeIfAbsent(topic, t -> localClient.findHttpServlet(t) != null)) {
return localClient.produceMessage(topic, userid, groupid, request);
} else {
return httpAsync(true, userid, request).thenApply(v -> null);
}
}
@Override
public CompletableFuture<Void> produceMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
if (topicServletMap.computeIfAbsent(topic, t -> localClient.findHttpServlet(t) != null)) {
return localClient.produceMessage(topic, userid, groupid, request);
} else {
return httpAsync(true, userid, request).thenApply(v -> null);
}
}
private CompletableFuture<HttpResult<byte[]>> httpAsync(boolean produce, Serializable userid, WebRequest req) {
req.setTraceid(Traces.computeIfAbsent(req.getTraceid(), Traces.currentTraceid()));
String module = req.getPath();
module = module.substring(1, module.indexOf('/', 1));
HttpHeaders headers = req.getHeaders();
String resname = req.getHeader(Rest.REST_HEADER_RESNAME, "");
final String localModule = module;
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "httpAsync.queryHttpAddress: module=" + localModule + ", resname=" + resname);
}
return clusterAgent.queryHttpAddress("http", module, resname).thenCompose(addrs -> {
Traces.currentTraceid(req.getTraceid());
if (isEmpty(addrs)) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(
Level.WARNING,
"httpAsync." + (produce ? "produceMessage" : "sendMessage") + " failed, module="
+ localModule + ", resname=" + resname + ", address is empty");
}
return new HttpResult<byte[]>().status(404).toFuture();
}
final HttpHeaders clientHeaders = HttpHeaders.create();
if (headers != null) {
boolean ws = headers.contains("Sec-WebSocket-Key");
headers.forEach((n, v) -> {
if (!DISALLOWED_HEADERS_SET.contains(n.toLowerCase())
&& (!ws
|| (!"Connection".equals(n)
&& !"Sec-WebSocket-Key".equals(n)
&& !"Sec-WebSocket-Version".equals(n)))) {
clientHeaders.add(n, v);
}
});
}
clientHeaders.set("Content-Type", "x-www-form-urlencoded");
if (req.isRpc()) {
clientHeaders.set(Rest.REST_HEADER_RPC, "true");
}
if (isNotEmpty(req.getTraceid())) {
clientHeaders.set(Rest.REST_HEADER_TRACEID, req.getTraceid());
}
if (userid != null) {
clientHeaders.set(Rest.REST_HEADER_CURRUSERID, String.valueOf(userid));
}
if (req.getReqConvertType() != null) {
clientHeaders.set(
Rest.REST_HEADER_REQ_CONVERT, req.getReqConvertType().toString());
}
if (req.getRespConvertType() != null) {
clientHeaders.set(
Rest.REST_HEADER_RESP_CONVERT, req.getRespConvertType().toString());
}
private CompletableFuture<HttpResult<byte[]>> httpAsync(boolean produce, Serializable userid, WebRequest req) {
req.setTraceid(Traces.computeIfAbsent(req.getTraceid(), Traces.currentTraceid()));
String module = req.getPath();
module = module.substring(1, module.indexOf('/', 1));
HttpHeaders headers = req.getHeaders();
String resname = req.getHeader(Rest.REST_HEADER_RESNAME, "");
final String localModule = module;
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "httpAsync.queryHttpAddress: module=" + localModule + ", resname=" + resname);
}
return clusterAgent.queryHttpAddress("http", module, resname).thenCompose(addrs -> {
Traces.currentTraceid(req.getTraceid());
if (isEmpty(addrs)) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(
Level.WARNING,
"httpAsync." + (produce ? "produceMessage" : "sendMessage") + " failed, module="
+ localModule + ", resname=" + resname + ", address is empty");
}
return new HttpResult<byte[]>().status(404).toFuture();
}
final HttpHeaders clientHeaders = HttpHeaders.create();
if (headers != null) {
boolean ws = headers.contains("Sec-WebSocket-Key");
headers.forEach((n, v) -> {
if (!DISALLOWED_HEADERS_SET.contains(n.toLowerCase())
&& (!ws
|| (!"Connection".equals(n)
&& !"Sec-WebSocket-Key".equals(n)
&& !"Sec-WebSocket-Version".equals(n)))) {
clientHeaders.add(n, v);
}
});
}
clientHeaders.set("Content-Type", "x-www-form-urlencoded");
if (req.isRpc()) {
clientHeaders.set(Rest.REST_HEADER_RPC, "true");
}
if (isNotEmpty(req.getTraceid())) {
clientHeaders.set(Rest.REST_HEADER_TRACEID, req.getTraceid());
}
if (userid != null) {
clientHeaders.set(Rest.REST_HEADER_CURRUSERID, String.valueOf(userid));
}
if (req.getReqConvertType() != null) {
clientHeaders.set(
Rest.REST_HEADER_REQ_CONVERT, req.getReqConvertType().toString());
}
if (req.getRespConvertType() != null) {
clientHeaders.set(
Rest.REST_HEADER_RESP_CONVERT, req.getRespConvertType().toString());
}
if (webClient != null) {
WebRequest newReq = req.copy().headers(clientHeaders);
InetSocketAddress addr = randomAddress(newReq, addrs);
if (logger.isLoggable(Level.FINEST)) {
logger.log(
Level.FINEST,
"httpAsync: module=" + localModule + ", resname=" + resname + ", addr=" + addr);
}
return (CompletableFuture) webClient.sendAsync(addr, newReq);
}
byte[] clientBody = null;
if (isNotEmpty(req.getBody())) {
String paramstr = req.getParametersToString();
if (paramstr != null) {
if (req.getPath().indexOf('?') > 0) {
req.setPath(req.getPath() + "&" + paramstr);
} else {
req.setPath(req.getPath() + "?" + paramstr);
}
}
clientBody = req.getBody();
} else {
String paramstr = req.getParametersToString();
if (paramstr != null) {
clientBody = paramstr.getBytes(StandardCharsets.UTF_8);
}
}
if (logger.isLoggable(Level.FINEST)) {
logger.log(
Level.FINEST,
"httpAsync: module=" + localModule + ", resname=" + resname + ", enter sendEachAddressAsync");
}
return sendEachAddressAsync(req, req.requestPath(), clientHeaders, clientBody, addrs.iterator());
});
}
if (webClient != null) {
WebRequest newReq = req.copy().headers(clientHeaders);
InetSocketAddress addr = randomAddress(newReq, addrs);
if (logger.isLoggable(Level.FINEST)) {
logger.log(
Level.FINEST,
"httpAsync: module=" + localModule + ", resname=" + resname + ", addr=" + addr);
}
return (CompletableFuture) webClient.sendAsync(addr, newReq);
}
byte[] clientBody = null;
if (isNotEmpty(req.getBody())) {
String paramstr = req.getParametersToString();
if (paramstr != null) {
if (req.getPath().indexOf('?') > 0) {
req.setPath(req.getPath() + "&" + paramstr);
} else {
req.setPath(req.getPath() + "?" + paramstr);
}
}
clientBody = req.getBody();
} else {
String paramstr = req.getParametersToString();
if (paramstr != null) {
clientBody = paramstr.getBytes(StandardCharsets.UTF_8);
}
}
if (logger.isLoggable(Level.FINEST)) {
logger.log(
Level.FINEST,
"httpAsync: module=" + localModule + ", resname=" + resname + ", enter sendEachAddressAsync");
}
return sendEachAddressAsync(req, req.requestPath(), clientHeaders, clientBody, addrs.iterator());
});
}
protected InetSocketAddress randomAddress(WebRequest req, Set<InetSocketAddress> addrs) {
InetSocketAddress[] array = addrs.toArray(new InetSocketAddress[addrs.size()]);
return array[ThreadLocalRandom.current().nextInt(array.length)];
}
protected InetSocketAddress randomAddress(WebRequest req, Set<InetSocketAddress> addrs) {
InetSocketAddress[] array = addrs.toArray(new InetSocketAddress[addrs.size()]);
return array[ThreadLocalRandom.current().nextInt(array.length)];
}
protected CompletableFuture<HttpResult<byte[]>> sendEachAddressAsync(
WebRequest req,
String requestPath,
final HttpHeaders clientHeaders,
byte[] clientBody,
Iterator<InetSocketAddress> it) {
if (!it.hasNext()) {
return new HttpResult<byte[]>().status(404).toFuture();
}
InetSocketAddress addr = it.next();
String host = addr.getPort() > 0 && addr.getPort() != 80
? (addr.getHostString() + ":" + addr.getPort())
: addr.getHostString();
String url = "http://" + host + requestPath;
if (logger.isLoggable(Level.FINER)) {
logger.log(
Level.FINER,
"sendEachAddressAsync: url: " + url + ", body: "
+ (clientBody != null ? new String(clientBody, StandardCharsets.UTF_8) : "") + ", headers: "
+ clientHeaders);
}
java.net.http.HttpRequest.Builder builder = java.net.http.HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofMillis(10_000))
// 存在sendHeader后不发送body数据的问题 java.net.http.HttpRequest的bug?
.method("POST", createBodyPublisher(clientBody));
clientHeaders.forEach(builder::header);
return httpClient
.sendAsync(builder.build(), java.net.http.HttpResponse.BodyHandlers.ofByteArray())
.thenApply((java.net.http.HttpResponse<byte[]> resp) -> {
Traces.currentTraceid(req.getTraceid());
final int rs = resp.statusCode();
if (rs != 200) {
return new HttpResult<byte[]>().status(rs);
}
return new HttpResult<>(resp.body());
});
}
protected CompletableFuture<HttpResult<byte[]>> sendEachAddressAsync(
WebRequest req,
String requestPath,
final HttpHeaders clientHeaders,
byte[] clientBody,
Iterator<InetSocketAddress> it) {
if (!it.hasNext()) {
return new HttpResult<byte[]>().status(404).toFuture();
}
InetSocketAddress addr = it.next();
String host = addr.getPort() > 0 && addr.getPort() != 80
? (addr.getHostString() + ":" + addr.getPort())
: addr.getHostString();
String url = "http://" + host + requestPath;
if (logger.isLoggable(Level.FINER)) {
logger.log(
Level.FINER,
"sendEachAddressAsync: url: " + url + ", body: "
+ (clientBody != null ? new String(clientBody, StandardCharsets.UTF_8) : "") + ", headers: "
+ clientHeaders);
}
java.net.http.HttpRequest.Builder builder = java.net.http.HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofMillis(10_000))
// 存在sendHeader后不发送body数据的问题 java.net.http.HttpRequest的bug?
.method("POST", createBodyPublisher(clientBody));
clientHeaders.forEach(builder::header);
return httpClient
.sendAsync(builder.build(), java.net.http.HttpResponse.BodyHandlers.ofByteArray())
.thenApply((java.net.http.HttpResponse<byte[]> resp) -> {
Traces.currentTraceid(req.getTraceid());
final int rs = resp.statusCode();
if (rs != 200) {
return new HttpResult<byte[]>().status(rs);
}
return new HttpResult<>(resp.body());
});
}
private static java.net.http.HttpRequest.BodyPublisher createBodyPublisher(byte[] clientBody) {
return clientBody == null
? java.net.http.HttpRequest.BodyPublishers.noBody()
: java.net.http.HttpRequest.BodyPublishers.ofByteArray(clientBody);
}
private static java.net.http.HttpRequest.BodyPublisher createBodyPublisher(byte[] clientBody) {
return clientBody == null
? java.net.http.HttpRequest.BodyPublishers.noBody()
: java.net.http.HttpRequest.BodyPublishers.ofByteArray(clientBody);
}
}

View File

@@ -32,320 +32,320 @@ import org.redkale.util.Traces;
*/
public class HttpLocalRpcClient extends HttpRpcClient {
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
protected final Application application;
protected final Application application;
protected final String resourceName;
protected final String resourceName;
protected HttpServer currServer;
protected HttpServer currServer;
public HttpLocalRpcClient(Application application, String resourceName) {
this.application = application;
this.resourceName = resourceName;
}
public HttpLocalRpcClient(Application application, String resourceName) {
this.application = application;
this.resourceName = resourceName;
}
private HttpServer httpServer() {
if (this.currServer == null) {
NodeHttpServer nodeHttpServer = null;
List<NodeServer> nodeServers = application.getNodeServers();
for (NodeServer n : nodeServers) {
if (n.getClass() == NodeHttpServer.class
&& Objects.equals(
resourceName,
((NodeHttpServer) n).getHttpServer().getName())) {
nodeHttpServer = (NodeHttpServer) n;
break;
}
}
if (nodeHttpServer == null) {
for (NodeServer n : nodeServers) {
if (n.getClass() == NodeHttpServer.class) {
nodeHttpServer = (NodeHttpServer) n;
break;
}
}
}
if (nodeHttpServer == null) {
throw new HttpException("Not found HttpServer");
}
this.currServer = nodeHttpServer.getServer();
}
return this.currServer;
}
private HttpServer httpServer() {
if (this.currServer == null) {
NodeHttpServer nodeHttpServer = null;
List<NodeServer> nodeServers = application.getNodeServers();
for (NodeServer n : nodeServers) {
if (n.getClass() == NodeHttpServer.class
&& Objects.equals(
resourceName,
((NodeHttpServer) n).getHttpServer().getName())) {
nodeHttpServer = (NodeHttpServer) n;
break;
}
}
if (nodeHttpServer == null) {
for (NodeServer n : nodeServers) {
if (n.getClass() == NodeHttpServer.class) {
nodeHttpServer = (NodeHttpServer) n;
break;
}
}
}
if (nodeHttpServer == null) {
throw new HttpException("Not found HttpServer");
}
this.currServer = nodeHttpServer.getServer();
}
return this.currServer;
}
@Override
protected String getNodeid() {
return application.getNodeid();
}
@Override
protected String getNodeid() {
return application.getNodeid();
}
protected HttpContext context() {
return httpServer().getContext();
}
protected HttpContext context() {
return httpServer().getContext();
}
protected HttpDispatcherServlet dispatcherServlet() {
return (HttpDispatcherServlet) httpServer().getDispatcherServlet();
}
protected HttpDispatcherServlet dispatcherServlet() {
return (HttpDispatcherServlet) httpServer().getDispatcherServlet();
}
public HttpServlet findHttpServlet(String topic) {
return dispatcherServlet().findServletByTopic(topic);
}
public HttpServlet findHttpServlet(String topic) {
return dispatcherServlet().findServletByTopic(topic);
}
public HttpServlet findHttpServlet(WebRequest request) {
return dispatcherServlet().findServletByTopic(generateHttpReqTopic(request, request.getContextPath()));
}
public HttpServlet findHttpServlet(WebRequest request) {
return dispatcherServlet().findServletByTopic(generateHttpReqTopic(request, request.getContextPath()));
}
@Override
public <T> CompletableFuture<T> sendMessage(WebRequest request, Type type) {
return sendMessage((Serializable) null, (String) null, request, type);
}
@Override
public <T> CompletableFuture<T> sendMessage(WebRequest request, Type type) {
return sendMessage((Serializable) null, (String) null, request, type);
}
@Override
public <T> CompletableFuture<T> sendMessage(Serializable userid, WebRequest request, Type type) {
return sendMessage(userid, (String) null, request, type);
}
@Override
public <T> CompletableFuture<T> sendMessage(Serializable userid, WebRequest request, Type type) {
return sendMessage(userid, (String) null, request, type);
}
@Override
public <T> CompletableFuture<T> sendMessage(Serializable userid, String groupid, WebRequest request, Type type) {
if (isEmpty(request.getTraceid())) {
request.setTraceid(Traces.currentTraceid());
}
CompletableFuture future = new CompletableFuture();
String topic = generateHttpReqTopic(request, request.getContextPath());
HttpServlet servlet = findHttpServlet(topic);
if (servlet == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "sendMessage: request=" + request + ", not found servlet");
}
future.completeExceptionally(new HttpException("404 Not Found " + topic));
return future;
}
HttpRequest req = new HttpMessageLocalRequest(context(), request, userid);
HttpResponse resp = new HttpMessageLocalResponse(req, future);
try {
servlet.execute(req, resp);
} catch (Exception e) {
future.completeExceptionally(e);
}
return future;
}
@Override
public <T> CompletableFuture<T> sendMessage(Serializable userid, String groupid, WebRequest request, Type type) {
if (isEmpty(request.getTraceid())) {
request.setTraceid(Traces.currentTraceid());
}
CompletableFuture future = new CompletableFuture();
String topic = generateHttpReqTopic(request, request.getContextPath());
HttpServlet servlet = findHttpServlet(topic);
if (servlet == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "sendMessage: request=" + request + ", not found servlet");
}
future.completeExceptionally(new HttpException("404 Not Found " + topic));
return future;
}
HttpRequest req = new HttpMessageLocalRequest(context(), request, userid);
HttpResponse resp = new HttpMessageLocalResponse(req, future);
try {
servlet.execute(req, resp);
} catch (Exception e) {
future.completeExceptionally(e);
}
return future;
}
@Override
public CompletableFuture<HttpResult<byte[]>> sendMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
if (isEmpty(request.getTraceid())) {
request.setTraceid(Traces.currentTraceid());
}
CompletableFuture future = new CompletableFuture();
HttpServlet servlet = findHttpServlet(topic);
if (servlet == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "sendMessage: request=" + request + ", not found servlet");
}
future.complete(new HttpResult().status(404));
return future;
}
HttpRequest req = new HttpMessageLocalRequest(context(), request, userid);
HttpResponse resp = new HttpMessageLocalResponse(req, future);
try {
servlet.execute(req, resp);
} catch (Exception e) {
future.completeExceptionally(e);
}
return future.thenApply(rs -> {
Traces.currentTraceid(request.getTraceid());
if (rs == null) {
return new HttpResult();
}
if (rs instanceof HttpResult) {
Object result = ((HttpResult) rs).getResult();
if (result == null || result instanceof byte[]) {
return (HttpResult) rs;
}
return new HttpResult(JsonConvert.root().convertToBytes(result));
}
return new HttpResult(JsonConvert.root().convertToBytes(rs));
});
}
@Override
public CompletableFuture<HttpResult<byte[]>> sendMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
if (isEmpty(request.getTraceid())) {
request.setTraceid(Traces.currentTraceid());
}
CompletableFuture future = new CompletableFuture();
HttpServlet servlet = findHttpServlet(topic);
if (servlet == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "sendMessage: request=" + request + ", not found servlet");
}
future.complete(new HttpResult().status(404));
return future;
}
HttpRequest req = new HttpMessageLocalRequest(context(), request, userid);
HttpResponse resp = new HttpMessageLocalResponse(req, future);
try {
servlet.execute(req, resp);
} catch (Exception e) {
future.completeExceptionally(e);
}
return future.thenApply(rs -> {
Traces.currentTraceid(request.getTraceid());
if (rs == null) {
return new HttpResult();
}
if (rs instanceof HttpResult) {
Object result = ((HttpResult) rs).getResult();
if (result == null || result instanceof byte[]) {
return (HttpResult) rs;
}
return new HttpResult(JsonConvert.root().convertToBytes(result));
}
return new HttpResult(JsonConvert.root().convertToBytes(rs));
});
}
@Override
public CompletableFuture<Void> produceMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
CompletableFuture future = new CompletableFuture();
HttpDispatcherServlet ps = dispatcherServlet();
HttpServlet servlet = ps.findServletByTopic(topic);
if (servlet == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "produceMessage: request=" + request + ", not found servlet");
}
future.completeExceptionally(new RuntimeException("404 Not Found " + topic));
return future;
}
HttpRequest req = new HttpMessageLocalRequest(context(), request, userid);
HttpResponse resp = new HttpMessageLocalResponse(req, null);
try {
servlet.execute(req, resp);
} catch (Exception e) {
throw new RedkaleException(e);
}
return future.thenApply(rs -> {
Traces.currentTraceid(request.getTraceid());
return null;
});
}
@Override
public CompletableFuture<Void> produceMessage(
String topic, Serializable userid, String groupid, WebRequest request) {
CompletableFuture future = new CompletableFuture();
HttpDispatcherServlet ps = dispatcherServlet();
HttpServlet servlet = ps.findServletByTopic(topic);
if (servlet == null) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "produceMessage: request=" + request + ", not found servlet");
}
future.completeExceptionally(new RuntimeException("404 Not Found " + topic));
return future;
}
HttpRequest req = new HttpMessageLocalRequest(context(), request, userid);
HttpResponse resp = new HttpMessageLocalResponse(req, null);
try {
servlet.execute(req, resp);
} catch (Exception e) {
throw new RedkaleException(e);
}
return future.thenApply(rs -> {
Traces.currentTraceid(request.getTraceid());
return null;
});
}
public static class HttpMessageLocalRequest extends HttpRequest {
public static class HttpMessageLocalRequest extends HttpRequest {
public HttpMessageLocalRequest(HttpContext context, WebRequest req, Serializable userid) {
super(context, req);
if (userid != null) {
this.currentUserid = userid;
}
}
}
public HttpMessageLocalRequest(HttpContext context, WebRequest req, Serializable userid) {
super(context, req);
if (userid != null) {
this.currentUserid = userid;
}
}
}
public static class HttpMessageLocalResponse extends HttpResponse {
public static class HttpMessageLocalResponse extends HttpResponse {
private final CompletableFuture future;
private final CompletableFuture future;
public HttpMessageLocalResponse(HttpRequest req, CompletableFuture future) {
super(req.getContext(), req, null);
this.future = future;
}
public HttpMessageLocalResponse(HttpRequest req, CompletableFuture future) {
super(req.getContext(), req, null);
this.future = future;
}
@Override
public void finishJson(final Convert convert, final Type type, final Object obj) {
if (future == null) {
return;
}
future.complete(obj);
}
@Override
public void finishJson(final Convert convert, final Type type, final Object obj) {
if (future == null) {
return;
}
future.complete(obj);
}
@Override
public void finish(final Convert convert, Type type, org.redkale.service.RetResult ret) {
if (future == null) {
return;
}
future.complete(ret);
}
@Override
public void finish(final Convert convert, Type type, org.redkale.service.RetResult ret) {
if (future == null) {
return;
}
future.complete(ret);
}
@Override
public void finish(final Convert convert, final Type type, Object obj) {
if (future == null) {
return;
}
if (obj instanceof CompletableFuture) {
((CompletableFuture) obj).whenComplete((r, t) -> {
if (t == null) {
future.complete(r);
} else {
future.completeExceptionally((Throwable) t);
}
});
} else {
future.complete(obj);
}
}
@Override
public void finish(final Convert convert, final Type type, Object obj) {
if (future == null) {
return;
}
if (obj instanceof CompletableFuture) {
((CompletableFuture) obj).whenComplete((r, t) -> {
if (t == null) {
future.complete(r);
} else {
future.completeExceptionally((Throwable) t);
}
});
} else {
future.complete(obj);
}
}
@Override
public void finish(String obj) {
if (future == null) {
return;
}
future.complete(obj == null ? "" : obj);
}
@Override
public void finish(String obj) {
if (future == null) {
return;
}
future.complete(obj == null ? "" : obj);
}
@Override
public void finish304() {
finish(304, null);
}
@Override
public void finish304() {
finish(304, null);
}
@Override
public void finish404() {
finish(404, null);
}
@Override
public void finish404() {
finish(404, null);
}
@Override
public void finish500() {
finish(500, null);
}
@Override
public void finish500() {
finish(500, null);
}
@Override
public void finish504() {
finish(504, null);
}
@Override
public void finish504() {
finish(504, null);
}
@Override
public void finish(int status, String msg) {
if (future == null) {
return;
}
if (status == 0 || status == 200) {
future.complete(msg == null ? "" : msg);
} else {
future.complete(new HttpResult(msg == null ? "" : msg).status(status));
}
}
@Override
public void finish(int status, String msg) {
if (future == null) {
return;
}
if (status == 0 || status == 200) {
future.complete(msg == null ? "" : msg);
} else {
future.complete(new HttpResult(msg == null ? "" : msg).status(status));
}
}
@Override
public void finish(final Convert convert, Type valueType, HttpResult result) {
if (future == null) {
return;
}
if (convert != null) {
result.convert(convert);
}
future.complete(result);
}
@Override
public void finish(final Convert convert, Type valueType, HttpResult result) {
if (future == null) {
return;
}
if (convert != null) {
result.convert(convert);
}
future.complete(result);
}
@Override
public void finish(boolean kill, final byte[] bs, int offset, int length) {
if (future == null) {
return;
}
if (offset == 0 && bs.length == length) {
future.complete(bs);
} else {
future.complete(Arrays.copyOfRange(bs, offset, offset + length));
}
}
@Override
public void finish(boolean kill, final byte[] bs, int offset, int length) {
if (future == null) {
return;
}
if (offset == 0 && bs.length == length) {
future.complete(bs);
} else {
future.complete(Arrays.copyOfRange(bs, offset, offset + length));
}
}
@Override
public void finish(boolean kill, final String contentType, final byte[] bs, int offset, int length) {
if (future == null) {
return;
}
byte[] rs = (offset == 0 && bs.length == length) ? bs : Arrays.copyOfRange(bs, offset, offset + length);
future.complete(rs);
}
@Override
public void finish(boolean kill, final String contentType, final byte[] bs, int offset, int length) {
if (future == null) {
return;
}
byte[] rs = (offset == 0 && bs.length == length) ? bs : Arrays.copyOfRange(bs, offset, offset + length);
future.complete(rs);
}
@Override
public void finishBuffer(boolean kill, ByteBuffer buffer) {
if (future == null) {
return;
}
byte[] bs = new byte[buffer.remaining()];
buffer.get(bs);
future.complete(bs);
}
@Override
public void finishBuffer(boolean kill, ByteBuffer buffer) {
if (future == null) {
return;
}
byte[] bs = new byte[buffer.remaining()];
buffer.get(bs);
future.complete(bs);
}
@Override
public void finishBuffers(boolean kill, ByteBuffer... buffers) {
if (future == null) {
return;
}
int size = 0;
for (ByteBuffer buf : buffers) {
size += buf.remaining();
}
byte[] bs = new byte[size];
int index = 0;
for (ByteBuffer buf : buffers) {
int r = buf.remaining();
buf.get(bs, index, r);
index += r;
}
future.complete(bs);
}
}
@Override
public void finishBuffers(boolean kill, ByteBuffer... buffers) {
if (future == null) {
return;
}
int size = 0;
for (ByteBuffer buf : buffers) {
size += buf.remaining();
}
byte[] bs = new byte[size];
int index = 0;
for (ByteBuffer buf : buffers) {
int r = buf.remaining();
buf.get(bs, index, r);
index += r;
}
future.complete(bs);
}
}
}

View File

@@ -21,61 +21,61 @@ import org.redkale.util.*;
*/
public class AnyDecoder<T> implements Decodeable<Reader, T> {
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {}.getType();
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {}.getType();
private static final Type mapObjectType = new TypeToken<Map<String, 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<ArrayList> collectionCreator = Creator.create(ArrayList.class);
private static final Creator<LinkedHashMap> mapCreator = Creator.create(LinkedHashMap.class);
private static final Creator<LinkedHashMap> mapCreator = Creator.create(LinkedHashMap.class);
protected final Decodeable<Reader, ? extends CharSequence> stringDecoder;
protected final Decodeable<Reader, ? extends CharSequence> stringDecoder;
protected final CollectionDecoder collectionDecoder;
protected final CollectionDecoder collectionDecoder;
protected final MapDecoder mapDecoder;
protected final MapDecoder mapDecoder;
/**
* 构造函数
*
* @param factory ConvertFactory
*/
public AnyDecoder(final ConvertFactory factory) {
this(mapCreator, mapObjectType, collectionCreator, collectionObjectType, factory.loadDecoder(String.class));
}
/**
* 构造函数
*
* @param factory ConvertFactory
*/
public AnyDecoder(final ConvertFactory factory) {
this(mapCreator, mapObjectType, collectionCreator, collectionObjectType, factory.loadDecoder(String.class));
}
protected AnyDecoder(
Creator<? extends Map> mapCreator,
Type mapObjectType,
Creator<? extends Collection> listCreator,
Type listObjectType,
Decodeable<Reader, String> keyDecoder) {
this.stringDecoder = keyDecoder;
this.collectionDecoder = new CollectionDecoder(listObjectType, Object.class, listCreator, this);
this.mapDecoder = new MapDecoder(mapObjectType, String.class, Object.class, mapCreator, keyDecoder, this);
}
protected AnyDecoder(
Creator<? extends Map> mapCreator,
Type mapObjectType,
Creator<? extends Collection> listCreator,
Type listObjectType,
Decodeable<Reader, String> keyDecoder) {
this.stringDecoder = keyDecoder;
this.collectionDecoder = new CollectionDecoder(listObjectType, Object.class, listCreator, this);
this.mapDecoder = new MapDecoder(mapObjectType, String.class, Object.class, mapCreator, keyDecoder, this);
}
@Override
public T convertFrom(Reader in) {
ValueType vt = in.readType();
if (vt == null) {
return null;
}
switch (vt) {
case ARRAY:
return (T) this.collectionDecoder.convertFrom(in);
case MAP:
return (T) this.mapDecoder.convertFrom(in);
}
return (T) stringFrom(in);
}
@Override
public T convertFrom(Reader in) {
ValueType vt = in.readType();
if (vt == null) {
return null;
}
switch (vt) {
case ARRAY:
return (T) this.collectionDecoder.convertFrom(in);
case MAP:
return (T) this.mapDecoder.convertFrom(in);
}
return (T) stringFrom(in);
}
protected T stringFrom(Reader in) {
return (T) this.stringDecoder.convertFrom(in);
}
protected T stringFrom(Reader in) {
return (T) this.stringDecoder.convertFrom(in);
}
@Override
public Type getType() {
return void.class;
}
@Override
public Type getType() {
return void.class;
}
}

View File

@@ -17,39 +17,39 @@ import java.lang.reflect.Type;
*/
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
final ConvertFactory factory;
final ConvertFactory factory;
AnyEncoder(ConvertFactory factory) {
this.factory = 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);
}
}
@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);
}
}
@Override
public Type getType() {
return Object.class;
}
@Override
public Type getType() {
return Object.class;
}
@Override
public boolean specifyable() {
return false;
}
@Override
public boolean specifyable() {
return false;
}
}

View File

@@ -19,19 +19,19 @@ import org.redkale.util.AnyValue;
*/
public class AnyValueDecoder<R extends Reader> implements Decodeable<R, AnyValue> {
protected final ConvertFactory factory;
protected final ConvertFactory factory;
public AnyValueDecoder(final ConvertFactory factory) {
this.factory = factory;
}
public AnyValueDecoder(final ConvertFactory factory) {
this.factory = factory;
}
@Override
public AnyValue convertFrom(R in) {
return null;
}
@Override
public AnyValue convertFrom(R in) {
return null;
}
@Override
public Type getType() {
return AnyValue.class;
}
@Override
public Type getType() {
return AnyValue.class;
}
}

View File

@@ -19,13 +19,13 @@ import org.redkale.util.AnyValue;
*/
public class AnyValueEncoder<W extends Writer> implements Encodeable<W, AnyValue> {
@Override
public void convertTo(W out, AnyValue value) {
// do nothing
}
@Override
public void convertTo(W out, AnyValue value) {
// do nothing
}
@Override
public Type getType() {
return AnyValue.class;
}
@Override
public Type getType() {
return AnyValue.class;
}
}

View File

@@ -24,138 +24,138 @@ import org.redkale.util.Creator;
@SuppressWarnings("unchecked")
public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
protected final Type type;
protected final Type type;
protected final Type componentType;
protected final Type componentType;
protected final Class componentClass;
protected final Class componentClass;
protected final Decodeable<Reader, T> componentDecoder;
protected final Decodeable<Reader, T> componentDecoder;
protected final IntFunction<T[]> componentArrayFunction;
protected final IntFunction<T[]> componentArrayFunction;
protected volatile boolean inited = false;
protected volatile boolean inited = false;
private final ReentrantLock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private final Condition condition = lock.newCondition();
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);
this.componentArrayFunction = Creator.funcArray(this.componentClass);
} finally {
inited = true;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
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);
this.componentArrayFunction = Creator.funcArray(this.componentClass);
} finally {
inited = true;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
@Override
public T[] convertFrom(Reader in) {
return convertFrom(in, null);
}
@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) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
}
}
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 = this.componentArrayFunction.apply(result.size());
return result.toArray(rs);
}
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) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
}
}
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 = this.componentArrayFunction.apply(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 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 Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
return decoder;
}
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
return in;
}
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);
}
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 String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:"
+ this.componentDecoder + "}";
}
@Override
public Type getType() {
return type;
}
@Override
public Type getType() {
return type;
}
public Type getComponentType() {
return componentType;
}
public Type getComponentType() {
return componentType;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
}

View File

@@ -21,142 +21,142 @@ import java.util.concurrent.locks.*;
@SuppressWarnings("unchecked")
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
protected final Type type;
protected final Type type;
protected final Type componentType;
protected final Type componentType;
protected final Encodeable anyEncoder;
protected final Encodeable anyEncoder;
protected final Encodeable<Writer, Object> componentEncoder;
protected final Encodeable<Writer, Object> componentEncoder;
protected final boolean subTypeFinal;
protected final boolean subTypeFinal;
protected volatile boolean inited = false;
protected volatile boolean inited = false;
private final ReentrantLock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private final Condition condition = lock.newCondition();
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);
if (componentEncoder == null) {
throw new ConvertException(
"ArrayEncoder init componentEncoder error, componentType = " + this.componentType);
}
this.anyEncoder = factory.getAnyEncoder();
this.subTypeFinal = (this.componentType instanceof Class)
&& Modifier.isFinal(((Class) this.componentType).getModifiers());
} finally {
inited = true;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
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);
if (componentEncoder == null) {
throw new ConvertException(
"ArrayEncoder init componentEncoder error, componentType = " + this.componentType);
}
this.anyEncoder = factory.getAnyEncoder();
this.subTypeFinal = (this.componentType instanceof Class)
&& Modifier.isFinal(((Class) this.componentType).getModifiers());
} finally {
inited = true;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
@Override
public void convertTo(Writer out, T[] value) {
convertTo(out, null, value);
}
@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;
}
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
if (itemEncoder == null) {
if (!this.inited) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
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.specificObjectType() == comp))
? itemEncoder
: anyEncoder),
v,
i);
if (i == iMax) {
break;
}
out.writeArrayMark();
}
}
}
out.writeArrayE();
}
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;
}
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
if (itemEncoder == null) {
if (!this.inited) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
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.specificObjectType() == 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);
}
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 String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:"
+ this.componentEncoder + "}";
}
@Override
public Type getType() {
return type;
}
@Override
public Type getType() {
return type;
}
@Override
public boolean specifyable() {
return false;
}
@Override
public boolean specifyable() {
return false;
}
public Type getComponentType() {
return componentType;
}
public Type getComponentType() {
return componentType;
}
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
}

View File

@@ -18,18 +18,18 @@ import java.lang.reflect.Type;
*/
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
protected BinaryConvert(ConvertFactory<R, W> factory, int features) {
super(factory, features);
}
protected BinaryConvert(ConvertFactory<R, W> factory, int features) {
super(factory, features);
}
@Override
public final boolean isBinary() {
return true;
}
@Override
public final boolean isBinary() {
return true;
}
public final byte[] convertTo(final Object value) {
return convertTo((Type) null, value);
}
public final byte[] convertTo(final Object value) {
return convertTo((Type) null, value);
}
public abstract byte[] convertTo(final Type type, final Object value);
public abstract byte[] convertTo(final Type type, final Object value);
}

View File

@@ -22,141 +22,141 @@ import org.redkale.util.Creator;
@SuppressWarnings("unchecked")
public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
protected final Type type;
protected final Type type;
protected final Type componentType;
protected final Type componentType;
protected Creator<Collection<T>> creator;
protected Creator<Collection<T>> creator;
protected final Decodeable<Reader, T> componentDecoder;
protected final Decodeable<Reader, T> componentDecoder;
protected volatile boolean inited = false;
protected volatile boolean inited = false;
private final ReentrantLock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private final Condition condition = lock.newCondition();
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;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
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;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
// 仅供类似JsonAnyDecoder这种动态创建使用 不得调用 factory.register
public CollectionDecoder(
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;
}
// 仅供类似JsonAnyDecoder这种动态创建使用 不得调用 factory.register
public CollectionDecoder(
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);
}
@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) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
}
}
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;
}
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) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
}
}
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 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 Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
return decoder;
}
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
return in;
}
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);
}
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;
}
@Override
public Type getType() {
return type;
}
public Type getComponentType() {
return componentType;
}
public Type getComponentType() {
return componentType;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
}

View File

@@ -21,107 +21,107 @@ import java.util.concurrent.locks.*;
@SuppressWarnings("unchecked")
public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
protected final Type type;
protected final Type type;
protected final Encodeable<Writer, Object> componentEncoder;
protected final Encodeable<Writer, Object> componentEncoder;
protected volatile boolean inited = false;
protected volatile boolean inited = false;
private final ReentrantLock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private final Condition condition = lock.newCondition();
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;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
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;
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
}
@Override
public void convertTo(Writer out, Collection<T> value) {
convertTo(out, null, value);
}
@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) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
}
}
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();
}
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) {
lock.lock();
try {
condition.await();
} catch (Exception e) {
// do nothing
} finally {
lock.unlock();
}
}
}
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);
}
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
componentEncoder.convertTo(out, value);
}
@Override
public Type getType() {
return type;
}
@Override
public Type getType() {
return type;
}
@Override
public boolean specifyable() {
return false;
}
@Override
public boolean specifyable() {
return false;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.type + ", encoder:" + this.componentEncoder
+ "}";
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.type + ", encoder:" + this.componentEncoder
+ "}";
}
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
public Type getComponentType() {
return componentEncoder == null ? null : componentEncoder.getType();
}
public Type getComponentType() {
return componentEncoder == null ? null : componentEncoder.getType();
}
}

View File

@@ -21,106 +21,106 @@ import org.redkale.util.*;
*/
public abstract class Convert<R extends Reader, W extends Writer> {
// 值为true时 String类型值为""Boolean类型值为false时不会输出默认为false
public static final int FEATURE_TINY = 1 << 1;
// 值为true时 String类型值为""Boolean类型值为false时不会输出默认为false
public static final int FEATURE_TINY = 1 << 1;
// 值为true时 字段值为null时会输出默认为false
public static final int FEATURE_NULLABLE = 1 << 2;
// 值为true时 字段值为null时会输出默认为false
public static final int FEATURE_NULLABLE = 1 << 2;
// 配置属性集合, 1<<1至1<<10为系统内置
protected final int features;
// 配置属性集合, 1<<1至1<<10为系统内置
protected final int features;
protected final ConvertFactory<R, W> factory;
protected final ConvertFactory<R, W> factory;
protected Convert(ConvertFactory<R, W> factory, int features) {
this.factory = factory;
this.features = features;
}
protected Convert(ConvertFactory<R, W> factory, int features) {
this.factory = factory;
this.features = features;
}
public ConvertFactory<R, W> getFactory() {
return this.factory;
}
public ConvertFactory<R, W> getFactory() {
return this.factory;
}
protected <S extends W> S configWrite(S writer) {
return writer;
}
protected <S extends W> S configWrite(S writer) {
return writer;
}
protected <S extends W> S fieldFunc(
S writer,
BiFunction<Attribute, Object, Object> objFieldFunc,
BiFunction mapFieldFunc,
Function<Object, ConvertField[]> objExtFunc) {
writer.mapFieldFunc = mapFieldFunc;
writer.objFieldFunc = objFieldFunc;
writer.objExtFunc = objExtFunc;
return writer;
}
protected <S extends W> S fieldFunc(
S writer,
BiFunction<Attribute, Object, Object> objFieldFunc,
BiFunction mapFieldFunc,
Function<Object, ConvertField[]> objExtFunc) {
writer.mapFieldFunc = mapFieldFunc;
writer.objFieldFunc = objFieldFunc;
writer.objExtFunc = objExtFunc;
return writer;
}
public Convert<R, W> newConvert(BiFunction<Attribute, Object, Object> objFieldFunc) {
return newConvert(objFieldFunc, null, null);
}
public Convert<R, W> newConvert(BiFunction<Attribute, Object, Object> objFieldFunc) {
return newConvert(objFieldFunc, null, null);
}
public Convert<R, W> newConvert(BiFunction<Attribute, Object, Object> objFieldFunc, BiFunction mapFieldFunc) {
return newConvert(objFieldFunc, mapFieldFunc, null);
}
public Convert<R, W> newConvert(BiFunction<Attribute, Object, Object> objFieldFunc, BiFunction mapFieldFunc) {
return newConvert(objFieldFunc, mapFieldFunc, null);
}
public Convert<R, W> newConvert(
BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
return newConvert(objFieldFunc, null, objExtFunc);
}
public Convert<R, W> newConvert(
BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
return newConvert(objFieldFunc, null, objExtFunc);
}
public abstract Convert<R, W> newConvert(
BiFunction<Attribute, Object, Object> objFieldFunc,
BiFunction mapFieldFunc,
Function<Object, ConvertField[]> objExtFunc);
public abstract Convert<R, W> newConvert(
BiFunction<Attribute, Object, Object> objFieldFunc,
BiFunction mapFieldFunc,
Function<Object, ConvertField[]> objExtFunc);
public abstract boolean isBinary();
public abstract boolean isBinary();
public abstract R pollReader();
public abstract R pollReader();
public abstract void offerReader(final R reader);
public abstract void offerReader(final R reader);
// 返回的Writer子类必须实现ByteTuple接口
public abstract W pollWriter();
// 返回的Writer子类必须实现ByteTuple接口
public abstract W pollWriter();
public abstract void offerWriter(final W write);
public abstract void offerWriter(final W write);
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
public abstract <T> T convertFrom(final Type type, final R reader);
public abstract <T> T convertFrom(final Type type, final R reader);
// @since 2.2.0
public abstract <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int length);
// @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 ByteBuffer... buffers);
public final void convertTo(final W writer, final Object value) {
convertTo(writer, (Type) null, value);
}
public final void convertTo(final W writer, final Object value) {
convertTo(writer, (Type) null, value);
}
public abstract void convertTo(final W writer, final Type type, final Object value);
public abstract void convertTo(final W writer, final Type type, final Object value);
public final byte[] convertToBytes(final Object value) {
return convertToBytes((Type) null, value);
}
public final byte[] convertToBytes(final Object value) {
return convertToBytes((Type) null, value);
}
public abstract byte[] convertToBytes(final Type type, final Object value);
public abstract byte[] convertToBytes(final Type type, final Object value);
public final void convertToBytes(final Object value, final ConvertBytesHandler handler) {
convertToBytes((Type) null, value, handler);
}
public final void convertToBytes(final Object value, final ConvertBytesHandler handler) {
convertToBytes((Type) null, value, handler);
}
public abstract void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler);
public abstract void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler);
public final void convertToBytes(final ByteArray array, final Object value) {
convertToBytes(array, (Type) null, value);
}
public final void convertToBytes(final ByteArray array, final Object value) {
convertToBytes(array, (Type) null, value);
}
public abstract void convertToBytes(final ByteArray array, final Type type, final Object value);
public abstract void convertToBytes(final ByteArray array, final Type type, final Object value);
public final ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) {
return convertTo(supplier, (Type) null, value);
}
public final ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) {
return convertTo(supplier, (Type) null, value);
}
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value);
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value);
}

Some files were not shown because too many files have changed in this diff Show More