Format
This commit is contained in:
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 值越大,优先级越高
|
||||
*
|
||||
* @see org.redkale.annotation.Priority
|
||||
* @since Common Annotations 1.2
|
||||
* @deprecated replace by {@link org.redkale.annotation.Priority}
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Priority {
|
||||
|
||||
/**
|
||||
* 优先级值
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 值越大,优先级越高
|
||||
*
|
||||
* @see org.redkale.annotation.Priority
|
||||
* @since Common Annotations 1.2
|
||||
* @deprecated replace by {@link org.redkale.annotation.Priority}
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Priority {
|
||||
|
||||
/**
|
||||
* 优先级值
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
|
||||
@@ -1,83 +1,83 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
* @see org.redkale.annotation.Resource
|
||||
* @deprecated replace by {@link org.redkale.annotation.Resource}
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Resource {
|
||||
|
||||
// /**
|
||||
// * AuthenticationType
|
||||
// */
|
||||
// @Deprecated
|
||||
// public enum AuthenticationType {
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// CONTAINER,
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// APPLICATION
|
||||
// }
|
||||
//
|
||||
/**
|
||||
* 资源名称
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String name() default "";
|
||||
|
||||
/**
|
||||
* 依赖注入的类型
|
||||
*
|
||||
* @return Class
|
||||
*/
|
||||
public Class<?> type() default Object.class;
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return AuthenticationType
|
||||
// */
|
||||
// @Deprecated
|
||||
// public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return boolean
|
||||
// */
|
||||
// @Deprecated
|
||||
// public boolean shareable() default true;
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return String
|
||||
// */
|
||||
// @Deprecated
|
||||
// public String description() default "";
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return String
|
||||
// */
|
||||
// @Deprecated
|
||||
// public String mappedName() default "";
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return String
|
||||
// */
|
||||
// @Deprecated
|
||||
// public String lookup() default "";
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
* @see org.redkale.annotation.Resource
|
||||
* @deprecated replace by {@link org.redkale.annotation.Resource}
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Resource {
|
||||
|
||||
// /**
|
||||
// * AuthenticationType
|
||||
// */
|
||||
// @Deprecated
|
||||
// public enum AuthenticationType {
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// CONTAINER,
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// APPLICATION
|
||||
// }
|
||||
//
|
||||
/**
|
||||
* 资源名称
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String name() default "";
|
||||
|
||||
/**
|
||||
* 依赖注入的类型
|
||||
*
|
||||
* @return Class
|
||||
*/
|
||||
public Class<?> type() default Object.class;
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return AuthenticationType
|
||||
// */
|
||||
// @Deprecated
|
||||
// public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return boolean
|
||||
// */
|
||||
// @Deprecated
|
||||
// public boolean shareable() default true;
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return String
|
||||
// */
|
||||
// @Deprecated
|
||||
// public String description() default "";
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return String
|
||||
// */
|
||||
// @Deprecated
|
||||
// public String mappedName() default "";
|
||||
//
|
||||
// /**
|
||||
// *
|
||||
// * @return String
|
||||
// */
|
||||
// @Deprecated
|
||||
// public String lookup() default "";
|
||||
}
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies whether an entity should be cached if caching is enabled when the value of the <code>persistence.xml</code>
|
||||
* caching element is <code>ENABLE_SELECTIVE</code> or <code>DISABLE_SELECTIVE</code>. The value of the <code>Cacheable
|
||||
* </code> annotation is inherited by subclasses; it can be overridden by specifying <code>Cacheable</code> on a
|
||||
* subclass.
|
||||
*
|
||||
* <p><code>Cacheable(false)</code> means that the entity and its state must not be cached by the provider.
|
||||
*
|
||||
* @since Java Persistence 2.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Cacheable}
|
||||
* @see org.redkale.persistence.Cacheable
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cacheable {
|
||||
|
||||
/**
|
||||
* (Optional) Whether or not the entity should be cached.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int interval() default 0;
|
||||
|
||||
/**
|
||||
* DataSource是否直接返回对象的真实引用, 而不是copy一份
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean direct() default false;
|
||||
}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies whether an entity should be cached if caching is enabled when the value of the <code>persistence.xml</code>
|
||||
* caching element is <code>ENABLE_SELECTIVE</code> or <code>DISABLE_SELECTIVE</code>. The value of the <code>Cacheable
|
||||
* </code> annotation is inherited by subclasses; it can be overridden by specifying <code>Cacheable</code> on a
|
||||
* subclass.
|
||||
*
|
||||
* <p><code>Cacheable(false)</code> means that the entity and its state must not be cached by the provider.
|
||||
*
|
||||
* @since Java Persistence 2.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Cacheable}
|
||||
* @see org.redkale.persistence.Cacheable
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cacheable {
|
||||
|
||||
/**
|
||||
* (Optional) Whether or not the entity should be cached.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int interval() default 0;
|
||||
|
||||
/**
|
||||
* DataSource是否直接返回对象的真实引用, 而不是copy一份
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean direct() default false;
|
||||
}
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the mapped column for a persistent property or field. If no <code>Column</code> annotation is specified,
|
||||
* the default values apply.
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* Example 1:
|
||||
*
|
||||
* @Column(name="DESC", nullable=false, length=512)
|
||||
* public String getDescription() { return description; }
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* @Column(name="DESC",
|
||||
* columnDefinition="CLOB NOT NULL",
|
||||
* table="EMP_DETAIL")
|
||||
* @Lob
|
||||
* public String getDescription() { return description; }
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* @Column(name="ORDER_COST", updatable=false, precision=12, scale=2)
|
||||
* public BigDecimal getCost() { return cost; }
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Column}
|
||||
* @see org.redkale.persistence.Column
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({METHOD, FIELD})
|
||||
@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 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 database column is required.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean nullable() default true;
|
||||
|
||||
/**
|
||||
* 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 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 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 <= 16777215 then sqltype is MEDIUMTEXT <br>
|
||||
* if type==String and length > 16777215 then sqltype is LONGTEXT <br>
|
||||
* if type==byte[] and length <= 65535 then sqltype is BLOB <br>
|
||||
* if type==byte[] and length <= 16777215 then sqltype is MEDIUMBLOB <br>
|
||||
* if type==byte[] and length > 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 scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int scale() default 0;
|
||||
}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the mapped column for a persistent property or field. If no <code>Column</code> annotation is specified,
|
||||
* the default values apply.
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* Example 1:
|
||||
*
|
||||
* @Column(name="DESC", nullable=false, length=512)
|
||||
* public String getDescription() { return description; }
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* @Column(name="DESC",
|
||||
* columnDefinition="CLOB NOT NULL",
|
||||
* table="EMP_DETAIL")
|
||||
* @Lob
|
||||
* public String getDescription() { return description; }
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* @Column(name="ORDER_COST", updatable=false, precision=12, scale=2)
|
||||
* public BigDecimal getCost() { return cost; }
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Column}
|
||||
* @see org.redkale.persistence.Column
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({METHOD, FIELD})
|
||||
@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 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 database column is required.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean nullable() default true;
|
||||
|
||||
/**
|
||||
* 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 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 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 <= 16777215 then sqltype is MEDIUMTEXT <br>
|
||||
* if type==String and length > 16777215 then sqltype is LONGTEXT <br>
|
||||
* if type==byte[] and length <= 65535 then sqltype is BLOB <br>
|
||||
* if type==byte[] and length <= 16777215 then sqltype is MEDIUMBLOB <br>
|
||||
* if type==byte[] and length > 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 scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int scale() default 0;
|
||||
}
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies that the class is an entity. This annotation is applied to the entity class.
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Entity}
|
||||
* @see org.redkale.persistence.Entity
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target(TYPE)
|
||||
@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 comment of the entity.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies that the class is an entity. This annotation is applied to the entity class.
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Entity}
|
||||
* @see org.redkale.persistence.Entity
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target(TYPE)
|
||||
@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 comment of the entity.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the primary key of an entity. The field or property to which the <code>Id</code> annotation is applied
|
||||
* should be one of the following types: any Java primitive type; any primitive wrapper type; <code>String</code>;
|
||||
* <code>java.util.Date</code>; <code>java.sql.Date</code>; <code>java.math.BigDecimal</code>; <code>
|
||||
* java.math.BigInteger</code>.
|
||||
*
|
||||
* <p>The mapped column for the primary key of the entity is assumed to be the primary key of the primary table. If no
|
||||
* <code>Column</code> annotation is specified, the primary key column name is assumed to be the name of the primary key
|
||||
* property or field.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
*
|
||||
* @Id
|
||||
* public Long getId() { return id; }
|
||||
* </pre>
|
||||
*
|
||||
* @see Column see GeneratedValue
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Id}
|
||||
* @see org.redkale.persistence.Id
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Id {}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the primary key of an entity. The field or property to which the <code>Id</code> annotation is applied
|
||||
* should be one of the following types: any Java primitive type; any primitive wrapper type; <code>String</code>;
|
||||
* <code>java.util.Date</code>; <code>java.sql.Date</code>; <code>java.math.BigDecimal</code>; <code>
|
||||
* java.math.BigInteger</code>.
|
||||
*
|
||||
* <p>The mapped column for the primary key of the entity is assumed to be the primary key of the primary table. If no
|
||||
* <code>Column</code> annotation is specified, the primary key column name is assumed to be the name of the primary key
|
||||
* property or field.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
*
|
||||
* @Id
|
||||
* public Long getId() { return id; }
|
||||
* </pre>
|
||||
*
|
||||
* @see Column see GeneratedValue
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Id}
|
||||
* @see org.redkale.persistence.Id
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Id {}
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2011 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Used in schema generation to specify creation of an index.
|
||||
*
|
||||
* <p>Note that it is not necessary to specify an index for a primary key, as the primary key index will be created
|
||||
* automatically.
|
||||
*
|
||||
* <p>The syntax of the <code>columnList</code> element is a <code>column_list</code>, as follows:
|
||||
*
|
||||
* <pre>
|
||||
* column::= index_column [,index_column]*
|
||||
* index_column::= column_name [ASC | DESC]
|
||||
* </pre>
|
||||
*
|
||||
* <p>If <code>ASC</code> or <code>DESC</code> is not specified, <code>ASC</code> (ascending order) is assumed.
|
||||
*
|
||||
* @since Java Persistence 2.1
|
||||
* @deprecated replace by {@link org.redkale.persistence.Index}
|
||||
* @see org.redkale.persistence.Index
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Index {
|
||||
|
||||
/**
|
||||
* (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();
|
||||
|
||||
/**
|
||||
* (Optional) Whether the index is unique.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean unique() default false;
|
||||
}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2011 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Used in schema generation to specify creation of an index.
|
||||
*
|
||||
* <p>Note that it is not necessary to specify an index for a primary key, as the primary key index will be created
|
||||
* automatically.
|
||||
*
|
||||
* <p>The syntax of the <code>columnList</code> element is a <code>column_list</code>, as follows:
|
||||
*
|
||||
* <pre>
|
||||
* column::= index_column [,index_column]*
|
||||
* index_column::= column_name [ASC | DESC]
|
||||
* </pre>
|
||||
*
|
||||
* <p>If <code>ASC</code> or <code>DESC</code> is not specified, <code>ASC</code> (ascending order) is assumed.
|
||||
*
|
||||
* @since Java Persistence 2.1
|
||||
* @deprecated replace by {@link org.redkale.persistence.Index}
|
||||
* @see org.redkale.persistence.Index
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Index {
|
||||
|
||||
/**
|
||||
* (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();
|
||||
|
||||
/**
|
||||
* (Optional) Whether the index is unique.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean unique() default false;
|
||||
}
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the primary table for the annotated entity. Additional tables may be specified using SecondaryTable or
|
||||
* SecondaryTables annotation.
|
||||
*
|
||||
* <p>If no <code>Table</code> annotation is specified for an entity class, the default values apply.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
*
|
||||
* @Entity
|
||||
* @Table(name="CUST", schema="RECORDS")
|
||||
* public class Customer { ... }
|
||||
* </pre>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Table}
|
||||
* @see org.redkale.persistence.Table
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Table {
|
||||
|
||||
/**
|
||||
* (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) 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 {};
|
||||
|
||||
/**
|
||||
* comment
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the primary table for the annotated entity. Additional tables may be specified using SecondaryTable or
|
||||
* SecondaryTables annotation.
|
||||
*
|
||||
* <p>If no <code>Table</code> annotation is specified for an entity class, the default values apply.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
*
|
||||
* @Entity
|
||||
* @Table(name="CUST", schema="RECORDS")
|
||||
* public class Customer { ... }
|
||||
* </pre>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Table}
|
||||
* @see org.redkale.persistence.Table
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Table {
|
||||
|
||||
/**
|
||||
* (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) 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 {};
|
||||
|
||||
/**
|
||||
* comment
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies that the property or field is not persistent. It is used to annotate a property or field of an entity
|
||||
* class, mapped superclass, or embeddable class.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
*
|
||||
* @Entity
|
||||
* public class Employee {
|
||||
* @Id int id;
|
||||
* @Transient User currentUser;
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Transient}
|
||||
* @see org.redkale.persistence.Transient
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Transient {}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies that the property or field is not persistent. It is used to annotate a property or field of an entity
|
||||
* class, mapped superclass, or embeddable class.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
*
|
||||
* @Entity
|
||||
* public class Employee {
|
||||
* @Id int id;
|
||||
* @Transient User currentUser;
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.Transient}
|
||||
* @see org.redkale.persistence.Transient
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Transient {}
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies that a unique constraint is to be included in the generated DDL for a primary or secondary table.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
* @Entity
|
||||
* @Table(
|
||||
* name="EMPLOYEE",
|
||||
* uniqueConstraints=
|
||||
* @UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})
|
||||
* )
|
||||
* public class Employee { ... }
|
||||
* </pre>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.UniqueConstraint}
|
||||
* @see org.redkale.persistence.UniqueConstraint
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({})
|
||||
@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 "";
|
||||
|
||||
/**
|
||||
* (Required) An array of the column names that make up the constraint.
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
String[] columnNames();
|
||||
}
|
||||
/**
|
||||
* ***************************************************************************** Copyright (c) 2008 - 2013 Oracle
|
||||
* Corporation. All rights reserved.
|
||||
*
|
||||
* <p>This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. The Eclipse Public License is available
|
||||
* at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* <p>Contributors: Linda DeMichiel - Java Persistence 2.1 Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
* <p>****************************************************************************
|
||||
*/
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies that a unique constraint is to be included in the generated DDL for a primary or secondary table.
|
||||
*
|
||||
* <pre>
|
||||
* Example:
|
||||
* @Entity
|
||||
* @Table(
|
||||
* name="EMPLOYEE",
|
||||
* uniqueConstraints=
|
||||
* @UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})
|
||||
* )
|
||||
* public class Employee { ... }
|
||||
* </pre>
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
* @deprecated replace by {@link org.redkale.persistence.UniqueConstraint}
|
||||
* @see org.redkale.persistence.UniqueConstraint
|
||||
*/
|
||||
@Deprecated(since = "2.8.0")
|
||||
@Target({})
|
||||
@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 "";
|
||||
|
||||
/**
|
||||
* (Required) An array of the column names that make up the constraint.
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
String[] columnNames();
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
/**
|
||||
* see: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
module org.redkale {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* see: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
module org.redkale {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自动加载。 使用场景: 1、被标记为@AutoLoad(false)的Service类不会被自动加载, 当被依赖时才会被加载 2、被标记为@AutoLoad(false)的Servlet类不会被自动加载
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface AutoLoad {
|
||||
|
||||
boolean value() default true;
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自动加载。 使用场景: 1、被标记为@AutoLoad(false)的Service类不会被自动加载, 当被依赖时才会被加载 2、被标记为@AutoLoad(false)的Servlet类不会被自动加载
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface AutoLoad {
|
||||
|
||||
boolean value() default true;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记参数bean
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Bean {}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记参数bean
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Bean {}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 被标记的元素表示会被动态字节码调用
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE, METHOD, FIELD})
|
||||
@Retention(SOURCE)
|
||||
public @interface ClassDepends {
|
||||
|
||||
Class[] value() default {};
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 被标记的元素表示会被动态字节码调用
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE, METHOD, FIELD})
|
||||
@Retention(SOURCE)
|
||||
public @interface ClassDepends {
|
||||
|
||||
Class[] value() default {};
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 接收命令的标记, 只能标记在本地模式下Service里参数为(String)或(String, String[])的public方法上
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.1.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Command {
|
||||
|
||||
/**
|
||||
* 命令号,没有指定值则接收所有的命令
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* 参数帮助说明,在value不为空命令redkale --help时显示
|
||||
*
|
||||
* @return String
|
||||
* @since 2.7.0
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 接收命令的标记, 只能标记在本地模式下Service里参数为(String)或(String, String[])的public方法上
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.1.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Command {
|
||||
|
||||
/**
|
||||
* 命令号,没有指定值则接收所有的命令
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* 参数帮助说明,在value不为空命令redkale --help时显示
|
||||
*
|
||||
* @return String
|
||||
* @since 2.7.0
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记注释,备注
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE, METHOD, FIELD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, TYPE_PARAMETER})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Comment {
|
||||
|
||||
String name() default "";
|
||||
|
||||
String value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记注释,备注
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE, METHOD, FIELD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, TYPE_PARAMETER})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Comment {
|
||||
|
||||
String name() default "";
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记Component的Service类特点: <br>
|
||||
* 1、直接构造, 不使用Sncp动态构建对象 <br>
|
||||
* 2、不会生成对应协议的Servlet <br>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Component {}
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记Component的Service类特点: <br>
|
||||
* 1、直接构造, 不使用Sncp动态构建对象 <br>
|
||||
* 2、不会生成对应协议的Servlet <br>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Component {}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 类似java.beans.ConstructorProperties, 必须配合Creator使用
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD, CONSTRUCTOR})
|
||||
@Retention(RUNTIME)
|
||||
@ClassDepends
|
||||
public @interface ConstructorParameters {
|
||||
|
||||
String[] value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 类似java.beans.ConstructorProperties, 必须配合Creator使用
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD, CONSTRUCTOR})
|
||||
@Retention(RUNTIME)
|
||||
@ClassDepends
|
||||
public @interface ConstructorParameters {
|
||||
|
||||
String[] value();
|
||||
}
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 等于level日志级别且包含keys字符串的日志才会被排除 <br>
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* @LogExcludeLevel(levels = {"FINEST"}, keys = {"SET username ="})
|
||||
* public class UserRecord {
|
||||
* public int userid;
|
||||
* public String username = "";
|
||||
* }
|
||||
*
|
||||
* 这样当调用DataSource对UserRecord对象进行操作时,拼接的SQL语句含"SET username ="字样的都会在FINEST日志级别过滤掉
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(LogExcludeLevel.LogExcludeLevels.class)
|
||||
public @interface LogExcludeLevel {
|
||||
|
||||
String[] levels();
|
||||
|
||||
String[] keys();
|
||||
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface LogExcludeLevels {
|
||||
|
||||
LogExcludeLevel[] value();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 等于level日志级别且包含keys字符串的日志才会被排除 <br>
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* @LogExcludeLevel(levels = {"FINEST"}, keys = {"SET username ="})
|
||||
* public class UserRecord {
|
||||
* public int userid;
|
||||
* public String username = "";
|
||||
* }
|
||||
*
|
||||
* 这样当调用DataSource对UserRecord对象进行操作时,拼接的SQL语句含"SET username ="字样的都会在FINEST日志级别过滤掉
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(LogExcludeLevel.LogExcludeLevels.class)
|
||||
public @interface LogExcludeLevel {
|
||||
|
||||
String[] levels();
|
||||
|
||||
String[] keys();
|
||||
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface LogExcludeLevels {
|
||||
|
||||
LogExcludeLevel[] value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 被标记的日志级别以上的才会被记录
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface LogLevel {
|
||||
|
||||
String value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 被标记的日志级别以上的才会被记录
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface LogLevel {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 非阻塞模式标记, 标记在Service类和方法、Filter类、HttpServlet类上 <br>
|
||||
* 一般情况下,没有显注此注解的方法视为阻塞时, 以下两种情况除外: <br>
|
||||
* 1、返回类型是CompletionStage <br>
|
||||
* 2、返回类型是void且参数存在CompletionHandler类型 <br>
|
||||
* 阻塞模式的方法会在work线程池中运行, 非阻塞在IO线程中运行。
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NonBlocking { // 不可使用@Inherited,防止被继承, 见HttpServlet.preExecute/authenticate/execute
|
||||
|
||||
boolean value() default true;
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 非阻塞模式标记, 标记在Service类和方法、Filter类、HttpServlet类上 <br>
|
||||
* 一般情况下,没有显注此注解的方法视为阻塞时, 以下两种情况除外: <br>
|
||||
* 1、返回类型是CompletionStage <br>
|
||||
* 2、返回类型是void且参数存在CompletionHandler类型 <br>
|
||||
* 阻塞模式的方法会在work线程池中运行, 非阻塞在IO线程中运行。
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NonBlocking { // 不可使用@Inherited,防止被继承, 见HttpServlet.preExecute/authenticate/execute
|
||||
|
||||
boolean value() default true;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记值可以为null
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nonnull {}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记值可以为null
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nonnull {}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记值可以为null
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nullable {}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记值可以为null
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 参数名注解,编译时加上 <b>-parameters</b> 参数可以不用此注解
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({PARAMETER})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Param {
|
||||
|
||||
String value();
|
||||
|
||||
String comment() default "";
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 参数名注解,编译时加上 <b>-parameters</b> 参数可以不用此注解
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({PARAMETER})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Param {
|
||||
|
||||
String value();
|
||||
|
||||
String comment() default "";
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface PostConstruct {}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface PostConstruct {}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface PreDestroy {}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @since Common Annotations 1.0
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface PreDestroy {}
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 值越大,优先级越高
|
||||
*
|
||||
* @since Common Annotations 1.2
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Priority {
|
||||
|
||||
/** 最高优先级, 其他值必须比此值小 */
|
||||
public static final int HIGHTEST = Integer.MAX_VALUE;
|
||||
|
||||
/** 最低优先级, 其他值必须比此值大 */
|
||||
public static final int LOWEST = Integer.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* 优先级值
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 值越大,优先级越高
|
||||
*
|
||||
* @since Common Annotations 1.2
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Priority {
|
||||
|
||||
/** 最高优先级, 其他值必须比此值小 */
|
||||
public static final int HIGHTEST = Integer.MAX_VALUE;
|
||||
|
||||
/** 最低优先级, 其他值必须比此值大 */
|
||||
public static final int LOWEST = Integer.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* 优先级值
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @Resource(name = "@") 表示资源name采用所属对象的name <br>
|
||||
* @Resource(name = "#name") 表示资源对象自身的name <br>
|
||||
* @Resource(name = "#type") 表示资源对象自身的类型 <br>
|
||||
*
|
||||
* @since Common Annotations 1.0
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Resource {
|
||||
|
||||
public static final String PARENT_NAME = "@";
|
||||
|
||||
public static final String SELF_NAME = "#name";
|
||||
|
||||
public static final String SELF_TYPE = "#type";
|
||||
|
||||
/**
|
||||
* 是否必须存在
|
||||
*
|
||||
* @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 "";
|
||||
|
||||
/**
|
||||
* 依赖注入的类型
|
||||
*
|
||||
* @return Class
|
||||
*/
|
||||
public Class<?> type() default Object.class;
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @Resource(name = "@") 表示资源name采用所属对象的name <br>
|
||||
* @Resource(name = "#name") 表示资源对象自身的name <br>
|
||||
* @Resource(name = "#type") 表示资源对象自身的类型 <br>
|
||||
*
|
||||
* @since Common Annotations 1.0
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Resource {
|
||||
|
||||
public static final String PARENT_NAME = "@";
|
||||
|
||||
public static final String SELF_NAME = "#name";
|
||||
|
||||
public static final String SELF_TYPE = "#type";
|
||||
|
||||
/**
|
||||
* 是否必须存在
|
||||
*
|
||||
* @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 "";
|
||||
|
||||
/**
|
||||
* 依赖注入的类型
|
||||
*
|
||||
* @return Class
|
||||
*/
|
||||
public Class<?> type() default Object.class;
|
||||
}
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上 <br>
|
||||
* 注意: 一个类只能存在一个@ResourceChanged的方法, 多余的会被忽略 <br>
|
||||
* 方法在资源被更新以后调用。
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* public class RecordService implements Service {
|
||||
*
|
||||
* @Resource(name = "record.id")
|
||||
* private int id;
|
||||
*
|
||||
* @Resource(name = "record.name")
|
||||
* private String name;
|
||||
*
|
||||
* @ResourceChanged
|
||||
* private void changeResource(ResourceEvent[] events) {
|
||||
* for(ResourceEvent event : events) {
|
||||
* System.out .println("@Resource = " + event.name() + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* ResourceFactory factory = ResourceFactory.create();
|
||||
* factory.register("record.id", "2345");
|
||||
* factory.register("record.name", "my old name");
|
||||
* Record record = new Record();
|
||||
* factory.inject(record);
|
||||
* factory.register("record.name", "my new name");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ResourceChanged {
|
||||
|
||||
/**
|
||||
* 新旧值是否不同时才回调方法 <br>
|
||||
* true: 新值与旧值不同时才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @return boolean
|
||||
*/
|
||||
boolean different() default true;
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上 <br>
|
||||
* 注意: 一个类只能存在一个@ResourceChanged的方法, 多余的会被忽略 <br>
|
||||
* 方法在资源被更新以后调用。
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* public class RecordService implements Service {
|
||||
*
|
||||
* @Resource(name = "record.id")
|
||||
* private int id;
|
||||
*
|
||||
* @Resource(name = "record.name")
|
||||
* private String name;
|
||||
*
|
||||
* @ResourceChanged
|
||||
* private void changeResource(ResourceEvent[] events) {
|
||||
* for(ResourceEvent event : events) {
|
||||
* System.out .println("@Resource = " + event.name() + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* ResourceFactory factory = ResourceFactory.create();
|
||||
* factory.register("record.id", "2345");
|
||||
* factory.register("record.name", "my old name");
|
||||
* Record record = new Record();
|
||||
* factory.inject(record);
|
||||
* factory.register("record.name", "my new name");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ResourceChanged {
|
||||
|
||||
/**
|
||||
* 新旧值是否不同时才回调方法 <br>
|
||||
* true: 新值与旧值不同时才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @return boolean
|
||||
*/
|
||||
boolean different() default true;
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @Resource资源被依赖注入时的监听事件。<br>
|
||||
* 本注解只能标记在空参数或者(String、Object、java.lang.reflect.Field)三个参数类型的任意组合方法上 <br>
|
||||
* 方法在资源被依赖注入后调用。
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* public class ResourceService implements Service {
|
||||
*
|
||||
* @Resource(name = "res.id")
|
||||
* private int id;
|
||||
*
|
||||
* @Resource(name = "res.name")
|
||||
* private String name;
|
||||
*
|
||||
* @ResourceInjected
|
||||
* private void onInjected(Object src, String fieldName) {
|
||||
* System.out .println("资源被注入到对象(" + src + ")的字段(" + fieldName + ")上");
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public class RecordService implements Service {
|
||||
*
|
||||
* @Resource
|
||||
* private ResourceService resService;
|
||||
*
|
||||
* public void test() {
|
||||
* }
|
||||
*
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* ResourceFactory factory = ResourceFactory.create();
|
||||
* factory.register("res.id", "2345");
|
||||
* factory.register("res.name", "my old name");
|
||||
* ResourceService res = new ResourceService();
|
||||
* factory.inject(res);
|
||||
* factory.register("", res);
|
||||
* RecordService serice = new RecordService();
|
||||
* factory.inject(record);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ResourceInjected {}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @Resource资源被依赖注入时的监听事件。<br>
|
||||
* 本注解只能标记在空参数或者(String、Object、java.lang.reflect.Field)三个参数类型的任意组合方法上 <br>
|
||||
* 方法在资源被依赖注入后调用。
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* public class ResourceService implements Service {
|
||||
*
|
||||
* @Resource(name = "res.id")
|
||||
* private int id;
|
||||
*
|
||||
* @Resource(name = "res.name")
|
||||
* private String name;
|
||||
*
|
||||
* @ResourceInjected
|
||||
* private void onInjected(Object src, String fieldName) {
|
||||
* System.out .println("资源被注入到对象(" + src + ")的字段(" + fieldName + ")上");
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public class RecordService implements Service {
|
||||
*
|
||||
* @Resource
|
||||
* private ResourceService resService;
|
||||
*
|
||||
* public void test() {
|
||||
* }
|
||||
*
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* ResourceFactory factory = ResourceFactory.create();
|
||||
* factory.register("res.id", "2345");
|
||||
* factory.register("res.name", "my old name");
|
||||
* ResourceService res = new ResourceService();
|
||||
* factory.inject(res);
|
||||
* factory.register("", res);
|
||||
* RecordService serice = new RecordService();
|
||||
* factory.inject(record);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ResourceInjected {}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 显式的指明资源类型。 调用ResourceFactory.register(Object rs)时通常执行的是ResourceFactory.register(rs.getClass(), Object rs);
|
||||
* 若rs.getClass()的类标记了@ResourceType, 则使用@ResourceType.value()的class值进行注入。
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ResourceType {
|
||||
|
||||
Class value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.annotation;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 显式的指明资源类型。 调用ResourceFactory.register(Object rs)时通常执行的是ResourceFactory.register(rs.getClass(), Object rs);
|
||||
* 若rs.getClass()的类标记了@ResourceType, 则使用@ResourceType.value()的class值进行注入。
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface ResourceType {
|
||||
|
||||
Class value();
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/** 提供基础注解包 */
|
||||
package org.redkale.annotation;
|
||||
/** 提供基础注解包 */
|
||||
package org.redkale.annotation;
|
||||
|
||||
@@ -1,170 +1,170 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java annotation. The methods of this class must be called in the following order: (
|
||||
* <tt>visit</tt> | <tt>visitEnum</tt> | <tt>visitAnnotation</tt> |
|
||||
* <tt>visitArray</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
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 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}.
|
||||
* @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 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 <tt>null</tt> 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 <tt>null</tt> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java annotation. The methods of this class must be called in the following order: (
|
||||
* <tt>visit</tt> | <tt>visitEnum</tt> | <tt>visitAnnotation</tt> |
|
||||
* <tt>visitArray</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
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 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}.
|
||||
* @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 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 <tt>null</tt> 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 <tt>null</tt> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,366 +1,366 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* An {@link AnnotationVisitor} that generates annotations in bytecode form.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
final class AnnotationWriter extends AnnotationVisitor {
|
||||
|
||||
/** The class writer to which this annotation must be added. */
|
||||
private final ClassWriter cw;
|
||||
|
||||
/** The number of values in this annotation. */
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* <tt>true<tt> if values are named, <tt>false</tt> 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 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationWriter}.
|
||||
*
|
||||
* @param cw the class writer to which this annotation must be added.
|
||||
* @param named <tt>true<tt> if values are named, <tt>false</tt> 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 <tt>parent</tt> 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
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@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 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 void visitEnd() {
|
||||
if (parent != null) {
|
||||
byte[] data = parent.data;
|
||||
data[offset] = (byte) (size >>> 8);
|
||||
data[offset + 1] = (byte) size;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 <tt>null</tt> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* An {@link AnnotationVisitor} that generates annotations in bytecode form.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
final class AnnotationWriter extends AnnotationVisitor {
|
||||
|
||||
/** The class writer to which this annotation must be added. */
|
||||
private final ClassWriter cw;
|
||||
|
||||
/** The number of values in this annotation. */
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* <tt>true<tt> if values are named, <tt>false</tt> 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 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationWriter}.
|
||||
*
|
||||
* @param cw the class writer to which this annotation must be added.
|
||||
* @param named <tt>true<tt> if values are named, <tt>false</tt> 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 <tt>parent</tt> 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
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@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 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 void visitEnd() {
|
||||
if (parent != null) {
|
||||
byte[] data = parent.data;
|
||||
data[offset] = (byte) (size >>> 8);
|
||||
data[offset + 1] = (byte) size;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 <tt>null</tt> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +1,140 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
* 存放方法的字节信息
|
||||
*
|
||||
* @see org.redkale.asm.AsmMethodBoost
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public class AsmMethodBean {
|
||||
|
||||
private List<AsmMethodParam> params;
|
||||
|
||||
private int access;
|
||||
|
||||
private String name;
|
||||
|
||||
private String desc;
|
||||
|
||||
private String signature;
|
||||
|
||||
private String[] exceptions;
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 List<AsmMethodParam> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(List<AsmMethodParam> params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public int getAccess() {
|
||||
return access;
|
||||
}
|
||||
|
||||
public void setAccess(int access) {
|
||||
this.access = access;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public String[] getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
public void setExceptions(String[] exceptions) {
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
* 存放方法的字节信息
|
||||
*
|
||||
* @see org.redkale.asm.AsmMethodBoost
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public class AsmMethodBean {
|
||||
|
||||
private List<AsmMethodParam> params;
|
||||
|
||||
private int access;
|
||||
|
||||
private String name;
|
||||
|
||||
private String desc;
|
||||
|
||||
private String signature;
|
||||
|
||||
private String[] exceptions;
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 List<AsmMethodParam> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(List<AsmMethodParam> params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public int getAccess() {
|
||||
return access;
|
||||
}
|
||||
|
||||
public void setAccess(int access) {
|
||||
this.access = access;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public String[] getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
public void setExceptions(String[] exceptions) {
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,409 +1,409 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import static org.redkale.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.redkale.asm.Opcodes.ACC_PROTECTED;
|
||||
import static org.redkale.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.redkale.asm.Opcodes.ALOAD;
|
||||
import static org.redkale.asm.Opcodes.ARETURN;
|
||||
import static org.redkale.asm.Opcodes.DLOAD;
|
||||
import static org.redkale.asm.Opcodes.DRETURN;
|
||||
import static org.redkale.asm.Opcodes.FLOAD;
|
||||
import static org.redkale.asm.Opcodes.FRETURN;
|
||||
import static org.redkale.asm.Opcodes.ILOAD;
|
||||
import static org.redkale.asm.Opcodes.IRETURN;
|
||||
import static org.redkale.asm.Opcodes.LLOAD;
|
||||
import static org.redkale.asm.Opcodes.LRETURN;
|
||||
import static org.redkale.asm.Opcodes.RETURN;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.annotation.Nullable;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
|
||||
*
|
||||
* @param <T> 泛型
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public abstract class AsmMethodBoost<T> {
|
||||
|
||||
protected final AtomicInteger fieldIndex = new AtomicInteger();
|
||||
|
||||
protected final boolean remote;
|
||||
|
||||
protected final Class 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, 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;
|
||||
}
|
||||
|
||||
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 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 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 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 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[] 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 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 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> {
|
||||
|
||||
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, 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 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 doInstance(ResourceFactory resourceFactory, T service) {
|
||||
for (AsmMethodBoost item : items) {
|
||||
if (item != null) {
|
||||
item.doInstance(resourceFactory, service);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MethodParamClassVisitor extends ClassVisitor {
|
||||
|
||||
private Class serviceType;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 返回的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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import static org.redkale.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.redkale.asm.Opcodes.ACC_PROTECTED;
|
||||
import static org.redkale.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.redkale.asm.Opcodes.ALOAD;
|
||||
import static org.redkale.asm.Opcodes.ARETURN;
|
||||
import static org.redkale.asm.Opcodes.DLOAD;
|
||||
import static org.redkale.asm.Opcodes.DRETURN;
|
||||
import static org.redkale.asm.Opcodes.FLOAD;
|
||||
import static org.redkale.asm.Opcodes.FRETURN;
|
||||
import static org.redkale.asm.Opcodes.ILOAD;
|
||||
import static org.redkale.asm.Opcodes.IRETURN;
|
||||
import static org.redkale.asm.Opcodes.LLOAD;
|
||||
import static org.redkale.asm.Opcodes.LRETURN;
|
||||
import static org.redkale.asm.Opcodes.RETURN;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.annotation.Nullable;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
|
||||
*
|
||||
* @param <T> 泛型
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public abstract class AsmMethodBoost<T> {
|
||||
|
||||
protected final AtomicInteger fieldIndex = new AtomicInteger();
|
||||
|
||||
protected final boolean remote;
|
||||
|
||||
protected final Class 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, 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;
|
||||
}
|
||||
|
||||
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 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 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 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 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[] 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 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 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> {
|
||||
|
||||
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, 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 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 doInstance(ResourceFactory resourceFactory, T service) {
|
||||
for (AsmMethodBoost item : items) {
|
||||
if (item != null) {
|
||||
item.doInstance(resourceFactory, service);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MethodParamClassVisitor extends ClassVisitor {
|
||||
|
||||
private Class serviceType;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 返回的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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.util.TypeToken;
|
||||
|
||||
/**
|
||||
* 存放方法参数的字节信息
|
||||
*
|
||||
* @see org.redkale.asm.AsmMethodBean
|
||||
* @see org.redkale.asm.AsmMethodBoost
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public class AsmMethodParam {
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private String signature;
|
||||
|
||||
public AsmMethodParam() {}
|
||||
|
||||
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 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 getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.util.TypeToken;
|
||||
|
||||
/**
|
||||
* 存放方法参数的字节信息
|
||||
*
|
||||
* @see org.redkale.asm.AsmMethodBean
|
||||
* @see org.redkale.asm.AsmMethodBoost
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public class AsmMethodParam {
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private String signature;
|
||||
|
||||
public AsmMethodParam() {}
|
||||
|
||||
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 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 getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,197 +1,197 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import static org.redkale.asm.Opcodes.BIPUSH;
|
||||
import static org.redkale.asm.Opcodes.CHECKCAST;
|
||||
import static org.redkale.asm.Opcodes.GETSTATIC;
|
||||
import static org.redkale.asm.Opcodes.ICONST_0;
|
||||
import static org.redkale.asm.Opcodes.INVOKESTATIC;
|
||||
import static org.redkale.asm.Opcodes.INVOKEVIRTUAL;
|
||||
import static org.redkale.asm.Opcodes.SIPUSH;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/**
|
||||
* ASM简单的工具方法 <br>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public final class 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 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 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import static org.redkale.asm.Opcodes.BIPUSH;
|
||||
import static org.redkale.asm.Opcodes.CHECKCAST;
|
||||
import static org.redkale.asm.Opcodes.GETSTATIC;
|
||||
import static org.redkale.asm.Opcodes.ICONST_0;
|
||||
import static org.redkale.asm.Opcodes.INVOKESTATIC;
|
||||
import static org.redkale.asm.Opcodes.INVOKEVIRTUAL;
|
||||
import static org.redkale.asm.Opcodes.SIPUSH;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/**
|
||||
* ASM简单的工具方法 <br>
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public final class 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 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 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,312 +1,312 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A non standard class, field, method or code attribute.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class Attribute {
|
||||
|
||||
/** The type of this attribute. */
|
||||
public final String type;
|
||||
|
||||
/** The raw value of this attribute, used only for unknown attributes. */
|
||||
byte[] value;
|
||||
|
||||
/** The next attribute in this attribute list. May be <tt>null</tt>. */
|
||||
Attribute next;
|
||||
|
||||
/**
|
||||
* Constructs a new empty attribute.
|
||||
*
|
||||
* @param type the type of the attribute.
|
||||
*/
|
||||
protected Attribute(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this type of attribute is unknown. The default implementation of this
|
||||
* method always returns <tt>true</tt>.
|
||||
*
|
||||
* @return <tt>true</tt> if this type of attribute is unknown.
|
||||
*/
|
||||
public boolean isUnknown() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this type of attribute is a code attribute.
|
||||
*
|
||||
* @return <tt>true</tt> 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 <tt>null</tt> 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 <tt>len</tt> 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 <tt>null</tt> 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 <tt>null</tt> if
|
||||
* this attribute is not a code attributes.
|
||||
* @param len the length of the bytecode of the method corresponding to this code attribute, or
|
||||
* <tt>null</tt> 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 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 <tt>null</tt>
|
||||
* if these attributes are not code attributes.
|
||||
* @param len the length of the bytecode of the method corresponding to these code attributes, or
|
||||
* <tt>null</tt> 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 <tt>null</tt>
|
||||
* if these attributes are not code attributes.
|
||||
* @param len the length of the bytecode of the method corresponding to these code attributes, or
|
||||
* <tt>null</tt> 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");
|
||||
}
|
||||
|
||||
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 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 {
|
||||
|
||||
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 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()};
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A non standard class, field, method or code attribute.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class Attribute {
|
||||
|
||||
/** The type of this attribute. */
|
||||
public final String type;
|
||||
|
||||
/** The raw value of this attribute, used only for unknown attributes. */
|
||||
byte[] value;
|
||||
|
||||
/** The next attribute in this attribute list. May be <tt>null</tt>. */
|
||||
Attribute next;
|
||||
|
||||
/**
|
||||
* Constructs a new empty attribute.
|
||||
*
|
||||
* @param type the type of the attribute.
|
||||
*/
|
||||
protected Attribute(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this type of attribute is unknown. The default implementation of this
|
||||
* method always returns <tt>true</tt>.
|
||||
*
|
||||
* @return <tt>true</tt> if this type of attribute is unknown.
|
||||
*/
|
||||
public boolean isUnknown() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this type of attribute is a code attribute.
|
||||
*
|
||||
* @return <tt>true</tt> 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 <tt>null</tt> 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 <tt>len</tt> 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 <tt>null</tt> 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 <tt>null</tt> if
|
||||
* this attribute is not a code attributes.
|
||||
* @param len the length of the bytecode of the method corresponding to this code attribute, or
|
||||
* <tt>null</tt> 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 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 <tt>null</tt>
|
||||
* if these attributes are not code attributes.
|
||||
* @param len the length of the bytecode of the method corresponding to these code attributes, or
|
||||
* <tt>null</tt> 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 <tt>null</tt>
|
||||
* if these attributes are not code attributes.
|
||||
* @param len the length of the bytecode of the method corresponding to these code attributes, or
|
||||
* <tt>null</tt> 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");
|
||||
}
|
||||
|
||||
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 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 {
|
||||
|
||||
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 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()};
|
||||
}
|
||||
|
||||
@@ -1,331 +1,331 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream on top of a
|
||||
* ByteArrayOutputStream, but is more efficient.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class ByteVector {
|
||||
|
||||
/** The content of this vector. */
|
||||
byte[] data;
|
||||
|
||||
/** 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 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 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 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 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. 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 <tt>null</tt> to put <tt>len</tt> 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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream on top of a
|
||||
* ByteArrayOutputStream, but is more efficient.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class ByteVector {
|
||||
|
||||
/** The content of this vector. */
|
||||
byte[] data;
|
||||
|
||||
/** 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 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 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 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 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. 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 <tt>null</tt> to put <tt>len</tt> 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;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,292 +1,292 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java class. The methods of this class must be called in the following order:
|
||||
* <tt>visit</tt> [ <tt>visitSource</tt> ] [ <tt>visitModule</tt> ][
|
||||
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
||||
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt>
|
||||
* )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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}.
|
||||
* @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 <tt>null</tt> 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 <tt>null</tt>, but only for the
|
||||
* {@link Object} class.
|
||||
* @param interfaces the internal names of the class's interfaces (see {@link Type#getInternalName()
|
||||
* getInternalName}). May be <tt>null</tt>.
|
||||
*/
|
||||
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
|
||||
* <tt>null</tt>.
|
||||
* @param debug additional debug information to compute the correspondance between source and compiled elements of
|
||||
* the class. May be <tt>null</tt>.
|
||||
*/
|
||||
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 <tt>null</tt> 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 <tt>null</tt> 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 <tt>null</tt> 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 <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc the class descriptor of the annotation class.
|
||||
* @param visible <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 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 <tt>null</tt> for not member classes.
|
||||
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
|
||||
* <tt>null</tt> 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 <tt>null</tt> if the field's type does not use
|
||||
* generic types.
|
||||
* @param value the field's initial value. This parameter, which may be <tt>null</tt> 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 <tt>int</tt>, <tt>float</tt>,
|
||||
* <tt>long</tt> or <tt>String</tt> 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 <tt>null</tt> 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
|
||||
* <tt>null</tt>) 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 <tt>null</tt> 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 <tt>null</tt>.
|
||||
* @return an object to visit the byte code of the method, or <tt>null</tt> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java class. The methods of this class must be called in the following order:
|
||||
* <tt>visit</tt> [ <tt>visitSource</tt> ] [ <tt>visitModule</tt> ][
|
||||
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
||||
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt>
|
||||
* )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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}.
|
||||
* @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 <tt>null</tt> 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 <tt>null</tt>, but only for the
|
||||
* {@link Object} class.
|
||||
* @param interfaces the internal names of the class's interfaces (see {@link Type#getInternalName()
|
||||
* getInternalName}). May be <tt>null</tt>.
|
||||
*/
|
||||
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
|
||||
* <tt>null</tt>.
|
||||
* @param debug additional debug information to compute the correspondance between source and compiled elements of
|
||||
* the class. May be <tt>null</tt>.
|
||||
*/
|
||||
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 <tt>null</tt> 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 <tt>null</tt> 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 <tt>null</tt> 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 <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc the class descriptor of the annotation class.
|
||||
* @param visible <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 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 <tt>null</tt> for not member classes.
|
||||
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
|
||||
* <tt>null</tt> 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 <tt>null</tt> if the field's type does not use
|
||||
* generic types.
|
||||
* @param value the field's initial value. This parameter, which may be <tt>null</tt> 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 <tt>int</tt>, <tt>float</tt>,
|
||||
* <tt>long</tt> or <tt>String</tt> 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 <tt>null</tt> 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
|
||||
* <tt>null</tt>) 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 <tt>null</tt> 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 <tt>null</tt>.
|
||||
* @return an object to visit the byte code of the method, or <tt>null</tt> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,143 +1,143 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Information about a class being parsed in a {@link ClassReader}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Context {
|
||||
|
||||
/** 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 buffer used to read strings. */
|
||||
char[] buffer;
|
||||
|
||||
/** The start index of each bootstrap method. */
|
||||
int[] bootstrapMethods;
|
||||
|
||||
/** The access flags of the method currently being parsed. */
|
||||
int access;
|
||||
|
||||
/** The name of the method currently being parsed. */
|
||||
String name;
|
||||
|
||||
/** 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 target of the type annotation currently being parsed. */
|
||||
int typeRef;
|
||||
|
||||
/** 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 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 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 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 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 values of the latest stack map frame that has been parsed. */
|
||||
Object[] stack;
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Information about a class being parsed in a {@link ClassReader}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Context {
|
||||
|
||||
/** 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 buffer used to read strings. */
|
||||
char[] buffer;
|
||||
|
||||
/** The start index of each bootstrap method. */
|
||||
int[] bootstrapMethods;
|
||||
|
||||
/** The access flags of the method currently being parsed. */
|
||||
int access;
|
||||
|
||||
/** The name of the method currently being parsed. */
|
||||
String name;
|
||||
|
||||
/** 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 target of the type annotation currently being parsed. */
|
||||
int typeRef;
|
||||
|
||||
/** 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 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 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 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 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 values of the latest stack map frame that has been parsed. */
|
||||
Object[] stack;
|
||||
}
|
||||
|
||||
@@ -1,83 +1,83 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Information about the input stack map frame at the "current" instruction of a method. This is implemented as a Frame
|
||||
* subclass for a "basic block" containing only one instruction.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Information about the input stack map frame at the "current" instruction of a method. This is implemented as a Frame
|
||||
* subclass for a "basic block" containing only one instruction.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,94 +1,94 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* An edge in the control flow graph of a method body. See {@link Label Label}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Edge {
|
||||
|
||||
/** 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;
|
||||
|
||||
/**
|
||||
* 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 next edge in the list of successors of the originating basic block. See {@link Label#successors successors}.
|
||||
*/
|
||||
Edge next;
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* An edge in the control flow graph of a method body. See {@link Label Label}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Edge {
|
||||
|
||||
/** 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;
|
||||
|
||||
/**
|
||||
* 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 next edge in the list of successors of the originating basic block. See {@link Label#successors successors}.
|
||||
*/
|
||||
Edge next;
|
||||
}
|
||||
|
||||
@@ -1,155 +1,155 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java field. The methods of this class must be called in the following order: (
|
||||
* <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> |
|
||||
* <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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}.
|
||||
* @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 <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc the class descriptor of the annotation class.
|
||||
* @param visible <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java field. The methods of this class must be called in the following order: (
|
||||
* <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> |
|
||||
* <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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}.
|
||||
* @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 <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc the class descriptor of the annotation class.
|
||||
* @param visible <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> 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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,320 +1,320 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* An {@link FieldVisitor} that generates Java fields in bytecode form.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class FieldWriter extends FieldVisitor {
|
||||
|
||||
/** The class writer to which this field must be added. */
|
||||
private final ClassWriter cw;
|
||||
|
||||
/** 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 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 constant value of this field. */
|
||||
private int value;
|
||||
|
||||
/** The runtime visible annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter anns;
|
||||
|
||||
/** The runtime invisible annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter ianns;
|
||||
|
||||
/** The runtime visible type annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter tanns;
|
||||
|
||||
/** The runtime invisible type annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter itanns;
|
||||
|
||||
/** The non standard attributes of this field. May be <tt>null</tt>. */
|
||||
private Attribute attrs;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 <tt>null</tt>.
|
||||
* @param value the field's constant value. May be <tt>null</tt>.
|
||||
*/
|
||||
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
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@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 void visitAttribute(final Attribute attr) {
|
||||
attr.next = attrs;
|
||||
attrs = attr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* An {@link FieldVisitor} that generates Java fields in bytecode form.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class FieldWriter extends FieldVisitor {
|
||||
|
||||
/** The class writer to which this field must be added. */
|
||||
private final ClassWriter cw;
|
||||
|
||||
/** 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 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 constant value of this field. */
|
||||
private int value;
|
||||
|
||||
/** The runtime visible annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter anns;
|
||||
|
||||
/** The runtime invisible annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter ianns;
|
||||
|
||||
/** The runtime visible type annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter tanns;
|
||||
|
||||
/** The runtime invisible type annotations of this field. May be <tt>null</tt>. */
|
||||
private AnnotationWriter itanns;
|
||||
|
||||
/** The non standard attributes of this field. May be <tt>null</tt>. */
|
||||
private Attribute attrs;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 <tt>null</tt>.
|
||||
* @param value the field's constant value. May be <tt>null</tt>.
|
||||
*/
|
||||
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
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@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 void visitAttribute(final Attribute attr) {
|
||||
attr.next = attrs;
|
||||
attrs = attr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
@@ -1,190 +1,190 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A reference to a field or a method.
|
||||
*
|
||||
* @author Remi Forax
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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 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;
|
||||
|
||||
/**
|
||||
* 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 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 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;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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" : "") + ')';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A reference to a field or a method.
|
||||
*
|
||||
* @author Remi Forax
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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 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;
|
||||
|
||||
/**
|
||||
* 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 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 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;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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" : "") + ')';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,138 +1,138 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Information about an exception handler block.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Handler {
|
||||
|
||||
/** Beginning of the exception handler's scope (inclusive). */
|
||||
Label start;
|
||||
|
||||
/** End of the exception handler's scope (exclusive). */
|
||||
Label end;
|
||||
|
||||
/** Beginning of the exception handler's code. */
|
||||
Label handler;
|
||||
|
||||
/**
|
||||
* Internal name of the type of exceptions handled by this handler, or <tt>null</tt> 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;
|
||||
|
||||
/** 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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Information about an exception handler block.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Handler {
|
||||
|
||||
/** Beginning of the exception handler's scope (inclusive). */
|
||||
Label start;
|
||||
|
||||
/** End of the exception handler's scope (exclusive). */
|
||||
Label end;
|
||||
|
||||
/** Beginning of the exception handler's code. */
|
||||
Label handler;
|
||||
|
||||
/**
|
||||
* Internal name of the type of exceptions handled by this handler, or <tt>null</tt> 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;
|
||||
|
||||
/** 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,289 +1,289 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A constant pool item. Constant pool items can be created with the 'newXXX' methods in the {@link ClassWriter} class.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class Item {
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Value of this item, for an integer item. */
|
||||
int intVal;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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 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 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 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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <tt>true</tt> if the given item if equal to this one, <tt>false</tt>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A constant pool item. Constant pool items can be created with the 'newXXX' methods in the {@link ClassWriter} class.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class Item {
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Value of this item, for an integer item. */
|
||||
int intVal;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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 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 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 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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <tt>true</tt> if the given item if equal to this one, <tt>false</tt>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,263 +1,263 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* MethodVisitor 的调试类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class MethodDebugVisitor extends MethodVisitor {
|
||||
|
||||
private final MethodVisitor visitor;
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
public MethodDebugVisitor setDebug(boolean d) {
|
||||
debug = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void debugLine() {
|
||||
if (!debug) {
|
||||
return;
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
||||
|
||||
private static final String[] opcodes = new String[200]; // 0 -18
|
||||
|
||||
static {
|
||||
try {
|
||||
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
||||
String name = field.getName();
|
||||
if (name.startsWith("ASM")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("V1_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("ACC_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("T_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("H_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("F_")) {
|
||||
continue;
|
||||
}
|
||||
if (field.getType() != int.class) {
|
||||
continue;
|
||||
}
|
||||
opcodes[(int) (Integer) field.get(null)] = name;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex); // 不可能会发生
|
||||
}
|
||||
}
|
||||
|
||||
/** @param visitor MethodVisitor */
|
||||
public MethodDebugVisitor(MethodVisitor visitor) {
|
||||
super(Opcodes.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 AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
||||
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
||||
}
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
||||
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
||||
}
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
if (debug) {
|
||||
System.out.println(
|
||||
"mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
|
||||
}
|
||||
return av;
|
||||
}
|
||||
|
||||
public void visitParameter(String name, int access) {
|
||||
visitor.visitParameter(name, access);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitVarInsn(int opcode, int var) {
|
||||
visitor.visitVarInsn(opcode, var);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
||||
visitor.visitFrame(type, nLocal, local, nStack, stack);
|
||||
if (debug) {
|
||||
String typestr = "" + type;
|
||||
if (type == -1) {
|
||||
typestr = "Opcodes.F_NEW";
|
||||
} else if (type == 1) {
|
||||
typestr = "Opcodes.F_APPEND";
|
||||
} else if (type == 2) {
|
||||
typestr = "Opcodes.F_CHOP";
|
||||
} else if (type == 3) {
|
||||
typestr = "Opcodes.F_SAME";
|
||||
} else if (type == 4) {
|
||||
typestr = "Opcodes.F_SAME1";
|
||||
}
|
||||
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", "
|
||||
+ nStack + ", " + Arrays.toString(stack) + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitJumpInsn(int opcode, Label var) { // 调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
||||
visitor.visitJumpInsn(opcode, var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCode() {
|
||||
visitor.visitCode();
|
||||
if (debug) {
|
||||
System.out.println("mv.visitCode();");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitLabel(Label var) {
|
||||
visitor.visitLabel(var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitLabel(l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \""
|
||||
+ desc + "\", " + itf + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void 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 visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||
visitor.visitFieldInsn(opcode, owner, name, desc);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \""
|
||||
+ desc + "\");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
visitor.visitTypeInsn(opcode, type);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitInsn(int opcode) {
|
||||
visitor.visitInsn(opcode);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitIntInsn(int opcode, int value) {
|
||||
visitor.visitIntInsn(opcode, value);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitIincInsn(int opcode, int value) {
|
||||
visitor.visitIincInsn(opcode, value);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitLdcInsn(Object o) {
|
||||
visitor.visitLdcInsn(o);
|
||||
if (debug) {
|
||||
if (o instanceof CharSequence) {
|
||||
System.out.println("mv.visitLdcInsn(\"" + o + "\");");
|
||||
} else if (o instanceof org.redkale.asm.Type) {
|
||||
System.out.println("mv.visitLdcInsn(Type.getType(\"" + o + "\"));");
|
||||
} else {
|
||||
System.out.println("mv.visitLdcInsn(" + o + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
visitor.visitMaxs(maxStack, maxLocals);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
visitor.visitEnd();
|
||||
if (debug) {
|
||||
System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* MethodVisitor 的调试类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class MethodDebugVisitor extends MethodVisitor {
|
||||
|
||||
private final MethodVisitor visitor;
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
public MethodDebugVisitor setDebug(boolean d) {
|
||||
debug = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void debugLine() {
|
||||
if (!debug) {
|
||||
return;
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
||||
|
||||
private static final String[] opcodes = new String[200]; // 0 -18
|
||||
|
||||
static {
|
||||
try {
|
||||
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
||||
String name = field.getName();
|
||||
if (name.startsWith("ASM")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("V1_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("ACC_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("T_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("H_")) {
|
||||
continue;
|
||||
}
|
||||
if (name.startsWith("F_")) {
|
||||
continue;
|
||||
}
|
||||
if (field.getType() != int.class) {
|
||||
continue;
|
||||
}
|
||||
opcodes[(int) (Integer) field.get(null)] = name;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex); // 不可能会发生
|
||||
}
|
||||
}
|
||||
|
||||
/** @param visitor MethodVisitor */
|
||||
public MethodDebugVisitor(MethodVisitor visitor) {
|
||||
super(Opcodes.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 AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
||||
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
||||
}
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
||||
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
||||
}
|
||||
return av;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
if (debug) {
|
||||
System.out.println(
|
||||
"mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
|
||||
}
|
||||
return av;
|
||||
}
|
||||
|
||||
public void visitParameter(String name, int access) {
|
||||
visitor.visitParameter(name, access);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitVarInsn(int opcode, int var) {
|
||||
visitor.visitVarInsn(opcode, var);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
||||
visitor.visitFrame(type, nLocal, local, nStack, stack);
|
||||
if (debug) {
|
||||
String typestr = "" + type;
|
||||
if (type == -1) {
|
||||
typestr = "Opcodes.F_NEW";
|
||||
} else if (type == 1) {
|
||||
typestr = "Opcodes.F_APPEND";
|
||||
} else if (type == 2) {
|
||||
typestr = "Opcodes.F_CHOP";
|
||||
} else if (type == 3) {
|
||||
typestr = "Opcodes.F_SAME";
|
||||
} else if (type == 4) {
|
||||
typestr = "Opcodes.F_SAME1";
|
||||
}
|
||||
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", "
|
||||
+ nStack + ", " + Arrays.toString(stack) + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitJumpInsn(int opcode, Label var) { // 调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
||||
visitor.visitJumpInsn(opcode, var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCode() {
|
||||
visitor.visitCode();
|
||||
if (debug) {
|
||||
System.out.println("mv.visitCode();");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitLabel(Label var) {
|
||||
visitor.visitLabel(var);
|
||||
if (debug) {
|
||||
Integer index = labels.get(var);
|
||||
if (index == null) {
|
||||
index = labels.size();
|
||||
labels.put(var, index);
|
||||
System.out.println("Label l" + index + " = new Label();");
|
||||
}
|
||||
System.out.println("mv.visitLabel(l" + index + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \""
|
||||
+ desc + "\", " + itf + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void 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 visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||
visitor.visitFieldInsn(opcode, owner, name, desc);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \""
|
||||
+ desc + "\");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
visitor.visitTypeInsn(opcode, type);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitInsn(int opcode) {
|
||||
visitor.visitInsn(opcode);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitIntInsn(int opcode, int value) {
|
||||
visitor.visitIntInsn(opcode, value);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitIincInsn(int opcode, int value) {
|
||||
visitor.visitIincInsn(opcode, value);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitLdcInsn(Object o) {
|
||||
visitor.visitLdcInsn(o);
|
||||
if (debug) {
|
||||
if (o instanceof CharSequence) {
|
||||
System.out.println("mv.visitLdcInsn(\"" + o + "\");");
|
||||
} else if (o instanceof org.redkale.asm.Type) {
|
||||
System.out.println("mv.visitLdcInsn(Type.getType(\"" + o + "\"));");
|
||||
} else {
|
||||
System.out.println("mv.visitLdcInsn(" + o + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
visitor.visitMaxs(maxStack, maxLocals);
|
||||
if (debug) {
|
||||
System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
visitor.visitEnd();
|
||||
if (debug) {
|
||||
System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,202 +1,202 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java module. The methods of this class must be called in the following order:
|
||||
* <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
|
||||
* <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
|
||||
* <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* <p>The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
|
||||
* {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)} take as parameter a package name or a
|
||||
* module name. Unlike the other names which are internal names (names separated by slash), module and package names are
|
||||
* qualified names (names separated by dot).
|
||||
*
|
||||
* @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 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}.
|
||||
* @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 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <tt>null</tt>.
|
||||
*/
|
||||
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 <tt>null</tt>.
|
||||
*/
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java module. The methods of this class must be called in the following order:
|
||||
* <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
|
||||
* <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
|
||||
* <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* <p>The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
|
||||
* {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)} take as parameter a package name or a
|
||||
* module name. Unlike the other names which are internal names (names separated by slash), module and package names are
|
||||
* qualified names (names separated by dot).
|
||||
*
|
||||
* @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 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}.
|
||||
* @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 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <tt>null</tt>.
|
||||
*/
|
||||
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 <tt>null</tt>.
|
||||
*/
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,288 +1,288 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/** size in byte of the Module attribute. */
|
||||
int size;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** module name index in the constant pool */
|
||||
private final int name;
|
||||
|
||||
/** module access flags */
|
||||
private final int access;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
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 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 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 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 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/** size in byte of the Module attribute. */
|
||||
int size;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** module name index in the constant pool */
|
||||
private final int name;
|
||||
|
||||
/** module access flags */
|
||||
private final int access;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
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 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 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 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 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,402 +1,402 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Defines the JVM opcodes, access flags and array type codes. This interface does not define all the JVM opcodes
|
||||
* because some opcodes are automatically handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
|
||||
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n opcodes are therefore not defined in this
|
||||
* interface. Likewise for LDC, automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and JSR_W.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public interface Opcodes {
|
||||
|
||||
// ASM API versions
|
||||
int ASM4 = 4 << 16 | 0 << 8;
|
||||
int ASM5 = 5 << 16 | 0 << 8;
|
||||
int ASM6 = 6 << 16 | 0 << 8;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
|
||||
// ASM specific pseudo access flags
|
||||
|
||||
int ACC_DEPRECATED = 0x20000; // class, field, method
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// stack map frame types
|
||||
|
||||
/** 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 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 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;
|
||||
|
||||
// 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 FLOAT = new Integer(2);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer DOUBLE = new Integer(3);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer LONG = new Integer(4);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer NULL = new Integer(5);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer UNINITIALIZED_THIS = new Integer(6);
|
||||
|
||||
// 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; // -
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* Defines the JVM opcodes, access flags and array type codes. This interface does not define all the JVM opcodes
|
||||
* because some opcodes are automatically handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
|
||||
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n opcodes are therefore not defined in this
|
||||
* interface. Likewise for LDC, automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and JSR_W.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public interface Opcodes {
|
||||
|
||||
// ASM API versions
|
||||
int ASM4 = 4 << 16 | 0 << 8;
|
||||
int ASM5 = 5 << 16 | 0 << 8;
|
||||
int ASM6 = 6 << 16 | 0 << 8;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
|
||||
// ASM specific pseudo access flags
|
||||
|
||||
int ACC_DEPRECATED = 0x20000; // class, field, method
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// stack map frame types
|
||||
|
||||
/** 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 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 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;
|
||||
|
||||
// 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 FLOAT = new Integer(2);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer DOUBLE = new Integer(3);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer LONG = new Integer(4);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer NULL = new Integer(5);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
Integer UNINITIALIZED_THIS = new Integer(6);
|
||||
|
||||
// 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; // -
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,195 +1,195 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* The path to a type argument, wildcard bound, array element type, or static inner type within an enclosing type.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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 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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* The path to a type argument, wildcard bound, array element type, or static inner type within an enclosing type.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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 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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,402 +1,402 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A reference to a type appearing in a class, field or method declaration, or on an instruction. Such a reference
|
||||
* designates the part of the class where the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
|
||||
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable declaration, etc).
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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 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 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 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 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 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 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 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 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 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 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;
|
||||
|
||||
/**
|
||||
* 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 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 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 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 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 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 "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 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 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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.redkale.asm;
|
||||
|
||||
/**
|
||||
* A reference to a type appearing in a class, field or method declaration, or on an instruction. Such a reference
|
||||
* designates the part of the class where the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
|
||||
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable declaration, etc).
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
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 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 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 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 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 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 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 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 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 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 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 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;
|
||||
|
||||
/**
|
||||
* 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 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 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 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 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 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 "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 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 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/** 本包下所有代码均是从/java.base/jdk/internal/org/objectweb/asm 拷贝过来的 */
|
||||
package org.redkale.asm;
|
||||
/** 本包下所有代码均是从/java.base/jdk/internal/org/objectweb/asm 拷贝过来的 */
|
||||
package org.redkale.asm;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,494 +1,494 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import static org.redkale.boot.Application.*;
|
||||
import static org.redkale.util.RedkaleClassLoader.putReflectionClass;
|
||||
import static org.redkale.util.RedkaleClassLoader.putReflectionPublicConstructors;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import org.redkale.source.DataSources;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.AnyValueWriter;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 加载系统参数配置
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class AppConfig {
|
||||
|
||||
/**
|
||||
* 当前进程的配置文件, 类型: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;
|
||||
|
||||
// 是否用于编译模式运行
|
||||
final boolean compileMode;
|
||||
|
||||
// application.xml原始配置信息
|
||||
AnyValue config;
|
||||
|
||||
// 是否从/META-INF中读取配置
|
||||
boolean configFromCache;
|
||||
|
||||
// 本进程节点ID
|
||||
String nodeid;
|
||||
|
||||
// 本进程节点ID
|
||||
String name;
|
||||
|
||||
// 本地IP地址
|
||||
InetSocketAddress localAddress;
|
||||
|
||||
// 进程根目录
|
||||
File home;
|
||||
|
||||
// 配置文件目录
|
||||
File confFile;
|
||||
|
||||
// 配置文件目录
|
||||
URI confDir;
|
||||
|
||||
// 根ClassLoader
|
||||
RedkaleClassLoader classLoader;
|
||||
|
||||
// Server根ClassLoader
|
||||
RedkaleClassLoader serverClassLoader;
|
||||
|
||||
// 本地文件日志配置项
|
||||
final Properties locaLogProperties = 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 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();
|
||||
}
|
||||
|
||||
/** 初始化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"));
|
||||
}
|
||||
|
||||
/** 读取本地参数配置 */
|
||||
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) {
|
||||
// 没有文件 跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 读取本地日志配置 */
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查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 File getCanonicalFile(File file) {
|
||||
try {
|
||||
return file.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import static org.redkale.boot.Application.*;
|
||||
import static org.redkale.util.RedkaleClassLoader.putReflectionClass;
|
||||
import static org.redkale.util.RedkaleClassLoader.putReflectionPublicConstructors;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import org.redkale.source.DataSources;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.AnyValueWriter;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 加载系统参数配置
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class AppConfig {
|
||||
|
||||
/**
|
||||
* 当前进程的配置文件, 类型: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;
|
||||
|
||||
// 是否用于编译模式运行
|
||||
final boolean compileMode;
|
||||
|
||||
// application.xml原始配置信息
|
||||
AnyValue config;
|
||||
|
||||
// 是否从/META-INF中读取配置
|
||||
boolean configFromCache;
|
||||
|
||||
// 本进程节点ID
|
||||
String nodeid;
|
||||
|
||||
// 本进程节点ID
|
||||
String name;
|
||||
|
||||
// 本地IP地址
|
||||
InetSocketAddress localAddress;
|
||||
|
||||
// 进程根目录
|
||||
File home;
|
||||
|
||||
// 配置文件目录
|
||||
File confFile;
|
||||
|
||||
// 配置文件目录
|
||||
URI confDir;
|
||||
|
||||
// 根ClassLoader
|
||||
RedkaleClassLoader classLoader;
|
||||
|
||||
// Server根ClassLoader
|
||||
RedkaleClassLoader serverClassLoader;
|
||||
|
||||
// 本地文件日志配置项
|
||||
final Properties locaLogProperties = 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 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();
|
||||
}
|
||||
|
||||
/** 初始化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"));
|
||||
}
|
||||
|
||||
/** 读取本地参数配置 */
|
||||
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) {
|
||||
// 没有文件 跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 读取本地日志配置 */
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查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 File getCanonicalFile(File file) {
|
||||
try {
|
||||
return file.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,75 +1,75 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* Application启动和关闭时的监听事件 <br>
|
||||
* 只能通过application.xml配置
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface ApplicationListener {
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*
|
||||
* @param config 配置参数
|
||||
*/
|
||||
default void init(AnyValue config) {}
|
||||
|
||||
/**
|
||||
* Application在运行start前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onPreStart(Application application) {}
|
||||
|
||||
/**
|
||||
* 服务全部停掉前被调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onServersPreStop(Application application) {}
|
||||
|
||||
/**
|
||||
* 服务全部停掉后被调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onServersPostStop(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 onPostCompile(Application application) {}
|
||||
|
||||
/**
|
||||
* Application在运行shutdown前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onPreShutdown(Application application) {}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
* Application启动和关闭时的监听事件 <br>
|
||||
* 只能通过application.xml配置
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface ApplicationListener {
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*
|
||||
* @param config 配置参数
|
||||
*/
|
||||
default void init(AnyValue config) {}
|
||||
|
||||
/**
|
||||
* Application在运行start前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onPreStart(Application application) {}
|
||||
|
||||
/**
|
||||
* 服务全部停掉前被调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onServersPreStop(Application application) {}
|
||||
|
||||
/**
|
||||
* 服务全部停掉后被调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onServersPostStop(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 onPostCompile(Application application) {}
|
||||
|
||||
/**
|
||||
* Application在运行shutdown前调用
|
||||
*
|
||||
* @param application Application
|
||||
*/
|
||||
default void onPreShutdown(Application application) {}
|
||||
}
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import org.redkale.inject.ResourceEvent;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.Environment;
|
||||
|
||||
/** @author zhangjx */
|
||||
public abstract class BootModule {
|
||||
|
||||
protected final Application application;
|
||||
|
||||
protected final ResourceFactory resourceFactory;
|
||||
|
||||
protected final Environment environment;
|
||||
|
||||
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 putEnvValue(Object name, Object value) {
|
||||
application.envProperties.put(name, value);
|
||||
}
|
||||
|
||||
protected List<ModuleEngine> getModuleEngines() {
|
||||
return application.getModuleEngines();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import org.redkale.inject.ResourceEvent;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.Environment;
|
||||
|
||||
/** @author zhangjx */
|
||||
public abstract class BootModule {
|
||||
|
||||
protected final Application application;
|
||||
|
||||
protected final ResourceFactory resourceFactory;
|
||||
|
||||
protected final Environment environment;
|
||||
|
||||
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 putEnvValue(Object name, Object value) {
|
||||
application.envProperties.put(name, value);
|
||||
}
|
||||
|
||||
protected List<ModuleEngine> getModuleEngines() {
|
||||
return application.getModuleEngines();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,141 +1,141 @@
|
||||
/*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.logging.*;
|
||||
import org.redkale.util.Traces;
|
||||
|
||||
/**
|
||||
* Handler基类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.7.0
|
||||
*/
|
||||
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";
|
||||
|
||||
// 有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";
|
||||
|
||||
static boolean traceEnable = false; // 防止设置system.property前调用Traces类导致enable提前初始化
|
||||
|
||||
/** 默认的日志时间格式化类 与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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.logging.*;
|
||||
import org.redkale.util.Traces;
|
||||
|
||||
/**
|
||||
* Handler基类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.7.0
|
||||
*/
|
||||
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";
|
||||
|
||||
// 有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";
|
||||
|
||||
static boolean traceEnable = false; // 防止设置system.property前调用Traces类导致enable提前初始化
|
||||
|
||||
/** 默认的日志时间格式化类 与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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,403 +1,403 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.regex.Pattern;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 自定义的日志输出类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LoggingFileHandler extends LoggingBaseHandler {
|
||||
|
||||
/** SNCP的日志输出Handler */
|
||||
public static class LoggingSncpFileHandler extends LoggingFileHandler {
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "sncp-";
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoggingConsoleHandler extends ConsoleHandler {
|
||||
|
||||
private Pattern denyRegx;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@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 String pattern;
|
||||
|
||||
protected String patternDateFormat; // 需要时间格式化
|
||||
|
||||
protected String unusual; // 不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||
|
||||
protected String unusualDateFormat; // 需要时间格式化
|
||||
|
||||
private int limit; // 文件大小限制
|
||||
|
||||
private final AtomicInteger logIndex = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger logUnusualIndex = new AtomicInteger();
|
||||
|
||||
private int count = 1; // 文件限制
|
||||
|
||||
private long tomorrow;
|
||||
|
||||
protected boolean append;
|
||||
|
||||
protected Pattern denyRegx;
|
||||
|
||||
private final AtomicLong logLength = new AtomicLong();
|
||||
|
||||
private final AtomicLong logUnusualLength = new AtomicLong();
|
||||
|
||||
private File logFile;
|
||||
|
||||
private File logUnusualFile;
|
||||
|
||||
private OutputStream logStream;
|
||||
|
||||
private OutputStream logUnusualStream;
|
||||
|
||||
public LoggingFileHandler() {
|
||||
updateTomorrow();
|
||||
configure();
|
||||
open();
|
||||
}
|
||||
|
||||
private void updateTomorrow() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
long t = cal.getTimeInMillis();
|
||||
if (this.tomorrow != t) {
|
||||
logIndex.set(0);
|
||||
}
|
||||
this.tomorrow = t;
|
||||
}
|
||||
|
||||
private void open() {
|
||||
final String name = "Redkale-Logging-" + getClass().getSimpleName().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();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@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 close() throws SecurityException {
|
||||
try {
|
||||
if (logStream != null) {
|
||||
logStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) {
|
||||
err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.regex.Pattern;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 自定义的日志输出类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LoggingFileHandler extends LoggingBaseHandler {
|
||||
|
||||
/** SNCP的日志输出Handler */
|
||||
public static class LoggingSncpFileHandler extends LoggingFileHandler {
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "sncp-";
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoggingConsoleHandler extends ConsoleHandler {
|
||||
|
||||
private Pattern denyRegx;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@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 String pattern;
|
||||
|
||||
protected String patternDateFormat; // 需要时间格式化
|
||||
|
||||
protected String unusual; // 不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||
|
||||
protected String unusualDateFormat; // 需要时间格式化
|
||||
|
||||
private int limit; // 文件大小限制
|
||||
|
||||
private final AtomicInteger logIndex = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger logUnusualIndex = new AtomicInteger();
|
||||
|
||||
private int count = 1; // 文件限制
|
||||
|
||||
private long tomorrow;
|
||||
|
||||
protected boolean append;
|
||||
|
||||
protected Pattern denyRegx;
|
||||
|
||||
private final AtomicLong logLength = new AtomicLong();
|
||||
|
||||
private final AtomicLong logUnusualLength = new AtomicLong();
|
||||
|
||||
private File logFile;
|
||||
|
||||
private File logUnusualFile;
|
||||
|
||||
private OutputStream logStream;
|
||||
|
||||
private OutputStream logUnusualStream;
|
||||
|
||||
public LoggingFileHandler() {
|
||||
updateTomorrow();
|
||||
configure();
|
||||
open();
|
||||
}
|
||||
|
||||
private void updateTomorrow() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
long t = cal.getTimeInMillis();
|
||||
if (this.tomorrow != t) {
|
||||
logIndex.set(0);
|
||||
}
|
||||
this.tomorrow = t;
|
||||
}
|
||||
|
||||
private void open() {
|
||||
final String name = "Redkale-Logging-" + getClass().getSimpleName().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();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@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 close() throws SecurityException {
|
||||
try {
|
||||
if (logStream != null) {
|
||||
logStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) {
|
||||
err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,192 +1,192 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import org.redkale.inject.ResourceEvent;
|
||||
import org.redkale.net.sncp.SncpClient;
|
||||
import org.redkale.util.Environment;
|
||||
|
||||
/**
|
||||
* 日志模块组件
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
class LoggingModule extends BootModule {
|
||||
|
||||
// 日志配置资源
|
||||
private final Properties loggingProperties = new Properties();
|
||||
|
||||
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 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) { // 不会发生
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import org.redkale.inject.ResourceEvent;
|
||||
import org.redkale.net.sncp.SncpClient;
|
||||
import org.redkale.util.Environment;
|
||||
|
||||
/**
|
||||
* 日志模块组件
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
class LoggingModule extends BootModule {
|
||||
|
||||
// 日志配置资源
|
||||
private final Properties loggingProperties = new Properties();
|
||||
|
||||
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 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) { // 不会发生
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,353 +1,353 @@
|
||||
/*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import static org.redkale.boot.Application.RESNAME_APP_NAME;
|
||||
import static org.redkale.boot.Application.SYSNAME_APP_NAME;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.*;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.regex.Pattern;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.persistence.*;
|
||||
import org.redkale.persistence.SearchColumn;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 基于SearchSource的日志输出类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public class LoggingSearchHandler extends LoggingBaseHandler {
|
||||
|
||||
protected static final String DEFAULT_TABLE_NAME = "log-record";
|
||||
|
||||
protected final LinkedBlockingQueue<SearchLogRecord> logqueue = new LinkedBlockingQueue();
|
||||
|
||||
protected final AtomicInteger retryCount = new AtomicInteger(3);
|
||||
|
||||
protected String tag = DEFAULT_TABLE_NAME; // 用于表前缀, 默认是
|
||||
|
||||
protected String tagDateFormat; // 需要时间格式化
|
||||
|
||||
protected String pattern;
|
||||
|
||||
protected Pattern denyRegx;
|
||||
|
||||
protected String sourceResourceName;
|
||||
|
||||
protected SearchSource source;
|
||||
|
||||
// 在LogManager.getLogManager().readConfiguration执行完后,通过反射注入Application
|
||||
protected Application application;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@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 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()); // 测试时间格式是否正确
|
||||
}
|
||||
}
|
||||
|
||||
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 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 flush() {
|
||||
// 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 {
|
||||
|
||||
@Id
|
||||
@ConvertColumn(index = 1)
|
||||
@SearchColumn(options = "false")
|
||||
public String logid;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
@SearchColumn(options = "false")
|
||||
public String level;
|
||||
|
||||
@ConvertColumn(index = 3)
|
||||
@SearchColumn(date = true)
|
||||
public long timestamp;
|
||||
|
||||
@ConvertColumn(index = 4)
|
||||
@SearchColumn(options = "false")
|
||||
public String traceid;
|
||||
|
||||
@ConvertColumn(index = 5)
|
||||
public String threadName;
|
||||
|
||||
@ConvertColumn(index = 6)
|
||||
@SearchColumn(text = true, options = "offsets")
|
||||
public String loggerName;
|
||||
|
||||
@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
|
||||
|
||||
@Transient
|
||||
@ConvertDisabled
|
||||
LogRecord rawLog;
|
||||
|
||||
@Transient
|
||||
@ConvertDisabled
|
||||
String rawTag;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
|
||||
public static class TableStrategy implements DistributeTableStrategy<SearchLogRecord> {
|
||||
|
||||
@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[] getTables(String table, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import static org.redkale.boot.Application.RESNAME_APP_NAME;
|
||||
import static org.redkale.boot.Application.SYSNAME_APP_NAME;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.*;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.regex.Pattern;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.persistence.*;
|
||||
import org.redkale.persistence.SearchColumn;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 基于SearchSource的日志输出类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public class LoggingSearchHandler extends LoggingBaseHandler {
|
||||
|
||||
protected static final String DEFAULT_TABLE_NAME = "log-record";
|
||||
|
||||
protected final LinkedBlockingQueue<SearchLogRecord> logqueue = new LinkedBlockingQueue();
|
||||
|
||||
protected final AtomicInteger retryCount = new AtomicInteger(3);
|
||||
|
||||
protected String tag = DEFAULT_TABLE_NAME; // 用于表前缀, 默认是
|
||||
|
||||
protected String tagDateFormat; // 需要时间格式化
|
||||
|
||||
protected String pattern;
|
||||
|
||||
protected Pattern denyRegx;
|
||||
|
||||
protected String sourceResourceName;
|
||||
|
||||
protected SearchSource source;
|
||||
|
||||
// 在LogManager.getLogManager().readConfiguration执行完后,通过反射注入Application
|
||||
protected Application application;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@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 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()); // 测试时间格式是否正确
|
||||
}
|
||||
}
|
||||
|
||||
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 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 flush() {
|
||||
// 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 {
|
||||
|
||||
@Id
|
||||
@ConvertColumn(index = 1)
|
||||
@SearchColumn(options = "false")
|
||||
public String logid;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
@SearchColumn(options = "false")
|
||||
public String level;
|
||||
|
||||
@ConvertColumn(index = 3)
|
||||
@SearchColumn(date = true)
|
||||
public long timestamp;
|
||||
|
||||
@ConvertColumn(index = 4)
|
||||
@SearchColumn(options = "false")
|
||||
public String traceid;
|
||||
|
||||
@ConvertColumn(index = 5)
|
||||
public String threadName;
|
||||
|
||||
@ConvertColumn(index = 6)
|
||||
@SearchColumn(text = true, options = "offsets")
|
||||
public String loggerName;
|
||||
|
||||
@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
|
||||
|
||||
@Transient
|
||||
@ConvertDisabled
|
||||
LogRecord rawLog;
|
||||
|
||||
@Transient
|
||||
@ConvertDisabled
|
||||
String rawTag;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
|
||||
public static class TableStrategy implements DistributeTableStrategy<SearchLogRecord> {
|
||||
|
||||
@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[] getTables(String table, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,179 +1,179 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.inject.ResourceEvent;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.Environment;
|
||||
|
||||
/**
|
||||
* 各组件的引擎类, 由Application管理
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public abstract class ModuleEngine {
|
||||
|
||||
protected final Logger logger = Logger.getLogger(getClass().getSimpleName());
|
||||
|
||||
protected final Application application;
|
||||
|
||||
protected final ResourceFactory resourceFactory;
|
||||
|
||||
protected final Environment environment;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态扩展类的方法
|
||||
*
|
||||
* @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方法前被调用 */
|
||||
public void onAppPostInit() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 进入Application.start方法被调用 */
|
||||
public void onAppPreStart() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 结束Application.start方法前被调用 */
|
||||
public void onAppPostStart() {
|
||||
// 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
|
||||
}
|
||||
|
||||
/** Application 在运行Compile前调用 */
|
||||
public void onPreCompile() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** Application 在运行Compile后调用 */
|
||||
public void onPostCompile() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 服务全部启动前被调用 */
|
||||
public void onServersPreStart() {
|
||||
// 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 onServicePostInit(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
|
||||
}
|
||||
|
||||
/** 服务全部停掉前被调用 */
|
||||
public void onServersPreStop() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 服务全部停掉后被调用 */
|
||||
public void onServersPostStop() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 进入Application.shutdown方法被调用 */
|
||||
public void onAppPreShutdown() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 结束Application.shutdown方法前被调用 */
|
||||
public void onAppPostShutdown() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.inject.ResourceEvent;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.Environment;
|
||||
|
||||
/**
|
||||
* 各组件的引擎类, 由Application管理
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public abstract class ModuleEngine {
|
||||
|
||||
protected final Logger logger = Logger.getLogger(getClass().getSimpleName());
|
||||
|
||||
protected final Application application;
|
||||
|
||||
protected final ResourceFactory resourceFactory;
|
||||
|
||||
protected final Environment environment;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态扩展类的方法
|
||||
*
|
||||
* @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方法前被调用 */
|
||||
public void onAppPostInit() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 进入Application.start方法被调用 */
|
||||
public void onAppPreStart() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 结束Application.start方法前被调用 */
|
||||
public void onAppPostStart() {
|
||||
// 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
|
||||
}
|
||||
|
||||
/** Application 在运行Compile前调用 */
|
||||
public void onPreCompile() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** Application 在运行Compile后调用 */
|
||||
public void onPostCompile() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 服务全部启动前被调用 */
|
||||
public void onServersPreStart() {
|
||||
// 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 onServicePostInit(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
|
||||
}
|
||||
|
||||
/** 服务全部停掉前被调用 */
|
||||
public void onServersPreStop() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 服务全部停掉后被调用 */
|
||||
public void onServersPostStop() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 进入Application.shutdown方法被调用 */
|
||||
public void onAppPreShutdown() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** 结束Application.shutdown方法前被调用 */
|
||||
public void onAppPostShutdown() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
/**
|
||||
* NodeServer的拦截类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class NodeInterceptor {
|
||||
|
||||
/**
|
||||
* * Server.start之前调用 <br>
|
||||
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preStart(NodeServer server) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Server.shutdown之前调用 <br>
|
||||
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.shutdown 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preShutdown(NodeServer server) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
/**
|
||||
* NodeServer的拦截类
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class NodeInterceptor {
|
||||
|
||||
/**
|
||||
* * Server.start之前调用 <br>
|
||||
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preStart(NodeServer server) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Server.shutdown之前调用 <br>
|
||||
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.shutdown 方法
|
||||
*
|
||||
* @param server NodeServer
|
||||
*/
|
||||
public void preShutdown(NodeServer server) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface NodeProtocol {
|
||||
|
||||
String value();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface NodeProtocol {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,183 +1,183 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.mq.spi.MessageAgent;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.Local;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* SNCP Server节点的配置Server
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol("SNCP")
|
||||
public class NodeSncpServer extends NodeServer {
|
||||
|
||||
protected final SncpServer sncpServer;
|
||||
|
||||
private NodeSncpServer(Application application, AnyValue serconf) {
|
||||
super(application, createServer(application, serconf));
|
||||
this.sncpServer = (SncpServer) this.server;
|
||||
}
|
||||
|
||||
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
||||
return new NodeSncpServer(application, serconf);
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
return new SncpServer(
|
||||
application,
|
||||
application.getStartTime(),
|
||||
serconf,
|
||||
application.getResourceFactory().createChild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public SncpServer getSncpServer() {
|
||||
return sncpServer;
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.mq.spi.MessageAgent;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.Local;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* SNCP Server节点的配置Server
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol("SNCP")
|
||||
public class NodeSncpServer extends NodeServer {
|
||||
|
||||
protected final SncpServer sncpServer;
|
||||
|
||||
private NodeSncpServer(Application application, AnyValue serconf) {
|
||||
super(application, createServer(application, serconf));
|
||||
this.sncpServer = (SncpServer) this.server;
|
||||
}
|
||||
|
||||
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
||||
return new NodeSncpServer(application, serconf);
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
return new SncpServer(
|
||||
application,
|
||||
application.getStartTime(),
|
||||
serconf,
|
||||
application.getResourceFactory().createChild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public SncpServer getSncpServer() {
|
||||
return sncpServer;
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.WebServlet;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.watch.*;
|
||||
|
||||
/** @author zhangjx */
|
||||
@NodeProtocol("WATCH")
|
||||
public class NodeWatchServer extends NodeHttpServer {
|
||||
|
||||
public NodeWatchServer(Application application, AnyValue serconf) {
|
||||
super(application, serconf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Service> createServiceClassFilter() {
|
||||
return createClassFilter(
|
||||
this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ClassFilter> createOtherClassFilters() {
|
||||
return null; // 不调用 super.createOtherClassFilters()
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWATCH() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.WebServlet;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.watch.*;
|
||||
|
||||
/** @author zhangjx */
|
||||
@NodeProtocol("WATCH")
|
||||
public class NodeWatchServer extends NodeHttpServer {
|
||||
|
||||
public NodeWatchServer(Application application, AnyValue serconf) {
|
||||
super(application, serconf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Service> createServiceClassFilter() {
|
||||
return createClassFilter(
|
||||
this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ClassFilter> createOtherClassFilters() {
|
||||
return null; // 不调用 super.createOtherClassFilters()
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWATCH() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,145 +1,145 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.List;
|
||||
import org.redkale.annotation.Bean;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.convert.Decodeable;
|
||||
import org.redkale.convert.bson.BsonFactory;
|
||||
import org.redkale.convert.json.*;
|
||||
import org.redkale.persistence.Entity;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 执行一次Application.run提前获取所有动态类
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class PrepareCompiler {
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// new PrepareCompiler().run();
|
||||
// }
|
||||
public Application run() throws Exception {
|
||||
// 必须设置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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.List;
|
||||
import org.redkale.annotation.Bean;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.convert.Decodeable;
|
||||
import org.redkale.convert.bson.BsonFactory;
|
||||
import org.redkale.convert.json.*;
|
||||
import org.redkale.persistence.Entity;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
* 执行一次Application.run提前获取所有动态类
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class PrepareCompiler {
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// new PrepareCompiler().run();
|
||||
// }
|
||||
public Application run() throws Exception {
|
||||
// 必须设置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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/** 提供Redkale服务器的启动、初始化和加载功能 */
|
||||
package org.redkale.boot;
|
||||
/** 提供Redkale服务器的启动、初始化和加载功能 */
|
||||
package org.redkale.boot;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import org.redkale.annotation.Comment;
|
||||
import org.redkale.service.AbstractService;
|
||||
import org.redkale.watch.WatchService;
|
||||
|
||||
/** @author zhangjx */
|
||||
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
||||
|
||||
/** 缺少参数 */
|
||||
@Comment("缺少参数")
|
||||
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
||||
|
||||
/** 执行异常 */
|
||||
@Comment("执行异常")
|
||||
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import org.redkale.annotation.Comment;
|
||||
import org.redkale.service.AbstractService;
|
||||
import org.redkale.watch.WatchService;
|
||||
|
||||
/** @author zhangjx */
|
||||
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
||||
|
||||
/** 缺少参数 */
|
||||
@Comment("缺少参数")
|
||||
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
||||
|
||||
/** 执行异常 */
|
||||
@Comment("执行异常")
|
||||
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
||||
}
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.redkale.annotation.*;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
|
||||
/** @author zhangjx */
|
||||
@RestService(name = "filter", catalog = "watch", repair = false)
|
||||
public class FilterWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("Filter类名不存在")
|
||||
public static final int RET_FILTER_TYPE_NOT_EXISTS = 1601_0002;
|
||||
|
||||
@Comment("Filter类名不合法")
|
||||
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
|
||||
|
||||
@Comment("Filter类名已存在")
|
||||
public static final int RET_FILTER_EXISTS = 1601_0004;
|
||||
|
||||
@Comment("Filter的JAR包不存在")
|
||||
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
|
||||
public RetResult addFilter(
|
||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, 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 = "test2", auth = false, comment = "预留")
|
||||
public RetResult test2() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||
public RetResult test3() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||
public RetResult test4() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||
public RetResult test5() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||
public RetResult test6() {
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.redkale.annotation.*;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
|
||||
/** @author zhangjx */
|
||||
@RestService(name = "filter", catalog = "watch", repair = false)
|
||||
public class FilterWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("Filter类名不存在")
|
||||
public static final int RET_FILTER_TYPE_NOT_EXISTS = 1601_0002;
|
||||
|
||||
@Comment("Filter类名不合法")
|
||||
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
|
||||
|
||||
@Comment("Filter类名已存在")
|
||||
public static final int RET_FILTER_EXISTS = 1601_0004;
|
||||
|
||||
@Comment("Filter的JAR包不存在")
|
||||
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
|
||||
public RetResult addFilter(
|
||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, 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 = "test2", auth = false, comment = "预留")
|
||||
public RetResult test2() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||
public RetResult test3() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||
public RetResult test4() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||
public RetResult test5() {
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||
public RetResult test6() {
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,117 +1,117 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.annotation.*;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.Server;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
|
||||
/** @author zhangjx */
|
||||
@RestService(name = "server", catalog = "watch", repair = false)
|
||||
public class ServerWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("不存在的Server节点")
|
||||
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
||||
|
||||
@Comment("更改Server监听地址端口失败")
|
||||
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "info", comment = "单个Server信息查询")
|
||||
public RetResult info(@RestParam(name = "#port:") final int port) {
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (node == null) {
|
||||
return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
||||
}
|
||||
return new RetResult(formatToMap(node));
|
||||
}
|
||||
|
||||
@RestMapping(name = "infos", comment = "Server信息查询")
|
||||
public RetResult infos() {
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
Server server = ns.getServer();
|
||||
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
||||
}
|
||||
return new RetResult(rs);
|
||||
}
|
||||
|
||||
@RestMapping(name = "changeAddress", comment = "更改Server的监听地址和端口")
|
||||
public RetResult changeAddress(
|
||||
@RestParam(name = "#port:") final int oldport,
|
||||
@RestParam(name = "#newhost:") final String newhost,
|
||||
@RestParam(name = "#newport:") final int newport) {
|
||||
if (oldport < 1) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
||||
}
|
||||
if (newport < 1) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
||||
}
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (node == null) {
|
||||
return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
||||
}
|
||||
final Server server = node.getServer();
|
||||
InetSocketAddress newAddr = new InetSocketAddress(
|
||||
newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
||||
try {
|
||||
server.changeAddress(application, newAddr);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeAddress error");
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
private Map<String, Object> formatToMap(NodeServer node) {
|
||||
Server server = node.getServer();
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
String protocol = server.getNetprotocol();
|
||||
if (node instanceof NodeSncpServer) {
|
||||
protocol += "/SNCP";
|
||||
} else if (node instanceof NodeWatchServer) {
|
||||
protocol += "/WATCH";
|
||||
} else if (node instanceof NodeHttpServer) {
|
||||
protocol += "/HTTP";
|
||||
} else {
|
||||
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
||||
protocol += "/" + np.value();
|
||||
}
|
||||
rs.put("name", server.getName());
|
||||
rs.put("protocol", protocol);
|
||||
rs.put("address", server.getSocketAddress());
|
||||
rs.put("backlog", server.getBacklog());
|
||||
rs.put("bufferCapacity", server.getBufferCapacity());
|
||||
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
||||
rs.put(
|
||||
"charset",
|
||||
server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
||||
rs.put("maxbody", server.getMaxBody());
|
||||
rs.put("maxconns", server.getMaxConns());
|
||||
rs.put("serverStartTime", server.getServerStartTime());
|
||||
rs.put("responsePoolSize", server.getResponsePoolSize());
|
||||
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
||||
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
||||
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
||||
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
||||
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.annotation.*;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.net.Server;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
|
||||
/** @author zhangjx */
|
||||
@RestService(name = "server", catalog = "watch", repair = false)
|
||||
public class ServerWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("不存在的Server节点")
|
||||
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
||||
|
||||
@Comment("更改Server监听地址端口失败")
|
||||
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestMapping(name = "info", comment = "单个Server信息查询")
|
||||
public RetResult info(@RestParam(name = "#port:") final int port) {
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (node == null) {
|
||||
return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
||||
}
|
||||
return new RetResult(formatToMap(node));
|
||||
}
|
||||
|
||||
@RestMapping(name = "infos", comment = "Server信息查询")
|
||||
public RetResult infos() {
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
Server server = ns.getServer();
|
||||
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
||||
}
|
||||
return new RetResult(rs);
|
||||
}
|
||||
|
||||
@RestMapping(name = "changeAddress", comment = "更改Server的监听地址和端口")
|
||||
public RetResult changeAddress(
|
||||
@RestParam(name = "#port:") final int oldport,
|
||||
@RestParam(name = "#newhost:") final String newhost,
|
||||
@RestParam(name = "#newport:") final int newport) {
|
||||
if (oldport < 1) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
||||
}
|
||||
if (newport < 1) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
||||
}
|
||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (node == null) {
|
||||
return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
||||
}
|
||||
final Server server = node.getServer();
|
||||
InetSocketAddress newAddr = new InetSocketAddress(
|
||||
newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
||||
try {
|
||||
server.changeAddress(application, newAddr);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeAddress error");
|
||||
}
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
private Map<String, Object> formatToMap(NodeServer node) {
|
||||
Server server = node.getServer();
|
||||
Map<String, Object> rs = new LinkedHashMap<>();
|
||||
String protocol = server.getNetprotocol();
|
||||
if (node instanceof NodeSncpServer) {
|
||||
protocol += "/SNCP";
|
||||
} else if (node instanceof NodeWatchServer) {
|
||||
protocol += "/WATCH";
|
||||
} else if (node instanceof NodeHttpServer) {
|
||||
protocol += "/HTTP";
|
||||
} else {
|
||||
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
||||
protocol += "/" + np.value();
|
||||
}
|
||||
rs.put("name", server.getName());
|
||||
rs.put("protocol", protocol);
|
||||
rs.put("address", server.getSocketAddress());
|
||||
rs.put("backlog", server.getBacklog());
|
||||
rs.put("bufferCapacity", server.getBufferCapacity());
|
||||
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
||||
rs.put(
|
||||
"charset",
|
||||
server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
||||
rs.put("maxbody", server.getMaxBody());
|
||||
rs.put("maxconns", server.getMaxConns());
|
||||
rs.put("serverStartTime", server.getServerStartTime());
|
||||
rs.put("responsePoolSize", server.getResponsePoolSize());
|
||||
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
||||
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
||||
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
||||
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
||||
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,262 +1,262 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.List;
|
||||
import org.redkale.annotation.*;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
|
||||
/**
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "service", catalog = "watch", repair = false)
|
||||
public class ServiceWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("没有找到目标Service")
|
||||
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "setField", auth = false, comment = "设置Service中指定字段的内容")
|
||||
public RetResult setField(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "field", comment = "字段名") String field,
|
||||
@RestParam(name = "value", comment = "字段值") String value) {
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
if (type == null) {
|
||||
type = "";
|
||||
}
|
||||
if (field == null) {
|
||||
field = "";
|
||||
}
|
||||
type = type.trim();
|
||||
field = field.trim();
|
||||
if (type.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
}
|
||||
if (field.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||
}
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
try {
|
||||
Field fieldObj = null;
|
||||
do {
|
||||
try {
|
||||
fieldObj = clazz.getDeclaredField(field);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) {
|
||||
t = e;
|
||||
}
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (fieldObj == null) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + 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 = "runMethod", auth = false, comment = "调用Service中指定方法")
|
||||
public RetResult runMethod(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "method", comment = "Service的方法名") String method,
|
||||
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
||||
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
if (type == null) {
|
||||
type = "";
|
||||
}
|
||||
if (method == null) {
|
||||
method = "";
|
||||
}
|
||||
type = type.trim();
|
||||
method = method.trim();
|
||||
if (type.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
}
|
||||
if (method.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
||||
}
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
final int paramcount = params == null ? 0 : params.size();
|
||||
if (paramtypes != null && paramcount != paramtypes.size()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
||||
}
|
||||
try {
|
||||
Method methodObj = null;
|
||||
do {
|
||||
try {
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
||||
boolean flag = true;
|
||||
if (paramtypes != null) {
|
||||
Class[] pts = m.getParameterTypes();
|
||||
for (int i = 0; i < pts.length; i++) {
|
||||
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
methodObj = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (methodObj != null) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (t == null) {
|
||||
t = e;
|
||||
}
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (methodObj == null) {
|
||||
return new RetResult(
|
||||
RET_WATCH_RUN_EXCEPTION,
|
||||
"run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t))
|
||||
+ ")");
|
||||
}
|
||||
methodObj.setAccessible(true);
|
||||
if (paramcount < 1) {
|
||||
return new RetResult(methodObj.invoke(dest));
|
||||
}
|
||||
Object[] paramObjs = new Object[paramcount];
|
||||
Type[] pts = methodObj.getGenericParameterTypes();
|
||||
for (int i = 0; i < paramObjs.length; i++) {
|
||||
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
||||
}
|
||||
return new RetResult(methodObj.invoke(dest, paramObjs));
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
protected Object findService(String name, String type) {
|
||||
Object dest = null;
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
ResourceFactory resFactory = ns.getResourceFactory();
|
||||
List list = resFactory.query((n, s) ->
|
||||
name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
||||
if (list == null || list.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
dest = list.get(0);
|
||||
}
|
||||
if (dest == null) {
|
||||
return new RetResult(
|
||||
RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
|
||||
public RetResult loadService(
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, 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 = "stopService", auth = false, comment = "动态停止Service")
|
||||
public RetResult stopService(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
// 待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "findService", auth = false, comment = "查找Service")
|
||||
public RetResult find(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
// 待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.List;
|
||||
import org.redkale.annotation.*;
|
||||
import org.redkale.boot.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.service.RetResult;
|
||||
|
||||
/**
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@RestService(name = "service", catalog = "watch", repair = false)
|
||||
public class ServiceWatchService extends AbstractWatchService {
|
||||
|
||||
@Comment("没有找到目标Service")
|
||||
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
||||
|
||||
@Resource
|
||||
protected Application application;
|
||||
|
||||
@RestConvert(type = void.class)
|
||||
@RestMapping(name = "setField", auth = false, comment = "设置Service中指定字段的内容")
|
||||
public RetResult setField(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "field", comment = "字段名") String field,
|
||||
@RestParam(name = "value", comment = "字段值") String value) {
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
if (type == null) {
|
||||
type = "";
|
||||
}
|
||||
if (field == null) {
|
||||
field = "";
|
||||
}
|
||||
type = type.trim();
|
||||
field = field.trim();
|
||||
if (type.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
}
|
||||
if (field.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||
}
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
try {
|
||||
Field fieldObj = null;
|
||||
do {
|
||||
try {
|
||||
fieldObj = clazz.getDeclaredField(field);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (t == null) {
|
||||
t = e;
|
||||
}
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (fieldObj == null) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + 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 = "runMethod", auth = false, comment = "调用Service中指定方法")
|
||||
public RetResult runMethod(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestParam(name = "method", comment = "Service的方法名") String method,
|
||||
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
||||
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
if (type == null) {
|
||||
type = "";
|
||||
}
|
||||
if (method == null) {
|
||||
method = "";
|
||||
}
|
||||
type = type.trim();
|
||||
method = method.trim();
|
||||
if (type.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||
}
|
||||
if (method.isEmpty()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
||||
}
|
||||
Object dest = findService(name, type);
|
||||
Class clazz = dest.getClass();
|
||||
Throwable t = null;
|
||||
final int paramcount = params == null ? 0 : params.size();
|
||||
if (paramtypes != null && paramcount != paramtypes.size()) {
|
||||
return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
||||
}
|
||||
try {
|
||||
Method methodObj = null;
|
||||
do {
|
||||
try {
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
||||
boolean flag = true;
|
||||
if (paramtypes != null) {
|
||||
Class[] pts = m.getParameterTypes();
|
||||
for (int i = 0; i < pts.length; i++) {
|
||||
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
methodObj = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (methodObj != null) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (t == null) {
|
||||
t = e;
|
||||
}
|
||||
}
|
||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||
if (methodObj == null) {
|
||||
return new RetResult(
|
||||
RET_WATCH_RUN_EXCEPTION,
|
||||
"run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t))
|
||||
+ ")");
|
||||
}
|
||||
methodObj.setAccessible(true);
|
||||
if (paramcount < 1) {
|
||||
return new RetResult(methodObj.invoke(dest));
|
||||
}
|
||||
Object[] paramObjs = new Object[paramcount];
|
||||
Type[] pts = methodObj.getGenericParameterTypes();
|
||||
for (int i = 0; i < paramObjs.length; i++) {
|
||||
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
||||
}
|
||||
return new RetResult(methodObj.invoke(dest, paramObjs));
|
||||
} catch (Throwable t2) {
|
||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
protected Object findService(String name, String type) {
|
||||
Object dest = null;
|
||||
for (NodeServer ns : application.getNodeServers()) {
|
||||
ResourceFactory resFactory = ns.getResourceFactory();
|
||||
List list = resFactory.query((n, s) ->
|
||||
name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
||||
if (list == null || list.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
dest = list.get(0);
|
||||
}
|
||||
if (dest == null) {
|
||||
return new RetResult(
|
||||
RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
|
||||
public RetResult loadService(
|
||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, 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 = "stopService", auth = false, comment = "动态停止Service")
|
||||
public RetResult stopService(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
// 待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
|
||||
@RestMapping(name = "findService", auth = false, comment = "查找Service")
|
||||
public RetResult find(
|
||||
@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||
// 待开发
|
||||
return RetResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/** 提供系统默认监控包 */
|
||||
package org.redkale.boot.watch;
|
||||
/** 提供系统默认监控包 */
|
||||
package org.redkale.boot.watch;
|
||||
|
||||
1684
src/main/java/org/redkale/cache/CacheManager.java
vendored
1684
src/main/java/org/redkale/cache/CacheManager.java
vendored
File diff suppressed because it is too large
Load Diff
180
src/main/java/org/redkale/cache/Cached.java
vendored
180
src/main/java/org/redkale/cache/Cached.java
vendored
@@ -1,90 +1,90 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.service.LoadMode;
|
||||
|
||||
/**
|
||||
* 标记在Service的缓存接口, 方法有以下限制: <br>
|
||||
* 1、方法返回类型不能是void/CompletableFuture<Void> <br>
|
||||
* 2、方法返回类型必须可json序列化 <br>
|
||||
* 3、方法必须是protected/public <br>
|
||||
* 4、方法不能是final/static <br>
|
||||
*
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target(METHOD)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cached {
|
||||
|
||||
/**
|
||||
* 缓存的key,支持参数动态组合,比如"key_#{id}" <br>
|
||||
* '@'开头的key值视为CacheKeyGenerator对象名称 <br>
|
||||
*
|
||||
* @see org.redkale.cache.spi.CacheKeyGenerator#name()
|
||||
*
|
||||
* @return 键
|
||||
*/
|
||||
String key();
|
||||
|
||||
/**
|
||||
* 缓存的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 remoteExpire() default "-1";
|
||||
|
||||
/**
|
||||
* 是否可以缓存null值
|
||||
*
|
||||
* @return 是否可以缓存null
|
||||
*/
|
||||
boolean nullable() default false;
|
||||
|
||||
/**
|
||||
* 过期时长的时间单位
|
||||
*
|
||||
* @return 时间单位
|
||||
*/
|
||||
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*
|
||||
* @return 备注
|
||||
*/
|
||||
String comment() default "";
|
||||
|
||||
/**
|
||||
* Service加载模式
|
||||
*
|
||||
* @return 模式
|
||||
*/
|
||||
LoadMode mode() default LoadMode.ANY;
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.service.LoadMode;
|
||||
|
||||
/**
|
||||
* 标记在Service的缓存接口, 方法有以下限制: <br>
|
||||
* 1、方法返回类型不能是void/CompletableFuture<Void> <br>
|
||||
* 2、方法返回类型必须可json序列化 <br>
|
||||
* 3、方法必须是protected/public <br>
|
||||
* 4、方法不能是final/static <br>
|
||||
*
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target(METHOD)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cached {
|
||||
|
||||
/**
|
||||
* 缓存的key,支持参数动态组合,比如"key_#{id}" <br>
|
||||
* '@'开头的key值视为CacheKeyGenerator对象名称 <br>
|
||||
*
|
||||
* @see org.redkale.cache.spi.CacheKeyGenerator#name()
|
||||
*
|
||||
* @return 键
|
||||
*/
|
||||
String key();
|
||||
|
||||
/**
|
||||
* 缓存的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 remoteExpire() default "-1";
|
||||
|
||||
/**
|
||||
* 是否可以缓存null值
|
||||
*
|
||||
* @return 是否可以缓存null
|
||||
*/
|
||||
boolean nullable() default false;
|
||||
|
||||
/**
|
||||
* 过期时长的时间单位
|
||||
*
|
||||
* @return 时间单位
|
||||
*/
|
||||
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*
|
||||
* @return 备注
|
||||
*/
|
||||
String comment() default "";
|
||||
|
||||
/**
|
||||
* Service加载模式
|
||||
*
|
||||
* @return 模式
|
||||
*/
|
||||
LoadMode mode() default LoadMode.ANY;
|
||||
}
|
||||
|
||||
368
src/main/java/org/redkale/cache/spi/CacheAction.java
vendored
368
src/main/java/org/redkale/cache/spi/CacheAction.java
vendored
@@ -1,184 +1,184 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.annotation.ClassDepends;
|
||||
import org.redkale.annotation.Nullable;
|
||||
import org.redkale.annotation.Resource;
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.Environment;
|
||||
import org.redkale.util.MultiHashKey;
|
||||
import org.redkale.util.ThrowSupplier;
|
||||
import org.redkale.util.TypeToken;
|
||||
|
||||
/**
|
||||
* 缓存的方法对象
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@ClassDepends
|
||||
public class CacheAction {
|
||||
|
||||
@Resource
|
||||
private Environment environment;
|
||||
|
||||
@Resource
|
||||
private CacheManager manager;
|
||||
|
||||
private final CacheEntry cached;
|
||||
|
||||
private final Method method;
|
||||
|
||||
// Supplier对象的类型
|
||||
private final Type resultType;
|
||||
|
||||
// 缓存方法是否异步
|
||||
private final boolean async;
|
||||
|
||||
// 是否可以缓存null
|
||||
private final boolean nullable;
|
||||
|
||||
// 宿主对象的类
|
||||
private final Class serviceClass;
|
||||
|
||||
// 无法获取动态的Method,只能存方法名
|
||||
private final String methodName;
|
||||
|
||||
// 获取动态的字段名
|
||||
private final String fieldName;
|
||||
|
||||
// 方法参数名
|
||||
@Nullable
|
||||
private final String[] paramNames;
|
||||
|
||||
// 缓存的hash
|
||||
private String hash;
|
||||
|
||||
// 模板key
|
||||
String templetKey;
|
||||
|
||||
// 缓存key生成器
|
||||
private CacheKeyGenerator keyGenerator;
|
||||
|
||||
// 父对象
|
||||
private Object service;
|
||||
|
||||
// 本地缓存过期时长,Duration.ZERO为永不过期,为null表示不本地缓存
|
||||
private Duration localExpire;
|
||||
|
||||
// 远程缓存过期时长,Duration.ZERO为永不过期,为null表示不远程缓存
|
||||
private Duration remoteExpire;
|
||||
|
||||
CacheAction(CacheEntry cached, Method method, Class serviceClass, String[] paramNames, String fieldName) {
|
||||
this.cached = cached;
|
||||
this.method = method;
|
||||
this.nullable = cached.isNullable();
|
||||
this.serviceClass = Objects.requireNonNull(serviceClass);
|
||||
this.paramNames = paramNames;
|
||||
this.methodName = method.getName();
|
||||
this.fieldName = Objects.requireNonNull(fieldName);
|
||||
this.templetKey = cached.getKey();
|
||||
Type returnType = method.getGenericReturnType();
|
||||
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
|
||||
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
|
||||
}
|
||||
|
||||
void init(ResourceFactory resourceFactory, Object service) {
|
||||
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.templetKey = key;
|
||||
if (key.startsWith("@")) { // 动态加载缓存key生成器
|
||||
String generatorName = key.substring(1);
|
||||
this.keyGenerator = resourceFactory.findChild(generatorName, CacheKeyGenerator.class);
|
||||
} else {
|
||||
MultiHashKey dynKey = MultiHashKey.create(paramNames, key);
|
||||
this.keyGenerator = CacheKeyGenerator.create(dynKey);
|
||||
}
|
||||
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,
|
||||
keyGenerator.generate(service, this, args),
|
||||
resultType,
|
||||
nullable,
|
||||
localExpire,
|
||||
remoteExpire,
|
||||
supplier0);
|
||||
} else {
|
||||
return manager.bothGetSet(
|
||||
hash,
|
||||
keyGenerator.generate(service, this, 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)));
|
||||
}
|
||||
}
|
||||
|
||||
public CacheEntry getCached() {
|
||||
return cached;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{"
|
||||
+ "\"serviceClass\":" + serviceClass.getName()
|
||||
+ ",\"methodName\":\"" + methodName + "\""
|
||||
+ ",\"fieldName\":\"" + fieldName + "\""
|
||||
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(method.getParameterTypes())
|
||||
+ ",\"paramNames\":" + JsonConvert.root().convertTo(paramNames)
|
||||
+ ",\"templetKey\":\"" + templetKey + "\""
|
||||
+ ",\"resultType\":\"" + resultType + "\""
|
||||
+ ",\"cache\":" + cached
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.annotation.ClassDepends;
|
||||
import org.redkale.annotation.Nullable;
|
||||
import org.redkale.annotation.Resource;
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.Environment;
|
||||
import org.redkale.util.MultiHashKey;
|
||||
import org.redkale.util.ThrowSupplier;
|
||||
import org.redkale.util.TypeToken;
|
||||
|
||||
/**
|
||||
* 缓存的方法对象
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@ClassDepends
|
||||
public class CacheAction {
|
||||
|
||||
@Resource
|
||||
private Environment environment;
|
||||
|
||||
@Resource
|
||||
private CacheManager manager;
|
||||
|
||||
private final CacheEntry cached;
|
||||
|
||||
private final Method method;
|
||||
|
||||
// Supplier对象的类型
|
||||
private final Type resultType;
|
||||
|
||||
// 缓存方法是否异步
|
||||
private final boolean async;
|
||||
|
||||
// 是否可以缓存null
|
||||
private final boolean nullable;
|
||||
|
||||
// 宿主对象的类
|
||||
private final Class serviceClass;
|
||||
|
||||
// 无法获取动态的Method,只能存方法名
|
||||
private final String methodName;
|
||||
|
||||
// 获取动态的字段名
|
||||
private final String fieldName;
|
||||
|
||||
// 方法参数名
|
||||
@Nullable
|
||||
private final String[] paramNames;
|
||||
|
||||
// 缓存的hash
|
||||
private String hash;
|
||||
|
||||
// 模板key
|
||||
String templetKey;
|
||||
|
||||
// 缓存key生成器
|
||||
private CacheKeyGenerator keyGenerator;
|
||||
|
||||
// 父对象
|
||||
private Object service;
|
||||
|
||||
// 本地缓存过期时长,Duration.ZERO为永不过期,为null表示不本地缓存
|
||||
private Duration localExpire;
|
||||
|
||||
// 远程缓存过期时长,Duration.ZERO为永不过期,为null表示不远程缓存
|
||||
private Duration remoteExpire;
|
||||
|
||||
CacheAction(CacheEntry cached, Method method, Class serviceClass, String[] paramNames, String fieldName) {
|
||||
this.cached = cached;
|
||||
this.method = method;
|
||||
this.nullable = cached.isNullable();
|
||||
this.serviceClass = Objects.requireNonNull(serviceClass);
|
||||
this.paramNames = paramNames;
|
||||
this.methodName = method.getName();
|
||||
this.fieldName = Objects.requireNonNull(fieldName);
|
||||
this.templetKey = cached.getKey();
|
||||
Type returnType = method.getGenericReturnType();
|
||||
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
|
||||
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
|
||||
}
|
||||
|
||||
void init(ResourceFactory resourceFactory, Object service) {
|
||||
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.templetKey = key;
|
||||
if (key.startsWith("@")) { // 动态加载缓存key生成器
|
||||
String generatorName = key.substring(1);
|
||||
this.keyGenerator = resourceFactory.findChild(generatorName, CacheKeyGenerator.class);
|
||||
} else {
|
||||
MultiHashKey dynKey = MultiHashKey.create(paramNames, key);
|
||||
this.keyGenerator = CacheKeyGenerator.create(dynKey);
|
||||
}
|
||||
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,
|
||||
keyGenerator.generate(service, this, args),
|
||||
resultType,
|
||||
nullable,
|
||||
localExpire,
|
||||
remoteExpire,
|
||||
supplier0);
|
||||
} else {
|
||||
return manager.bothGetSet(
|
||||
hash,
|
||||
keyGenerator.generate(service, this, 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)));
|
||||
}
|
||||
}
|
||||
|
||||
public CacheEntry getCached() {
|
||||
return cached;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{"
|
||||
+ "\"serviceClass\":" + serviceClass.getName()
|
||||
+ ",\"methodName\":\"" + methodName + "\""
|
||||
+ ",\"fieldName\":\"" + fieldName + "\""
|
||||
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(method.getParameterTypes())
|
||||
+ ",\"paramNames\":" + JsonConvert.root().convertTo(paramNames)
|
||||
+ ",\"templetKey\":\"" + templetKey + "\""
|
||||
+ ",\"resultType\":\"" + resultType + "\""
|
||||
+ ",\"cache\":" + cached
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,249 +1,249 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.redkale.asm.AnnotationVisitor;
|
||||
import org.redkale.asm.AsmMethodBean;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.asm.Asms;
|
||||
import org.redkale.asm.ClassWriter;
|
||||
import org.redkale.asm.FieldVisitor;
|
||||
import org.redkale.asm.Handle;
|
||||
import org.redkale.asm.Label;
|
||||
import org.redkale.asm.MethodVisitor;
|
||||
import org.redkale.asm.Opcodes;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.service.LoadMode;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.ThrowSupplier;
|
||||
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 List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class, DynForCache.class);
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getSimpleName());
|
||||
|
||||
private Map<String, CacheAction> actionMap;
|
||||
|
||||
public CacheAsmMethodBoost(boolean remote, Class serviceType) {
|
||||
super(remote, serviceType);
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
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.visitMaxs(20, 20);
|
||||
mv.visitEnd();
|
||||
CacheAction action = new CacheAction(
|
||||
new CacheEntry(cached), method, serviceType, methodBean.fieldNameArray(), 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, serviceType, methodBean.fieldNameArray(), dynFieldName);
|
||||
actionMap.put(dynFieldName, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
actionMap.forEach((field, action) -> {
|
||||
try {
|
||||
resourceFactory.inject(action);
|
||||
action.init(resourceFactory, service);
|
||||
if (action.templetKey.indexOf('@') < 0
|
||||
&& action.templetKey.indexOf('{') < 0
|
||||
&& action.getMethod().getParameterCount() > 0) {
|
||||
// 一般有参数的方法,Cached.key应该是动态的
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
action.getMethod() + " has parameters but @" + Cached.class.getSimpleName()
|
||||
+ ".key not contains parameter");
|
||||
}
|
||||
Field c = clazz.getDeclaredField(field);
|
||||
c.setAccessible(true);
|
||||
resourceFactory.inject(action);
|
||||
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
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.redkale.asm.AnnotationVisitor;
|
||||
import org.redkale.asm.AsmMethodBean;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.asm.Asms;
|
||||
import org.redkale.asm.ClassWriter;
|
||||
import org.redkale.asm.FieldVisitor;
|
||||
import org.redkale.asm.Handle;
|
||||
import org.redkale.asm.Label;
|
||||
import org.redkale.asm.MethodVisitor;
|
||||
import org.redkale.asm.Opcodes;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.service.LoadMode;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.ThrowSupplier;
|
||||
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 List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class, DynForCache.class);
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getSimpleName());
|
||||
|
||||
private Map<String, CacheAction> actionMap;
|
||||
|
||||
public CacheAsmMethodBoost(boolean remote, Class serviceType) {
|
||||
super(remote, serviceType);
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
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.visitMaxs(20, 20);
|
||||
mv.visitEnd();
|
||||
CacheAction action = new CacheAction(
|
||||
new CacheEntry(cached), method, serviceType, methodBean.fieldNameArray(), 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, serviceType, methodBean.fieldNameArray(), dynFieldName);
|
||||
actionMap.put(dynFieldName, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
actionMap.forEach((field, action) -> {
|
||||
try {
|
||||
resourceFactory.inject(action);
|
||||
action.init(resourceFactory, service);
|
||||
if (action.templetKey.indexOf('@') < 0
|
||||
&& action.templetKey.indexOf('{') < 0
|
||||
&& action.getMethod().getParameterCount() > 0) {
|
||||
// 一般有参数的方法,Cached.key应该是动态的
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
action.getMethod() + " has parameters but @" + Cached.class.getSimpleName()
|
||||
+ ".key not contains parameter");
|
||||
}
|
||||
Field c = clazz.getDeclaredField(field);
|
||||
c.setAccessible(true);
|
||||
resourceFactory.inject(action);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
146
src/main/java/org/redkale/cache/spi/CacheEntry.java
vendored
146
src/main/java/org/redkale/cache/spi/CacheEntry.java
vendored
@@ -1,73 +1,73 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/** @author zhangjx */
|
||||
public class CacheEntry {
|
||||
|
||||
private String key;
|
||||
|
||||
private String hash;
|
||||
|
||||
private String localExpire;
|
||||
|
||||
private String remoteExpire;
|
||||
|
||||
private TimeUnit timeUnit;
|
||||
|
||||
private boolean nullable;
|
||||
|
||||
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(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 getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String getLocalExpire() {
|
||||
return localExpire;
|
||||
}
|
||||
|
||||
public String getRemoteExpire() {
|
||||
return remoteExpire;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return timeUnit;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/** @author zhangjx */
|
||||
public class CacheEntry {
|
||||
|
||||
private String key;
|
||||
|
||||
private String hash;
|
||||
|
||||
private String localExpire;
|
||||
|
||||
private String remoteExpire;
|
||||
|
||||
private TimeUnit timeUnit;
|
||||
|
||||
private boolean nullable;
|
||||
|
||||
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(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 getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String getLocalExpire() {
|
||||
return localExpire;
|
||||
}
|
||||
|
||||
public String getRemoteExpire() {
|
||||
return remoteExpire;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return timeUnit;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.redkale.util.MultiHashKey;
|
||||
|
||||
/**
|
||||
* 缓存key生成器
|
||||
*
|
||||
* @see org.redkale.cache.Cached#key()
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface CacheKeyGenerator {
|
||||
|
||||
/**
|
||||
* 根据service和方法名生成key
|
||||
*
|
||||
* @param target Service对象
|
||||
* @param action CacheAction对象
|
||||
* @param params 参数值
|
||||
* @return key值
|
||||
*/
|
||||
public String generate(Object target, CacheAction action, Object... params);
|
||||
|
||||
/**
|
||||
* 生成器的名字
|
||||
*
|
||||
* @see org.redkale.cache.Cached#key()
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String name();
|
||||
|
||||
/**
|
||||
* 根据MultiHashKey生成一个CacheKeyGenerator
|
||||
* @param key MultiHashKey 不能为空
|
||||
* @return CacheKeyGenerator
|
||||
*/
|
||||
public static CacheKeyGenerator create(MultiHashKey key) {
|
||||
Objects.requireNonNull(key);
|
||||
return new CacheKeyGenerator() {
|
||||
@Override
|
||||
public String generate(Object target, CacheAction action, Object... params) {
|
||||
return key.keyFor(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.redkale.util.MultiHashKey;
|
||||
|
||||
/**
|
||||
* 缓存key生成器
|
||||
*
|
||||
* @see org.redkale.cache.Cached#key()
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface CacheKeyGenerator {
|
||||
|
||||
/**
|
||||
* 根据service和方法名生成key
|
||||
*
|
||||
* @param target Service对象
|
||||
* @param action CacheAction对象
|
||||
* @param params 参数值
|
||||
* @return key值
|
||||
*/
|
||||
public String generate(Object target, CacheAction action, Object... params);
|
||||
|
||||
/**
|
||||
* 生成器的名字
|
||||
*
|
||||
* @see org.redkale.cache.Cached#key()
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String name();
|
||||
|
||||
/**
|
||||
* 根据MultiHashKey生成一个CacheKeyGenerator
|
||||
* @param key MultiHashKey 不能为空
|
||||
* @return CacheKeyGenerator
|
||||
*/
|
||||
public static CacheKeyGenerator create(MultiHashKey key) {
|
||||
Objects.requireNonNull(key);
|
||||
return new CacheKeyGenerator() {
|
||||
@Override
|
||||
public String generate(Object target, CacheAction action, Object... params) {
|
||||
return key.keyFor(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.util.InstanceProvider;
|
||||
|
||||
/**
|
||||
* 自定义的CacheManager加载器, 如果标记@Priority加载器的优先级需要大于1000, 1000以下预留给官方加载器
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface CacheManagerProvider extends InstanceProvider<CacheManager> {}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.util.InstanceProvider;
|
||||
|
||||
/**
|
||||
* 自定义的CacheManager加载器, 如果标记@Priority加载器的优先级需要大于1000, 1000以下预留给官方加载器
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface CacheManagerProvider extends InstanceProvider<CacheManager> {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,153 +1,153 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.boot.Application;
|
||||
import org.redkale.boot.ModuleEngine;
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.inject.ResourceTypeLoader;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.InstanceProvider;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/** @author zhangjx */
|
||||
public class CacheModuleEngine extends ModuleEngine {
|
||||
|
||||
// 全局缓存管理器
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private AnyValue config;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态扩展类的方法
|
||||
*
|
||||
* @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);
|
||||
ConcurrentHashMap<String, CacheKeyGenerator> generatorMap = new ConcurrentHashMap<>();
|
||||
this.resourceFactory.register(new ResourceTypeLoader() {
|
||||
|
||||
@Override
|
||||
public Object load(
|
||||
ResourceFactory rf,
|
||||
String srcResourceName,
|
||||
Object srcObj,
|
||||
String resourceName,
|
||||
Field field,
|
||||
Object attachment) {
|
||||
try {
|
||||
CacheKeyGenerator generator = rf.find(resourceName, CacheKeyGenerator.class);
|
||||
if (generator == null) {
|
||||
return generator;
|
||||
}
|
||||
generator = generatorMap.computeIfAbsent(resourceName, n -> {
|
||||
for (CacheKeyGenerator instance :
|
||||
ServiceLoader.load(CacheKeyGenerator.class, application.getClassLoader())) {
|
||||
if (Objects.equals(n, instance.name())) {
|
||||
rf.inject(instance);
|
||||
if (instance instanceof Service) {
|
||||
((Service) instance).init(null);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (generator != null) {
|
||||
rf.register(resourceName, CacheKeyGenerator.class, generator);
|
||||
}
|
||||
return generator;
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, CacheKeyGenerator.class.getSimpleName() + " inject error", e);
|
||||
throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type resourceType() {
|
||||
return CacheKeyGenerator.class;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 进入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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.boot.Application;
|
||||
import org.redkale.boot.ModuleEngine;
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.inject.ResourceTypeLoader;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.InstanceProvider;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/** @author zhangjx */
|
||||
public class CacheModuleEngine extends ModuleEngine {
|
||||
|
||||
// 全局缓存管理器
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private AnyValue config;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态扩展类的方法
|
||||
*
|
||||
* @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);
|
||||
ConcurrentHashMap<String, CacheKeyGenerator> generatorMap = new ConcurrentHashMap<>();
|
||||
this.resourceFactory.register(new ResourceTypeLoader() {
|
||||
|
||||
@Override
|
||||
public Object load(
|
||||
ResourceFactory rf,
|
||||
String srcResourceName,
|
||||
Object srcObj,
|
||||
String resourceName,
|
||||
Field field,
|
||||
Object attachment) {
|
||||
try {
|
||||
CacheKeyGenerator generator = rf.find(resourceName, CacheKeyGenerator.class);
|
||||
if (generator == null) {
|
||||
return generator;
|
||||
}
|
||||
generator = generatorMap.computeIfAbsent(resourceName, n -> {
|
||||
for (CacheKeyGenerator instance :
|
||||
ServiceLoader.load(CacheKeyGenerator.class, application.getClassLoader())) {
|
||||
if (Objects.equals(n, instance.name())) {
|
||||
rf.inject(instance);
|
||||
if (instance instanceof Service) {
|
||||
((Service) instance).init(null);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (generator != null) {
|
||||
rf.register(resourceName, CacheKeyGenerator.class, generator);
|
||||
}
|
||||
return generator;
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, CacheKeyGenerator.class.getSimpleName() + " inject error", e);
|
||||
throw e instanceof RuntimeException ? (RuntimeException) e : new RedkaleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type resourceType() {
|
||||
return CacheKeyGenerator.class;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 进入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);
|
||||
}
|
||||
}
|
||||
|
||||
106
src/main/java/org/redkale/cache/spi/CacheValue.java
vendored
106
src/main/java/org/redkale/cache/spi/CacheValue.java
vendored
@@ -1,53 +1,53 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import org.redkale.convert.ConvertColumn;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
* 内部缓存对象
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 泛型
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public class CacheValue<T> {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
private T val;
|
||||
|
||||
public CacheValue() {}
|
||||
|
||||
protected CacheValue(T value) {
|
||||
this.val = value;
|
||||
}
|
||||
|
||||
public static <T> CacheValue<T> create(T value) {
|
||||
return new CacheValue(value);
|
||||
}
|
||||
|
||||
public static boolean isValid(CacheValue val) {
|
||||
return val != null;
|
||||
}
|
||||
|
||||
public static <T> T get(CacheValue val) {
|
||||
return isValid(val) ? (T) val.getVal() : null;
|
||||
}
|
||||
|
||||
public T getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setVal(T val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import org.redkale.convert.ConvertColumn;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
* 内部缓存对象
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 泛型
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public class CacheValue<T> {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
private T val;
|
||||
|
||||
public CacheValue() {}
|
||||
|
||||
protected CacheValue(T value) {
|
||||
this.val = value;
|
||||
}
|
||||
|
||||
public static <T> CacheValue<T> create(T value) {
|
||||
return new CacheValue(value);
|
||||
}
|
||||
|
||||
public static boolean isValid(CacheValue val) {
|
||||
return val != null;
|
||||
}
|
||||
|
||||
public static <T> T get(CacheValue val) {
|
||||
return isValid(val) ? (T) val.getVal() : null;
|
||||
}
|
||||
|
||||
public T getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setVal(T val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.service.LoadMode;
|
||||
|
||||
/**
|
||||
* {@link org.redkale.cache.Cached}注解的动态扩展版,会多一个字段信息 用于识别方法是否已经动态处理过
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface DynForCache {
|
||||
|
||||
String dynField();
|
||||
|
||||
String key();
|
||||
|
||||
String hash();
|
||||
|
||||
String localExpire();
|
||||
|
||||
String remoteExpire();
|
||||
|
||||
TimeUnit timeUnit();
|
||||
|
||||
boolean nullable();
|
||||
|
||||
LoadMode mode() default LoadMode.ANY;
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.service.LoadMode;
|
||||
|
||||
/**
|
||||
* {@link org.redkale.cache.Cached}注解的动态扩展版,会多一个字段信息 用于识别方法是否已经动态处理过
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.8.0
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface DynForCache {
|
||||
|
||||
String dynField();
|
||||
|
||||
String key();
|
||||
|
||||
String hash();
|
||||
|
||||
String localExpire();
|
||||
|
||||
String remoteExpire();
|
||||
|
||||
TimeUnit timeUnit();
|
||||
|
||||
boolean nullable();
|
||||
|
||||
LoadMode mode() default LoadMode.ANY;
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* cluster模式下的rpc client
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> message
|
||||
* @param <P> result
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface ClusterRpcClient<R, P> {
|
||||
|
||||
/**
|
||||
* 发送消息,需要响应
|
||||
*
|
||||
* @param message 消息体
|
||||
* @return 应答消息
|
||||
*/
|
||||
public CompletableFuture<P> sendMessage(final R message);
|
||||
|
||||
/**
|
||||
* 发送消息,无需响应
|
||||
*
|
||||
* @param message 消息体
|
||||
* @return 应答
|
||||
*/
|
||||
public CompletableFuture<Void> produceMessage(R message);
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* cluster模式下的rpc client
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> message
|
||||
* @param <P> result
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface ClusterRpcClient<R, P> {
|
||||
|
||||
/**
|
||||
* 发送消息,需要响应
|
||||
*
|
||||
* @param message 消息体
|
||||
* @return 应答消息
|
||||
*/
|
||||
public CompletableFuture<P> sendMessage(final R message);
|
||||
|
||||
/**
|
||||
* 发送消息,无需响应
|
||||
*
|
||||
* @param message 消息体
|
||||
* @return 应答
|
||||
*/
|
||||
public CompletableFuture<Void> produceMessage(R message);
|
||||
}
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/**
|
||||
* 不依赖MessageRecord则可兼容RPC方式
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.1.0
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
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(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);
|
||||
}
|
||||
|
||||
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(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(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());
|
||||
});
|
||||
}
|
||||
|
||||
// 格式: 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());
|
||||
}
|
||||
|
||||
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<Void> produceMessage(
|
||||
String topic, Serializable userid, String groupid, WebRequest request);
|
||||
|
||||
protected abstract String getNodeid();
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.cluster;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/**
|
||||
* 不依赖MessageRecord则可兼容RPC方式
|
||||
*
|
||||
* <p>详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @since 2.1.0
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
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(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);
|
||||
}
|
||||
|
||||
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(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(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());
|
||||
});
|
||||
}
|
||||
|
||||
// 格式: 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());
|
||||
}
|
||||
|
||||
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<Void> produceMessage(
|
||||
String topic, Serializable userid, String groupid, WebRequest request);
|
||||
|
||||
protected abstract String getNodeid();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user