Skip to content

Commit

Permalink
[release-later] WhoCalledUtils.getCallingClasses()
Browse files Browse the repository at this point in the history
  • Loading branch information
remal committed Jan 7, 2025
1 parent 083ff97 commit ae5cba1
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 27 deletions.
25 changes: 0 additions & 25 deletions toolkit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,6 @@ project.fatJarWith(project(':toolkit:fat-jar--latest-lts-jdk'))

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

tasks.named('generateJava') { Task it ->
Property<String> toolkitGroupId = project.objects.property(String).value(provider { project.group?.toString() }).with { it.finalizeValueOnRead(); it }
Property<String> toolkitArtifactId = project.objects.property(String).value(provider { project.name }).with { it.finalizeValueOnRead(); it }
Property<String> toolkitVersion = project.objects.property(String).value(provider { project.version?.toString() }).with { it.finalizeValueOnRead(); it }
inputs.property('toolkitGroupId', toolkitGroupId).optional(true)
inputs.property('toolkitArtifactId', toolkitArtifactId).optional(true)
inputs.property('toolkitVersion', toolkitVersion).optional(true)
classFile(project.calculateBaseJavaPackage(), 'ToolkitBuildInfo') {
it.writePackage()
it.println("")
it.writeStaticImport("lombok.AccessLevel", "PRIVATE")
it.println("")
it.writeImport("lombok.NoArgsConstructor")
it.println("")
it.println("@NoArgsConstructor(access = PRIVATE)")
it.writeBlock("abstract class ${it.simpleName}") {
it.println("public static final String TOOLKIT_GROUP_ID = \"${it.escapeJava(toolkitGroupId.get())}\";")
it.println("public static final String TOOLKIT_ARTIFACT_IT = \"${it.escapeJava(toolkitArtifactId.get())}\";")
it.println("public static final String TOOLKIT_VERSION = \"${it.escapeJava(toolkitVersion.get())}\";")
}
}
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Configuration saxonConf = configurations.create('saxon') {
dependencies.add(project.dependencies.create('net.sf.saxon:Saxon-HE:12.5'))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package name.remal.gradle_plugins.toolkit.reflection;

import java.util.List;
import org.jetbrains.annotations.Unmodifiable;

interface WhoCalled {

@Unmodifiable
List<Class<?>> getCallingClasses(int depth);

Class<?> getCallingClass(int depth);

boolean isCalledBy(Class<?> type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,35 @@

import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;

import com.google.auto.service.AutoService;
import java.lang.StackWalker.StackFrame;
import java.util.List;
import lombok.val;
import org.jetbrains.annotations.Unmodifiable;

@AutoService(WhoCalled.class)
@SuppressWarnings("unused")
final class WhoCalledStackWalker implements WhoCalled {

private static final long OFFSET = 1;

@Override
@Unmodifiable
public List<Class<?>> getCallingClasses(int depth) {
val classes = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk(stream -> stream
.skip(OFFSET + 1)
.map(StackFrame::getDeclaringClass)
.collect(toList())
);
return unmodifiableList(classes);
}

@Override
public Class<?> getCallingClass(int depth) {
Class<?>[] classes = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk(stream -> stream
val classes = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk(stream -> stream
.skip(OFFSET)
.limit(depth + 1L)
.map(StackFrame::getDeclaringClass)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package name.remal.gradle_plugins.toolkit;

import static lombok.AccessLevel.PRIVATE;
import static name.remal.gradle_plugins.build_time_constants.api.BuildTimeConstants.getStringProperty;

import lombok.NoArgsConstructor;

@NoArgsConstructor(access = PRIVATE)
abstract class ToolkitBuildInfo {
public static final String TOOLKIT_GROUP_ID = getStringProperty("project.group");
public static final String TOOLKIT_ARTIFACT_IT = getStringProperty("project.name");
public static final String TOOLKIT_VERSION = getStringProperty("project.version");
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
package name.remal.gradle_plugins.toolkit.reflection;

import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;

import com.google.auto.service.AutoService;
import java.util.ArrayList;
import java.util.List;
import lombok.val;
import org.jetbrains.annotations.Unmodifiable;

@AutoService(WhoCalled.class)
@SuppressWarnings({"unused", "removal", "java:S5738", "RedundantSuppression"})
final class WhoCalledSecurityManager extends SecurityManager implements WhoCalled {

private static final int OFFSET = 1;

@Override
@Unmodifiable
public List<Class<?>> getCallingClasses(int depth) {
val result = new ArrayList<Class<?>>();
val classes = getClassContext();
for (int i = OFFSET + depth; i < classes.length; i++) {
result.add(classes[i]);
}
return unmodifiableList(result);
}

@Override
public Class<?> getCallingClass(int depth) {
Class<?>[] classes = getClassContext();
val classes = getClassContext();
val index = OFFSET + depth;
if (index >= classes.length) {
throw new IllegalArgumentException(format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
import static lombok.AccessLevel.PRIVATE;
import static name.remal.gradle_plugins.toolkit.CrossCompileServices.loadCrossCompileService;

import java.util.List;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.Unmodifiable;

@NoArgsConstructor(access = PRIVATE)
public abstract class WhoCalledUtils {

private static final WhoCalled WHO_CALLED = loadCrossCompileService(WhoCalled.class);

@Unmodifiable
public static List<Class<?>> getCallingClasses(int depth) {
return WHO_CALLED.getCallingClasses(depth);
}

public static Class<?> getCallingClass(int depth) {
return WHO_CALLED.getCallingClass(depth);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
package name.remal.gradle_plugins.toolkit.reflection;

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
import static name.remal.gradle_plugins.toolkit.PredicateUtils.not;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import lombok.val;
import org.junit.jupiter.api.Test;

class WhoCalledUtilsTest {

@Test
void getCallingClasses() {
val callingClassNames = WhoCalledUtils.getCallingClasses(1).stream()
.map(Class::getName)
.filter(not(name -> name.startsWith("jdk.internal.reflect.")))
.filter(not(name -> name.startsWith("sun.reflect.")))
.filter(not(name -> name.contains("$$Lambda$")))
.filter(not("java.lang.reflect.Method"::equals))
.collect(toList());

val expectedCallingClassNames = stream(new Exception().getStackTrace())
.map(StackTraceElement::getClassName)
.filter(not(name -> name.startsWith("jdk.internal.reflect.")))
.filter(not(name -> name.startsWith("sun.reflect.")))
.filter(not(name -> name.contains("$$Lambda$")))
.filter(not("java.lang.reflect.Method"::equals))
.toArray(String[]::new);

assertThat(callingClassNames)
.isNotEmpty()
.contains(WhoCalledUtilsTest.class.getName())
.containsExactly(expectedCallingClassNames);
}

@Test
void getCallingClass() {
assertEquals(WhoCalledUtilsTest.class, WhoCalledUtils.getCallingClass(1));
Expand Down

0 comments on commit ae5cba1

Please sign in to comment.