Skip to content

Commit

Permalink
Add a utility class for checking if Guice has enhanced a class (and r…
Browse files Browse the repository at this point in the history
…eturning the unenhanced 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: 526291523
  • Loading branch information
sameb authored and Guice Team committed Apr 22, 2023
1 parent 356f6ba commit 4baf691
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ protected AbstractGlueGenerator(Class<?> hostClass, String marker) {

/** Generates a unique name based on the original class name and marker. */
private static String proxyName(String hostName, String marker, int hash) {
int id = ((hash & 0x000FFFFF) | (COUNTER.getAndIncrement() << 20));
String proxyName = hostName + marker + id;
long id = ((hash & 0x000FFFFF) | (COUNTER.getAndIncrement() << 20));
String proxyName = hostName + marker + Long.toHexString(id);
if (proxyName.startsWith("java/") && !ClassDefining.hasPackageAccess()) {
proxyName = '$' + proxyName; // can't define java.* glue in same package
}
Expand Down
38 changes: 38 additions & 0 deletions core/src/com/google/inject/util/Enhanced.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Google Inc.
*
* Licensed 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 com.google.inject.util;

import com.google.inject.internal.BytecodeGen;
import java.util.Optional;

/** Utilities for checking if classes are enhanced and/or getting the original un-enhanced class. */
public final class Enhanced {
private Enhanced() {}

/** Returns true if this is a class that Guice enhanced with AOP functionality. */
public static boolean isEnhanced(Class<?> clazz) {
return clazz.getSimpleName().contains(BytecodeGen.ENHANCER_BY_GUICE_MARKER);
}

/**
* If the input class is a class that {@link #isEnhanced} is true for, returns the un-enhanced
* version of the class. Otherwise returns an empty optional.
*/
public static <T> Optional<Class<? super T>> unenhancedClass(Class<T> clazz) {
return isEnhanced(clazz) ? Optional.of(clazz.getSuperclass()) : Optional.empty();
}
}
82 changes: 82 additions & 0 deletions core/test/com/google/inject/util/EnhancedTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.google.inject.util;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static org.junit.Assume.assumeTrue;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.internal.InternalFlags;
import com.google.inject.matcher.Matchers;
import java.util.Optional;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public final class EnhancedTest {
@Test
public void isEnhanced() {
assumeTrue(InternalFlags.isBytecodeGenEnabled());

Injector injector = Guice.createInjector(new InterceptingModule());
Foo foo = injector.getInstance(Foo.class);
Bar bar = injector.getInstance(Bar.class);
// Validate preconditions: foo is intercepted & bar isn't.
assertThat(foo.foo()).isEqualTo("intercepted-foo");
assertThat(bar.bar()).isEqualTo("bar");

// The actual tests.
assertThat(Enhanced.isEnhanced(foo.getClass())).isTrue();
assertThat(Enhanced.isEnhanced(bar.getClass())).isFalse();
}

@Test
public void unenhancedClass() {
assumeTrue(InternalFlags.isBytecodeGenEnabled());

Injector injector = Guice.createInjector(new InterceptingModule());
Foo foo = injector.getInstance(Foo.class);
Bar bar = injector.getInstance(Bar.class);
// Validate preconditions: foo is intercepted & bar isn't.
assertThat(foo.foo()).isEqualTo("intercepted-foo");
assertThat(bar.bar()).isEqualTo("bar");

// The actual tests.
assertThat(Enhanced.unenhancedClass(foo.getClass())).isEqualTo(Optional.of(Foo.class));
assertThat(Enhanced.unenhancedClass(bar.getClass())).isEmpty();
}

private static class InterceptingModule extends AbstractModule {
@Override
protected void configure() {
binder()
.bindInterceptor(
Matchers.only(Foo.class),
Matchers.any(),
new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation i) throws Throwable {
return "intercepted-" + i.proceed();
}
});
bind(Foo.class);
bind(Bar.class);
}
}

public static class Foo {
public String foo() {
return "foo";
}
}

public static class Bar {
public String bar() {
return "bar";
}
}
}

0 comments on commit 4baf691

Please sign in to comment.