Skip to content

Commit 139e697

Browse files
samebGuice Team
authored andcommitted
Add a utility class for checking if Guice has enhanced a class (and returning the unenahnced version).
(Also changes the classname suffix to be a hex string instead of an int, which had previously included a leading negative sign, which was weird.) Fixes #1340 & fixes #187. PiperOrigin-RevId: 525256080
1 parent 9678847 commit 139e697

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed

core/src/com/google/inject/internal/aop/AbstractGlueGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ protected AbstractGlueGenerator(Class<?> hostClass, String marker) {
102102

103103
/** Generates a unique name based on the original class name and marker. */
104104
private static String proxyName(String hostName, String marker, int hash) {
105-
int id = ((hash & 0x000FFFFF) | (COUNTER.getAndIncrement() << 20));
106-
String proxyName = hostName + marker + id;
105+
long id = ((hash & 0x000FFFFF) | (COUNTER.getAndIncrement() << 20));
106+
String proxyName = hostName + marker + Long.toHexString(id);
107107
if (proxyName.startsWith("java/") && !ClassDefining.hasPackageAccess()) {
108108
proxyName = '$' + proxyName; // can't define java.* glue in same package
109109
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (C) 2023 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.inject.util;
18+
19+
import com.google.inject.internal.BytecodeGen;
20+
import java.util.Optional;
21+
import java.util.regex.Pattern;
22+
23+
/** Utilities for checking if classes are enhanced and/or getting the original un-enhanced class. */
24+
public final class Enhanced {
25+
26+
// The pattern for enhanced classes. Note that the trailing (/.*)? is to support the ANONYMOUS
27+
// classloading option, which uses defineAnonymousClass|defineHiddenClass, which return classes
28+
// suffixed with a trailing "/<suffix>". According to the spec, the suffix can be pretty much
29+
// anything (though in theory it is a hexadecimal value).
30+
private static final Pattern ENHANCED =
31+
Pattern.compile(
32+
".+" + Pattern.quote(BytecodeGen.ENHANCER_BY_GUICE_MARKER) + "[a-f0-9]+(/.*)?$");
33+
34+
private Enhanced() {}
35+
36+
/** Returns true if this is a class that Guice enhanced with AOP functionality. */
37+
public static boolean isEnhanced(Class<?> clazz) {
38+
return ENHANCED.matcher(clazz.getSimpleName()).matches();
39+
}
40+
41+
/**
42+
* If the input class is a class that {@link #isEnhanced} is true for, returns the un-enhanced
43+
* version of the class. Otherwise returns an empty optional.
44+
*/
45+
public static Optional<Class<?>> unenhancedClass(Class<?> clazz) {
46+
if (!isEnhanced(clazz)) {
47+
return Optional.empty();
48+
}
49+
return Optional.of(clazz.getSuperclass());
50+
}
51+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.google.inject.util;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
5+
import com.google.inject.AbstractModule;
6+
import com.google.inject.Guice;
7+
import com.google.inject.Injector;
8+
import com.google.inject.matcher.Matchers;
9+
import java.util.Optional;
10+
import org.aopalliance.intercept.MethodInterceptor;
11+
import org.aopalliance.intercept.MethodInvocation;
12+
import org.junit.Test;
13+
import org.junit.runner.RunWith;
14+
import org.junit.runners.JUnit4;
15+
16+
@RunWith(JUnit4.class)
17+
public final class EnhancedTest {
18+
@Test
19+
public void isEnhancedAndUnenhancedClass() {
20+
Injector injector =
21+
Guice.createInjector(
22+
new AbstractModule() {
23+
@Override
24+
protected void configure() {
25+
binder()
26+
.bindInterceptor(
27+
Matchers.only(Foo.class),
28+
Matchers.any(),
29+
new MethodInterceptor() {
30+
@Override
31+
public Object invoke(MethodInvocation i) throws Throwable {
32+
return "intercepted-" + i.proceed();
33+
}
34+
});
35+
bind(Foo.class);
36+
bind(Bar.class);
37+
}
38+
});
39+
Foo foo = injector.getInstance(Foo.class);
40+
Bar bar = injector.getInstance(Bar.class);
41+
// Validate preconditions: foo is intercepted & bar isn't.
42+
assertThat(foo.foo()).isEqualTo("intercepted-foo");
43+
assertThat(bar.bar()).isEqualTo("bar");
44+
45+
// The actual tests.
46+
assertThat(Enhanced.isEnhanced(foo.getClass())).isTrue();
47+
assertThat(Enhanced.unenhancedClass(foo.getClass())).isEqualTo(Optional.of(Foo.class));
48+
assertThat(Enhanced.isEnhanced(bar.getClass())).isFalse();
49+
assertThat(Enhanced.unenhancedClass(bar.getClass())).isEqualTo(Optional.empty());
50+
}
51+
52+
public static class Foo {
53+
public String foo() {
54+
return "foo";
55+
}
56+
}
57+
58+
public static class Bar {
59+
public String bar() {
60+
return "bar";
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)