Skip to content
GitLab
Explore
Sign in
Register
Commits on Source
3
New upstream version 1.8.0
· a3f12a81
Emmanuel Bourg
authored
Jul 31, 2018
a3f12a81
New upstream version 1.8.1
· 5e4f2284
Emmanuel Bourg
authored
Sep 19, 2018
5e4f2284
New upstream version 1.8.2
· 1474cd5e
Emmanuel Bourg
authored
Sep 19, 2018
1474cd5e
Expand all
Show whitespace changes
Inline
Side-by-side
.travis.yml
View file @
1474cd5e
...
...
@@ -3,19 +3,27 @@ language: java
sudo
:
false
dist
:
trusty
before_install
:
-
unset _JAVA_OPTIONS
-
wget https://raw.githubusercontent.com/sormuras/bach/master/install-jdk.sh
matrix
:
include
:
# Java 9
(openjdk-9.0.1 fails with java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty)
# Java 9
-
jdk
:
oraclejdk9
env
:
JDK
_RELEASE
='JDK 9' TARGET='-Pjava9'
env
:
JDK='JDK 9' TARGET='-Pjava9'
install
:
echo "The default Travis install script is being skipped!"
# Java 10
-
env
:
JDK
_RELEASE
='JDK 10' TARGET='-Pjava10'
install
:
. ./
.travis/
install-jdk.sh -F 10 -L
BC
L
-
env
:
JDK='JDK 10' TARGET='-Pjava10'
install
:
. ./install-jdk.sh -F 10 -L
GP
L
# Java 11
-
env
:
JDK_RELEASE='JDK 11-ea' TARGET='-Pjava11'
install
:
. ./.travis/install-jdk.sh -F 11 -L BCL
-
env
:
JDK='JDK 11' TARGET='-Pjava11'
install
:
. ./install-jdk.sh -F 11 -L BCL
# The following environments are known to fail
allow_failures
:
-
env
:
JDK='JDK 10' TARGET='-Pjava10'
-
env
:
JDK='JDK 11' TARGET='-Pjava11'
script
:
-
./mvnw install -DskipTests=true -Dmaven.javadoc.skip=true -Dnet.bytebuddy.test.ci=true
-
./mvnw jacoco:prepare-agent verify jacoco:report ${TARGET} -Pintegration -Dfindbugs.skip=true -Dnet.bytebuddy.test.ci=true
-
./mvnw install -DskipTests=true -Dmaven.javadoc.skip=true -Dnet.bytebuddy.test.ci=true
-pl '!byte-buddy-gradle-plugin'
-
./mvnw jacoco:prepare-agent verify jacoco:report ${TARGET} -Pintegration -Dfindbugs.skip=true -Dnet.bytebuddy.test.ci=true
-pl '!byte-buddy-gradle-plugin'
.travis/install-jdk.sh
deleted
100644 → 0
View file @
087b0365
#!/usr/bin/env bash
#
# Install JDK for Linux
#
# This script determines the most recent early-access build number,
# downloads the JDK archive to the user home directory and extracts
# it there.
#
# Example usage
#
# install-jdk.sh | install most recent (early-access) JDK
# install-jdk.sh -W /usr/opt | install most recent (early-access) JDK to /usr/opt
# install-jdk.sh -F 9 | install most recent OpenJDK 9
# install-jdk.sh -F 10 | install most recent OpenJDK 10
# install-jdk.sh -F 10 -L BCL | install most recent OracleJDK 10
# install-jdk.sh -F 11 | install most recent OpenJDK 10
# install-jdk.sh -F 11 -L BCL | install most recent OracleJDK 10
#
# Options
#
# -F f | Feature number of the JDK release [9|10|...]
# -B b | Build number of the JDK release [?|1|2...]
# -L l | License of the JDK [GPL|BCL]
# -W w | Working directory and install path [${HOME}]
#
# Exported environment variables
#
# JAVA_HOME is set to the extracted JDK directory
# PATH is prepended with ${JAVA_HOME}/bin
#
# (C) 2018 Christian Stein
#
# https://github.com/sormuras/bach/blob/master/install-jdk.sh
#
set
-e
JDK_FEATURE
=
'11'
JDK_BUILD
=
'?'
JDK_LICENSE
=
'GPL'
JDK_WORKSPACE
=
${
HOME
}
while
getopts
F:B:L:W: option
do
case
"
${
option
}
"
in
F
)
JDK_FEATURE
=
${
OPTARG
}
;;
B
)
JDK_BUILD
=
${
OPTARG
}
;;
L
)
JDK_LICENSE
=
${
OPTARG
}
;;
W
)
JDK_WORKSPACE
=
${
OPTARG
}
;;
esac
done
#
# Other constants
#
JDK_DOWNLOAD
=
'https://download.java.net/java'
JDK_BASENAME
=
'openjdk'
if
[
"
${
JDK_LICENSE
}
"
!=
'GPL'
]
;
then
JDK_BASENAME
=
'jdk'
fi
#
# 9
#
if
[
"
${
JDK_FEATURE
}
"
==
'9'
]
;
then
if
[
"
${
JDK_BUILD
}
"
==
'?'
]
;
then
TMP
=
$(
curl
-L
jdk.java.net/
${
JDK_FEATURE
}
)
TMP
=
"
${
TMP
#*<h1>JDK
}
"
# remove everything before the number
TMP
=
"
${
TMP
%%General-Availability Release*
}
"
# remove everything after the number
JDK_BUILD
=
"
$(
echo
-e
"
${
TMP
}
"
|
tr
-d
'[:space:]'
)
"
# remove all whitespace
fi
JDK_ARCHIVE
=
${
JDK_BASENAME
}
-
${
JDK_BUILD
}
_linux-x64_bin.tar.gz
JDK_URL
=
${
JDK_DOWNLOAD
}
/GA/jdk
${
JDK_FEATURE
}
/
${
JDK_BUILD
}
/binaries/
${
JDK_ARCHIVE
}
JDK_HOME
=
jdk-
${
JDK_BUILD
}
fi
#
# 10
#
if
[
"
${
JDK_FEATURE
}
"
==
'10'
]
;
then
if
[
"
${
JDK_BUILD
}
"
==
'?'
]
;
then
TMP
=
$(
curl
-L
jdk.java.net/
${
JDK_FEATURE
}
)
TMP
=
"
${
TMP
#*Most recent build
:
jdk-
${
JDK_FEATURE
}
+
}
"
# remove everything before the number
TMP
=
"
${
TMP
%%<*
}
"
# remove everything after the number
JDK_BUILD
=
"
$(
echo
-e
"
${
TMP
}
"
|
tr
-d
'[:space:]'
)
"
# remove all whitespace
fi
JDK_ARCHIVE
=
${
JDK_BASENAME
}
-
${
JDK_FEATURE
}
+
${
JDK_BUILD
}
_linux-x64_bin.tar.gz
JDK_URL
=
${
JDK_DOWNLOAD
}
/jdk
${
JDK_FEATURE
}
/archive/
${
JDK_BUILD
}
/
${
JDK_LICENSE
}
/
${
JDK_ARCHIVE
}
JDK_HOME
=
jdk-
${
JDK_FEATURE
}
fi
#
# 11
#
if
[
"
${
JDK_FEATURE
}
"
==
'11'
]
;
then
if
[
"
${
JDK_BUILD
}
"
==
'?'
]
;
then
TMP
=
$(
curl
-L
jdk.java.net/
${
JDK_FEATURE
}
)
TMP
=
"
${
TMP
#*Most recent build
:
jdk-
${
JDK_FEATURE
}
-ea+
}
"
# remove everything before the number
TMP
=
"
${
TMP
%%<*
}
"
# remove everything after the number
JDK_BUILD
=
"
$(
echo
-e
"
${
TMP
}
"
|
tr
-d
'[:space:]'
)
"
# remove all whitespace
fi
JDK_ARCHIVE
=
${
JDK_BASENAME
}
-
${
JDK_FEATURE
}
-ea
+
${
JDK_BUILD
}
_linux-x64_bin.tar.gz
JDK_URL
=
${
JDK_DOWNLOAD
}
/early_access/jdk
${
JDK_FEATURE
}
/
${
JDK_BUILD
}
/
${
JDK_LICENSE
}
/
${
JDK_ARCHIVE
}
JDK_HOME
=
jdk-
${
JDK_FEATURE
}
fi
#
# Create any missing intermediate paths, switch to workspace, download, unpack, switch back.
#
mkdir
-p
${
JDK_WORKSPACE
}
cd
${
JDK_WORKSPACE
}
wget
${
JDK_URL
}
tar
-xzf
${
JDK_ARCHIVE
}
cd
-
#
# Update environment and test-drive.
#
export
JAVA_HOME
=
${
JDK_WORKSPACE
}
/
${
JDK_HOME
}
export
PATH
=
${
JAVA_HOME
}
/bin:
$PATH
java
--version
byte-buddy-agent/pom.xml
View file @
1474cd5e
...
...
@@ -5,7 +5,7 @@
<parent>
<artifactId>
byte-buddy-parent
</artifactId>
<groupId>
net.bytebuddy
</groupId>
<version>
1.
7.11
</version>
<version>
1.
8.2
</version>
</parent>
<artifactId>
byte-buddy-agent
</artifactId>
...
...
byte-buddy-agent/src/main/java/net/bytebuddy/agent/ByteBuddyAgent.java
View file @
1474cd5e
...
...
@@ -364,7 +364,7 @@ public class ByteBuddyAgent {
private
static
void
install
(
AttachmentProvider
attachmentProvider
,
String
processId
,
String
argument
,
AgentProvider
agentProvider
)
{
AttachmentProvider
.
Accessor
attachmentAccessor
=
attachmentProvider
.
attempt
();
if
(!
attachmentAccessor
.
isAvailable
())
{
throw
new
IllegalStateException
(
"No compatible attachment provider is
not
available"
);
throw
new
IllegalStateException
(
"No compatible attachment provider is available"
);
}
try
{
if
(
ATTACHMENT_TYPE_EVALUATOR
.
requiresExternalAttachment
(
processId
))
{
...
...
byte-buddy-android/pom.xml
View file @
1474cd5e
...
...
@@ -5,7 +5,7 @@
<parent>
<artifactId>
byte-buddy-parent
</artifactId>
<groupId>
net.bytebuddy
</groupId>
<version>
1.
7.11
</version>
<version>
1.
8.2
</version>
</parent>
<artifactId>
byte-buddy-android
</artifactId>
...
...
byte-buddy-benchmark/pom.xml
View file @
1474cd5e
...
...
@@ -5,7 +5,7 @@
<parent>
<artifactId>
byte-buddy-parent
</artifactId>
<groupId>
net.bytebuddy
</groupId>
<version>
1.
7.11
</version>
<version>
1.
8.2
</version>
</parent>
<artifactId>
byte-buddy-benchmark
</artifactId>
...
...
byte-buddy-dep/pom.xml
View file @
1474cd5e
...
...
@@ -5,7 +5,7 @@
<parent>
<groupId>
net.bytebuddy
</groupId>
<artifactId>
byte-buddy-parent
</artifactId>
<version>
1.
7.11
</version>
<version>
1.
8.2
</version>
</parent>
<artifactId>
byte-buddy-dep
</artifactId>
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/ClassFileVersion.java
View file @
1474cd5e
...
...
@@ -72,9 +72,14 @@ public class ClassFileVersion implements Comparable<ClassFileVersion> {
public
static
final
ClassFileVersion
JAVA_V9
=
new
ClassFileVersion
(
Opcodes
.
V9
);
/**
* The class file version of Java 10
(preliminary)
.
* The class file version of Java 10.
*/
public
static
final
ClassFileVersion
JAVA_V10
=
new
ClassFileVersion
(
Opcodes
.
V9
+
1
);
public
static
final
ClassFileVersion
JAVA_V10
=
new
ClassFileVersion
(
Opcodes
.
V10
);
/**
* The class file version of Java 11 (preliminary).
*/
public
static
final
ClassFileVersion
JAVA_V11
=
new
ClassFileVersion
(
Opcodes
.
V10
+
1
);
/**
* A version locator for the executing JVM.
...
...
@@ -136,6 +141,8 @@ public class ClassFileVersion implements Comparable<ClassFileVersion> {
return
JAVA_V9
;
}
else
if
(
javaVersionString
.
equals
(
"1.10"
)
||
javaVersionString
.
equals
(
"10"
))
{
return
JAVA_V10
;
}
else
if
(
javaVersionString
.
equals
(
"1.11"
)
||
javaVersionString
.
equals
(
"11"
))
{
return
JAVA_V11
;
}
else
{
throw
new
IllegalArgumentException
(
"Unknown Java version string: "
+
javaVersionString
);
}
...
...
@@ -171,6 +178,8 @@ public class ClassFileVersion implements Comparable<ClassFileVersion> {
return
JAVA_V9
;
case
10
:
return
JAVA_V10
;
case
11
:
return
JAVA_V11
;
default
:
throw
new
IllegalArgumentException
(
"Unknown Java version: "
+
javaVersion
);
}
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/agent/builder/AgentBuilder.java
View file @
1474cd5e
...
...
@@ -1372,7 +1372,7 @@ public interface AgentBuilder {
*
* @return A listener writing events to the standard output stream.
*/
public
static
Listener
toSystemOut
()
{
public
static
StreamWriting
toSystemOut
()
{
return
new
StreamWriting
(
System
.
out
);
}
...
...
@@ -1381,10 +1381,28 @@ public interface AgentBuilder {
*
* @return A listener writing events to the standard error stream.
*/
public
static
Listener
toSystemError
()
{
public
static
StreamWriting
toSystemError
()
{
return
new
StreamWriting
(
System
.
err
);
}
/**
* Returns a version of this listener that only reports successfully transformed classes and failed transformations.
*
* @return A version of this listener that only reports successfully transformed classes and failed transformations.
*/
public
Listener
withTransformationsOnly
()
{
return
new
WithTransformationsOnly
(
this
);
}
/**
* Returns a version of this listener that only reports failed transformations.
*
* @return A version of this listener that only reports failed transformations.
*/
public
Listener
withErrorsOnly
()
{
return
new
WithErrorsOnly
(
this
);
}
@Override
public
void
onDiscovery
(
String
typeName
,
ClassLoader
classLoader
,
JavaModule
module
,
boolean
loaded
)
{
printStream
.
printf
(
PREFIX
+
" DISCOVERY %s [%s, %s, loaded=%b]%n"
,
typeName
,
classLoader
,
module
,
loaded
);
...
...
@@ -1477,6 +1495,63 @@ public interface AgentBuilder {
}
}
/**
* A listener that only delegates events if they are successful or failed transformations.
*/
@EqualsAndHashCode
(
callSuper
=
false
)
class
WithTransformationsOnly
extends
Listener
.
Adapter
{
/**
* The delegate listener.
*/
private
final
Listener
delegate
;
/**
* Creates a new listener that only delegates events if they are succesful or failed transformations.
*
* @param delegate The delegate listener.
*/
public
WithTransformationsOnly
(
Listener
delegate
)
{
this
.
delegate
=
delegate
;
}
@Override
public
void
onTransformation
(
TypeDescription
typeDescription
,
ClassLoader
classLoader
,
JavaModule
module
,
boolean
loaded
,
DynamicType
dynamicType
)
{
delegate
.
onTransformation
(
typeDescription
,
classLoader
,
module
,
loaded
,
dynamicType
);
}
@Override
public
void
onError
(
String
typeName
,
ClassLoader
classLoader
,
JavaModule
module
,
boolean
loaded
,
Throwable
throwable
)
{
delegate
.
onError
(
typeName
,
classLoader
,
module
,
loaded
,
throwable
);
}
}
/**
* A listener that only delegates events if they are failed transformations.
*/
@EqualsAndHashCode
(
callSuper
=
false
)
class
WithErrorsOnly
extends
Listener
.
Adapter
{
/**
* The delegate listener.
*/
private
final
Listener
delegate
;
/**
* Creates a new listener that only delegates events if they are failed transformations.
*
* @param delegate The delegate listener.
*/
public
WithErrorsOnly
(
Listener
delegate
)
{
this
.
delegate
=
delegate
;
}
@Override
public
void
onError
(
String
typeName
,
ClassLoader
classLoader
,
JavaModule
module
,
boolean
loaded
,
Throwable
throwable
)
{
delegate
.
onError
(
typeName
,
classLoader
,
module
,
loaded
,
throwable
);
}
}
/**
* A listener that adds read-edges to any module of an instrumented class upon its transformation.
*/
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
View file @
1474cd5e
This diff is collapsed.
Click to expand it.
byte-buddy-dep/src/main/java/net/bytebuddy/build/HashCodeAndEqualsPlugin.java
0 → 100644
View file @
1474cd5e
package
net.bytebuddy.build
;
import
lombok.EqualsAndHashCode
;
import
net.bytebuddy.description.annotation.AnnotationDescription
;
import
net.bytebuddy.description.field.FieldDescription
;
import
net.bytebuddy.description.method.MethodList
;
import
net.bytebuddy.description.type.TypeDefinition
;
import
net.bytebuddy.description.type.TypeDescription
;
import
net.bytebuddy.dynamic.DynamicType
;
import
net.bytebuddy.implementation.EqualsMethod
;
import
net.bytebuddy.implementation.HashCodeMethod
;
import
net.bytebuddy.matcher.ElementMatcher
;
import
net.bytebuddy.matcher.ElementMatchers
;
import
java.lang.annotation.*
;
import
static
net
.
bytebuddy
.
matcher
.
ElementMatchers
.*;
/**
* A build tool plugin that adds {@link Object#hashCode()} and {@link Object#equals(Object)} methods to a class if the
* {@link Enhance} annotation is present and no explicit method declaration was added.
*/
@EqualsAndHashCode
public
class
HashCodeAndEqualsPlugin
implements
Plugin
{
@Override
public
boolean
matches
(
TypeDescription
target
)
{
return
target
.
getDeclaredAnnotations
().
isAnnotationPresent
(
Enhance
.
class
);
}
@Override
public
DynamicType
.
Builder
<?>
apply
(
DynamicType
.
Builder
<?>
builder
,
TypeDescription
typeDescription
)
{
Enhance
enhance
=
typeDescription
.
getDeclaredAnnotations
().
ofType
(
Enhance
.
class
).
loadSilent
();
if
(
typeDescription
.
getDeclaredMethods
().
filter
(
isHashCode
()).
isEmpty
())
{
builder
=
builder
.
method
(
isHashCode
()).
intercept
(
enhance
.
invokeSuper
()
.
hashCodeMethod
(
typeDescription
)
.
withIgnoredFields
(
enhance
.
includeSyntheticFields
()
?
ElementMatchers
.<
FieldDescription
>
none
()
:
ElementMatchers
.<
FieldDescription
>
isSynthetic
())
.
withIgnoredFields
(
new
ValueMatcher
(
ValueHandling
.
Sort
.
IGNORE
))
.
withNonNullableFields
(
nonNullable
(
new
ValueMatcher
(
ValueHandling
.
Sort
.
REVERSE_NULLABILITY
))));
}
if
(
typeDescription
.
getDeclaredMethods
().
filter
(
isEquals
()).
isEmpty
())
{
EqualsMethod
equalsMethod
=
enhance
.
invokeSuper
()
.
equalsMethod
(
typeDescription
)
.
withIgnoredFields
(
enhance
.
includeSyntheticFields
()
?
ElementMatchers
.<
FieldDescription
>
none
()
:
ElementMatchers
.<
FieldDescription
>
isSynthetic
())
.
withIgnoredFields
(
new
ValueMatcher
(
ValueHandling
.
Sort
.
IGNORE
))
.
withNonNullableFields
(
nonNullable
(
new
ValueMatcher
(
ValueHandling
.
Sort
.
REVERSE_NULLABILITY
)));
builder
=
builder
.
method
(
isEquals
()).
intercept
(
enhance
.
permitSubclassEquality
()
?
equalsMethod
.
withSubclassEquality
()
:
equalsMethod
);
}
return
builder
;
}
/**
* Resolves the matcher to identify non-nullable fields.
*
* @param matcher The matcher that identifies fields that are either nullable or non-nullable.
* @return The actual matcher to identify non-nullable fields.
*/
protected
ElementMatcher
<
FieldDescription
>
nonNullable
(
ElementMatcher
<
FieldDescription
>
matcher
)
{
return
matcher
;
}
/**
* A version of the {@link HashCodeAndEqualsPlugin} that assumes that all fields are non-nullable unless they are explicitly marked.
*/
@EqualsAndHashCode
(
callSuper
=
true
)
public
static
class
WithNonNullableFields
extends
HashCodeAndEqualsPlugin
{
@Override
protected
ElementMatcher
<
FieldDescription
>
nonNullable
(
ElementMatcher
<
FieldDescription
>
matcher
)
{
return
not
(
matcher
);
}
}
/**
* Instructs the {@link HashCodeAndEqualsPlugin} to generate {@link Object#hashCode()} and {@link Object#equals(Object)} for the annotated
* class unless these methods are already declared explicitly.
*/
@Documented
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Enhance
{
/**
* Determines the base value of any added method, i.e. if hash code or equality is based on the super type or not.
*
* @return A strategy for determining the base value.
*/
InvokeSuper
invokeSuper
()
default
InvokeSuper
.
IF_DECLARED
;
/**
* Determines if synthetic fields should be included in the hash code and equality contract.
*
* @return {@code true} if synthetic fields should be included.
*/
boolean
includeSyntheticFields
()
default
false
;
/**
* Determines if instances subclasses of the instrumented type are accepted upon an equality check.
*
* @return {@code true} if instances subclasses of the instrumented type are accepted upon an equality check.
*/
boolean
permitSubclassEquality
()
default
false
;
/**
* A strategy for determining the base value of a hash code or equality contract.
*/
enum
InvokeSuper
{
/**
* Only invokes the super method's hash code and equality methods if any super class that is not {@link Object} explicitly defines such a method.
*/
IF_DECLARED
{
@Override
protected
HashCodeMethod
hashCodeMethod
(
TypeDescription
instrumentedType
)
{
TypeDefinition
typeDefinition
=
instrumentedType
.
getSuperClass
();
while
(
typeDefinition
!=
null
&&
!
typeDefinition
.
represents
(
Object
.
class
))
{
if
(
typeDefinition
.
asErasure
().
getDeclaredAnnotations
().
isAnnotationPresent
(
Enhance
.
class
))
{
return
HashCodeMethod
.
usingSuperClassOffset
();
}
MethodList
<?>
hashCode
=
typeDefinition
.
getDeclaredMethods
().
filter
(
isHashCode
());
if
(!
hashCode
.
isEmpty
())
{
return
hashCode
.
getOnly
().
isAbstract
()
?
HashCodeMethod
.
usingDefaultOffset
()
:
HashCodeMethod
.
usingSuperClassOffset
();
}
typeDefinition
=
typeDefinition
.
getSuperClass
();
}
return
HashCodeMethod
.
usingDefaultOffset
();
}
@Override
protected
EqualsMethod
equalsMethod
(
TypeDescription
instrumentedType
)
{
TypeDefinition
typeDefinition
=
instrumentedType
.
getSuperClass
();
while
(
typeDefinition
!=
null
&&
!
typeDefinition
.
represents
(
Object
.
class
))
{
if
(
typeDefinition
.
asErasure
().
getDeclaredAnnotations
().
isAnnotationPresent
(
Enhance
.
class
))
{
return
EqualsMethod
.
requiringSuperClassEquality
();
}
MethodList
<?>
hashCode
=
typeDefinition
.
getDeclaredMethods
().
filter
(
isHashCode
());
if
(!
hashCode
.
isEmpty
())
{
return
hashCode
.
getOnly
().
isAbstract
()
?
EqualsMethod
.
isolated
()
:
EqualsMethod
.
requiringSuperClassEquality
();
}
typeDefinition
=
typeDefinition
.
getSuperClass
().
asErasure
();
}
return
EqualsMethod
.
isolated
();
}
},
/**
* Only invokes the super method's hash code and equality methods if the super class is also annotated with {@link Enhance}.
*/
IF_ANNOTATED
{
@Override
protected
HashCodeMethod
hashCodeMethod
(
TypeDescription
instrumentedType
)
{
TypeDefinition
superClass
=
instrumentedType
.
getSuperClass
();
return
superClass
!=
null
&&
superClass
.
asErasure
().
getDeclaredAnnotations
().
isAnnotationPresent
(
Enhance
.
class
)
?
HashCodeMethod
.
usingSuperClassOffset
()
:
HashCodeMethod
.
usingDefaultOffset
();
}
@Override
protected
EqualsMethod
equalsMethod
(
TypeDescription
instrumentedType
)
{
TypeDefinition
superClass
=
instrumentedType
.
getSuperClass
();
return
superClass
!=
null
&&
superClass
.
asErasure
().
getDeclaredAnnotations
().
isAnnotationPresent
(
Enhance
.
class
)
?
EqualsMethod
.
requiringSuperClassEquality
()
:
EqualsMethod
.
isolated
();
}
},
/**
* Always invokes the super class's hash code and equality methods.
*/
ALWAYS
{
@Override
protected
HashCodeMethod
hashCodeMethod
(
TypeDescription
instrumentedType
)
{
return
HashCodeMethod
.
usingSuperClassOffset
();
}
@Override
protected
EqualsMethod
equalsMethod
(
TypeDescription
instrumentedType
)
{
return
EqualsMethod
.
requiringSuperClassEquality
();
}
},
/**
* Never invokes the super class's hash code and equality methods.
*/
NEVER
{
@Override
protected
HashCodeMethod
hashCodeMethod
(
TypeDescription
instrumentedType
)
{
return
HashCodeMethod
.
usingDefaultOffset
();
}
@Override
protected
EqualsMethod
equalsMethod
(
TypeDescription
instrumentedType
)
{
return
EqualsMethod
.
isolated
();
}
};
/**
* Resolves the hash code method to use.
*
* @param instrumentedType The instrumented type.
* @return The hash code method to use.
*/
protected
abstract
HashCodeMethod
hashCodeMethod
(
TypeDescription
instrumentedType
);
/**
* Resolves the equals method to use.
*
* @param instrumentedType The instrumented type.
* @return The equals method to use.
*/
protected
abstract
EqualsMethod
equalsMethod
(
TypeDescription
instrumentedType
);
}
}
/**
* Determines how a field should be used within generated hash code and equality methods.
*/
@Documented
@Target
(
ElementType
.
FIELD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
ValueHandling
{
/**
* Determines the handling of the annotated field.
*
* @return The handling of the annotated field.
*/
Sort
value
();
/**
* Determines how a field should be handled.
*/
enum
Sort
{
/**
* Excludes the field from hash code and equality methods.
*/
IGNORE
,
/**
* Reverses the nullability of the field, i.e. assumes this field to be non-null or {@code null} if {@link WithNonNullableFields} is used.
*/
REVERSE_NULLABILITY
}
}
/**
* An element matcher for a {@link ValueHandling} annotation.
*/
@EqualsAndHashCode
protected
static
class
ValueMatcher
implements
ElementMatcher
<
FieldDescription
>
{
/**
* The matched value.
*/
private
final
ValueHandling
.
Sort
sort
;
/**
* Creates a new value matcher.
*
* @param sort The matched value.
*/
protected
ValueMatcher
(
ValueHandling
.
Sort
sort
)
{
this
.
sort
=
sort
;
}
@Override
public
boolean
matches
(
FieldDescription
target
)
{
AnnotationDescription
.
Loadable
<
ValueHandling
>
annotation
=
target
.
getDeclaredAnnotations
().
ofType
(
ValueHandling
.
class
);
return
annotation
!=
null
&&
annotation
.
loadSilent
().
value
()
==
sort
;
}
}
}
byte-buddy-dep/src/main/java/net/bytebuddy/build/ToStringPlugin.java
0 → 100644
View file @
1474cd5e
package
net.bytebuddy.build
;
import
lombok.EqualsAndHashCode
;
import
net.bytebuddy.description.field.FieldDescription
;
import
net.bytebuddy.description.type.TypeDescription
;
import
net.bytebuddy.dynamic.DynamicType
;
import
net.bytebuddy.implementation.ToStringMethod
;
import
net.bytebuddy.matcher.ElementMatchers
;
import
java.lang.annotation.*
;
import
static
net
.
bytebuddy
.
matcher
.
ElementMatchers
.
isAnnotatedWith
;
import
static
net
.
bytebuddy
.
matcher
.
ElementMatchers
.
isToString
;
/**
* A build tool plugin that adds a {@link Object#toString()} and method to a class if the {@link Enhance} annotation is present and no
* explicit method declaration was added.
*/
@EqualsAndHashCode
public
class
ToStringPlugin
implements
Plugin
{
@Override
public
boolean
matches
(
TypeDescription
target
)
{
return
target
.
getDeclaredAnnotations
().
isAnnotationPresent
(
Enhance
.
class
);
}
@Override
public
DynamicType
.
Builder
<?>
apply
(
DynamicType
.
Builder
<?>
builder
,
TypeDescription
typeDescription
)
{
Enhance
enhance
=
typeDescription
.
getDeclaredAnnotations
().
ofType
(
Enhance
.
class
).
loadSilent
();
if
(
typeDescription
.
getDeclaredMethods
().
filter
(
isToString
()).
isEmpty
())
{
builder
=
builder
.
method
(
isToString
()).
intercept
(
ToStringMethod
.
prefixedBy
(
enhance
.
prefix
().
getPrefixResolver
())
.
withIgnoredFields
(
enhance
.
includeSyntheticFields
()
?
ElementMatchers
.<
FieldDescription
>
none
()
:
ElementMatchers
.<
FieldDescription
>
isSynthetic
())
.
withIgnoredFields
(
isAnnotatedWith
(
Exclude
.
class
)));
}
return
builder
;
}
/**
* Instructs the {@link ToStringPlugin} to generate a {@link Object#toString()} method for the annotated class unless this method
* is already declared explicitly.
*/
@Documented
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Enhance
{
/**
* Determines the prefix to be used for the string representation prior to adding field values.
*
* @return The prefix to use.
*/
Prefix
prefix
()
default
Prefix
.
SIMPLE
;
/**
* Determines if synthetic fields should be included in the string representation.
*
* @return {@code true} if synthetic fields should be included.
*/
boolean
includeSyntheticFields
()
default
false
;
/**
* A strategy for defining a prefix.
*/
enum
Prefix
{
/**
* Determines the use of a fully qualified class name as a prefix.
*/
FULLY_QUALIFIED
(
ToStringMethod
.
PrefixResolver
.
Default
.
FULLY_QUALIFIED_CLASS_NAME
),
/**
* Determines the use of the canonical class name as a prefix.
*/
CANONICAL
(
ToStringMethod
.
PrefixResolver
.
Default
.
CANONICAL_CLASS_NAME
),
/**
* Determines the use of the simple class name as a prefix.
*/
SIMPLE
(
ToStringMethod
.
PrefixResolver
.
Default
.
SIMPLE_CLASS_NAME
);
/**
* The prefix resolver to use.
*/
private
final
ToStringMethod
.
PrefixResolver
.
Default
prefixResolver
;
/**
* Creates a new prefix.
*
* @param prefixResolver The prefix resolver to use.
*/
Prefix
(
ToStringMethod
.
PrefixResolver
.
Default
prefixResolver
)
{
this
.
prefixResolver
=
prefixResolver
;
}
/**
* Returns the prefix resolver to use.
*
* @return The prefix resolver to use.
*/
protected
ToStringMethod
.
PrefixResolver
.
Default
getPrefixResolver
()
{
return
prefixResolver
;
}
}
}
/**
* Determines that the annotated field is excluded from a string representation of the {@link ToStringPlugin}.
*/
@Documented
@Target
(
ElementType
.
FIELD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Exclude
{
/* does not declare any properties */
}
}
byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java
View file @
1474cd5e
...
...
@@ -7016,27 +7016,36 @@ public interface TypeDescription extends TypeDefinition, ByteCodeElement, TypeVa
@Override
public
String
getCanonicalName
()
{
return
isAnonymousClass
()
||
isLocalClass
()
?
NO_NAME
:
getName
().
replace
(
'$'
,
'.'
);
if
(
isAnonymousClass
()
||
isLocalClass
())
{
return
NO_NAME
;
}
String
internalName
=
getInternalName
();
TypeDescription
enclosingType
=
getEnclosingType
();
if
(
enclosingType
!=
null
&&
internalName
.
startsWith
(
enclosingType
.
getInternalName
()
+
"$"
))
{
return
enclosingType
.
getCanonicalName
()
+
"."
+
internalName
.
substring
(
enclosingType
.
getInternalName
().
length
()
+
1
);
}
else
{
return
getName
();
}
}
@Override
public
String
getSimpleName
()
{
String
internalName
=
getInternalName
();
int
simpleNameIndex
=
internalName
.
lastIndexOf
(
'$'
);
simpleNameIndex
=
simpleNameIndex
==
-
1
?
internalName
.
lastIndexOf
(
'/'
)
:
simpleNameIndex
;
TypeDescription
enclosingType
=
getEnclosingType
();
int
simpleNameIndex
;
if
(
enclosingType
!=
null
&&
internalName
.
startsWith
(
enclosingType
.
getInternalName
()
+
"$"
))
{
simpleNameIndex
=
enclosingType
.
getInternalName
().
length
()
+
1
;
}
else
{
simpleNameIndex
=
internalName
.
lastIndexOf
(
'/'
);
if
(
simpleNameIndex
==
-
1
)
{
return
internalName
;
}
else
{
}
}
while
(
simpleNameIndex
<
internalName
.
length
()
&&
!
Character
.
isLetter
(
internalName
.
charAt
(
simpleNameIndex
)))
{
simpleNameIndex
+=
1
;
}
return
internalName
.
substring
(
simpleNameIndex
);
}
}
@Override
public
StackSize
getStackSize
()
{
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeList.java
View file @
1474cd5e
...
...
@@ -54,6 +54,11 @@ public interface TypeList extends FilterableList<TypeDescription, TypeList> {
protected
TypeList
wrap
(
List
<
TypeDescription
>
values
)
{
return
new
Explicit
(
values
);
}
@Override
public
int
getStackSize
()
{
return
StackSize
.
of
(
this
);
}
}
/**
...
...
@@ -105,11 +110,6 @@ public interface TypeList extends FilterableList<TypeDescription, TypeList> {
?
NO_INTERFACES
:
internalNames
;
}
@Override
public
int
getStackSize
()
{
return
StackSize
.
sizeOf
(
types
);
}
}
/**
...
...
@@ -161,15 +161,6 @@ public interface TypeList extends FilterableList<TypeDescription, TypeList> {
?
NO_INTERFACES
:
internalNames
;
}
@Override
public
int
getStackSize
()
{
int
stackSize
=
0
;
for
(
TypeDescription
typeDescription
:
typeDescriptions
)
{
stackSize
+=
typeDescription
.
getStackSize
().
getSize
();
}
return
stackSize
;
}
}
/**
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/DynamicType.java
View file @
1474cd5e
...
...
@@ -19,9 +19,7 @@ import net.bytebuddy.description.type.TypeVariableToken;
import
net.bytebuddy.dynamic.loading.ClassLoadingStrategy
;
import
net.bytebuddy.dynamic.loading.InjectionClassLoader
;
import
net.bytebuddy.dynamic.scaffold.*
;
import
net.bytebuddy.implementation.FieldAccessor
;
import
net.bytebuddy.implementation.Implementation
;
import
net.bytebuddy.implementation.LoadedTypeInitializer
;
import
net.bytebuddy.implementation.*
;
import
net.bytebuddy.implementation.attribute.*
;
import
net.bytebuddy.implementation.auxiliary.AuxiliaryType
;
import
net.bytebuddy.implementation.bytecode.ByteCodeAppender
;
...
...
@@ -887,6 +885,24 @@ public interface DynamicType {
*/
MethodDefinition
.
ImplementationDefinition
<
T
>
invokable
(
LatentMatcher
<?
super
MethodDescription
>
matcher
);
/**
* Implements {@link Object#hashCode()} and {@link Object#equals(Object)} methods for the instrumented type if those
* methods are not declared as {@code final} by a super class. The implementations do not consider any implementations
* of a super class and compare a class field by field without considering synthetic fields.
*
* @return A new type builder that defines {@link Object#hashCode()} and {@link Object#equals(Object)} methods accordingly.
*/
Builder
<
T
>
withHashCodeEquals
();
/**
* Implements a {@link Object#toString()} method for the instrumented type if such a method is not declared as {@code final}
* by a super class. The implementation prefixes the string with the simple class name and prints each non-synthetic field's
* value after the field's name.
*
* @return A new type builder that defines {@link Object#toString()} method accordingly.
*/
Builder
<
T
>
withToString
();
/**
* <p>
* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown.
...
...
@@ -2629,6 +2645,19 @@ public interface DynamicType {
return
invokable
(
new
LatentMatcher
.
Resolved
<
MethodDescription
>(
matcher
));
}
@Override
public
Builder
<
S
>
withHashCodeEquals
()
{
return
method
(
isHashCode
())
.
intercept
(
HashCodeMethod
.
usingDefaultOffset
().
withIgnoredFields
(
isSynthetic
()))
.
method
(
isEquals
())
.
intercept
(
EqualsMethod
.
isolated
().
withIgnoredFields
(
isSynthetic
()));
}
@Override
public
Builder
<
S
>
withToString
()
{
return
method
(
isToString
()).
intercept
(
ToStringMethod
.
prefixedBySimpleClassName
());
}
@Override
public
Unloaded
<
S
>
make
(
TypePool
typePool
)
{
return
make
(
TypeResolutionStrategy
.
Passive
.
INSTANCE
,
typePool
);
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/TypeWriter.java
View file @
1474cd5e
...
...
@@ -3968,6 +3968,13 @@ public interface TypeWriter<T> {
:
IGNORE_ANNOTATION
;
}
@Override
public
void
visitAnnotableParameterCount
(
int
count
,
boolean
visible
)
{
if
(
annotationRetention
.
isEnabled
())
{
super
.
visitAnnotableParameterCount
(
count
,
visible
);
}
}
@Override
public
AnnotationVisitor
visitParameterAnnotation
(
int
index
,
String
descriptor
,
boolean
visible
)
{
return
annotationRetention
.
isEnabled
()
...
...
@@ -4043,6 +4050,13 @@ public interface TypeWriter<T> {
:
IGNORE_ANNOTATION
;
}
@Override
public
void
visitAnnotableParameterCount
(
int
count
,
boolean
visible
)
{
if
(
annotationRetention
.
isEnabled
())
{
super
.
visitAnnotableParameterCount
(
count
,
visible
);
}
}
@Override
public
AnnotationVisitor
visitParameterAnnotation
(
int
index
,
String
descriptor
,
boolean
visible
)
{
return
annotationRetention
.
isEnabled
()
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/implementation/EqualsMethod.java
0 → 100644
View file @
1474cd5e
This diff is collapsed.
Click to expand it.
byte-buddy-dep/src/main/java/net/bytebuddy/implementation/HashCodeMethod.java
0 → 100644
View file @
1474cd5e
This diff is collapsed.
Click to expand it.
byte-buddy-dep/src/main/java/net/bytebuddy/implementation/Implementation.java
View file @
1474cd5e
...
...
@@ -695,6 +695,11 @@ public interface Implementation extends InstrumentedType.Prepareable {
*/
private
final
Map
<
FieldCacheEntry
,
FieldDescription
.
InDefinedShape
>
registeredFieldCacheEntries
;
/**
* A set of registered field cache entries.
*/
private
final
Set
<
FieldDescription
.
InDefinedShape
>
registeredFieldCacheFields
;
/**
* A random suffix to append to the names of accessor methods.
*/
...
...
@@ -728,6 +733,7 @@ public interface Implementation extends InstrumentedType.Prepareable {
registeredSetters
=
new
HashMap
<
FieldDescription
,
DelegationRecord
>();
auxiliaryTypes
=
new
HashMap
<
AuxiliaryType
,
DynamicType
>();
registeredFieldCacheEntries
=
new
HashMap
<
FieldCacheEntry
,
FieldDescription
.
InDefinedShape
>();
registeredFieldCacheFields
=
new
HashSet
<
FieldDescription
.
InDefinedShape
>();
suffix
=
RandomString
.
make
();
fieldCacheCanAppendEntries
=
true
;
}
...
...
@@ -795,7 +801,7 @@ public interface Implementation extends InstrumentedType.Prepareable {
int
hashCode
=
fieldValue
.
hashCode
();
do
{
fieldCache
=
new
CacheValueField
(
instrumentedType
,
fieldType
.
asGenericType
(),
suffix
,
hashCode
++);
}
while
(
registeredFieldCache
Entries
.
values
().
contains
(
fieldCache
));
}
while
(
!
registeredFieldCache
Fields
.
add
(
fieldCache
));
registeredFieldCacheEntries
.
put
(
fieldCacheEntry
,
fieldCache
);
return
fieldCache
;
}
...
...
byte-buddy-dep/src/main/java/net/bytebuddy/implementation/MethodCall.java
View file @
1474cd5e
...
...
@@ -1445,6 +1445,9 @@ public class MethodCall implements Implementation.Composable {
TypeDescription
instrumentedType
,
Assigner
assigner
,
Assigner
.
Typing
typing
)
{
if
(
instrumentedMethod
.
isStatic
()
&&
!
invokedMethod
.
isStatic
()
&&
!
invokedMethod
.
isConstructor
())
{
throw
new
IllegalStateException
(
"Cannot invoke "
+
invokedMethod
+
" from "
+
instrumentedMethod
);
}
return
new
StackManipulation
.
Compound
(
invokedMethod
.
isStatic
()
?
StackManipulation
.
Trivial
.
INSTANCE
...
...
@@ -2008,10 +2011,10 @@ public class MethodCall implements Implementation.Composable {
argumentLoaders
.
addAll
(
argumentLoader
.
make
(
implementationTarget
.
getInstrumentedType
(),
instrumentedMethod
,
invokedMethod
));
}
ParameterList
<?>
parameters
=
invokedMethod
.
getParameters
();
Iterator
<?
extends
ParameterDescription
>
parameterIterator
=
parameters
.
iterator
();
if
(
parameters
.
size
()
!=
argumentLoaders
.
size
())
{
throw
new
IllegalStateException
(
invokedMethod
+
" does not take "
+
argumentLoaders
.
size
()
+
" arguments"
);
}
Iterator
<?
extends
ParameterDescription
>
parameterIterator
=
parameters
.
iterator
();
List
<
StackManipulation
>
argumentInstructions
=
new
ArrayList
<
StackManipulation
>(
argumentLoaders
.
size
());
for
(
ArgumentLoader
argumentLoader
:
argumentLoaders
)
{
argumentInstructions
.
add
(
argumentLoader
.
resolve
(
parameterIterator
.
next
(),
assigner
,
typing
));
...
...
Prev
1
2
3
4
Next