Policeman's Forbidden API Checker

Overview

Policeman's Forbidden API Checker

Allows to parse Java byte code to find invocations of method/class/field signatures and fail build (Apache Ant, Apache Maven, or Gradle).

Maven Central Build Status

Documentation

Please refer to the Github Wiki & Documentation.

The checker is available as Apache Ant Task, Apache Maven Mojo, and Gradle plugin. In addition there is a command line tool (CLI):

This project uses Apache Ant (and Apache Ivy) to build. The minimum Ant version is 1.8.0 and it is recommended to not have Apache Ivy in the Ant lib folder, because the build script will download the correct version of Ivy automatically.

Project Resources

Comments
  • Add option to suppress warning about unresolved signature

    Add option to suppress warning about unresolved signature

    I'm using the gradle plugin, version 2.0 . Please consider suppressing the warning about unresolved signature i.e. this signature: Class 'com.google.inject.Inject' not found on classpath while parsing signature: com.google.inject.Inject [signature ignored]

    The use case is as follows:

    • I have a multi-project gradle build, where some subprojects often use different libraries.
    • I would like to have a single top-level forbidden signatures file.
    • When a project starts using a library and also uses a forbidden method, i would like there to be an error. (e.g. in this case, I want to mandate that Guice users use the JSR-330 annotations instead of the guice annotations, however not all subprojects are using guice yet).

    The failOnUnresolvableSignatures = false option makes the build still pass, but currently my build logs are polluted with messages about signatures for libraries from other projects.

    That being said, I just started using the plugin, and I'm open to ideas about how to better achieve my goals. Thank you for this useful plugin.

    enhancement 
    opened by ghost 41
  • Add new bundled signatures for disallowing internal runtime APIs + fix class loading order bugs

    Add new bundled signatures for disallowing internal runtime APIs + fix class loading order bugs

    Problem 1. If you name a class sun.misc.Unsafe and put it in your classpath, it does not change the fact, any code calling that will still be calling the real Unsafe. But it does hide it from forbidden-apis!!!

    This is because classloader order, when the application is actually used, is Bootstrap->Extensions->System (App), as explained here: http://docs.oracle.com/javase/tutorial/ext/basics/load.html

    But forbidden-apis checks the wrong order, it checks the ones you provide first, because it uses lookupRelatedClass(): https://github.com/policeman-tools/forbidden-apis/blob/9de5e1fccb1755d58a271870a2dee3a19f0d51ec/src/main/java/de/thetaphi/forbiddenapis/Checker.java#L303-L306

    This causes the interesting scenario when trying to cleanup crazy classpaths, where removing a jar can cause new violations in your build :)

    Problem 2: The current isRuntimeClass() does not seem to check for extensions at all, but only against bootstrap classpath. This hides additional internal accesses, e.g. jdk.nashorn.internal, which will cause a SecurityException if you try to use it.

    So can we use the following code on pre-jigsaw, to identify extensions jars and treat them as "internal" too? I think this extensions idea goes away with jigsaw, and everything is just modules, so it should not be a problem that we can't get extensions jars/directories there.

    // of course with proper checks and best-effort, not guaranteed but works.
    URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader().getParent();
    URL extensions[] = loader.getURLs();
    

    Problem 3: Internal checking has a hardcoded list of simple patterns: https://github.com/policeman-tools/forbidden-apis/blob/f7dce219c725add93de3ec4545d94f164ef032df/src/main/java/de/thetaphi/forbiddenapis/AsmUtils.java#L33

    Can we use java.security.Security.getProperty("package.access") instead? That property is set by the JDK, in e.g. the jre/lib/security/java.security configuration file for security checks against internal apis:

    #
    # List of comma-separated packages that start with or equal this string
    # will cause a security exception to be thrown when
    # passed to checkPackageAccess unless the
    # corresponding RuntimePermission ("accessClassInPackage."+package) has
    # been granted.
    package.access=sun.,\
                   com.sun.xml.internal.,\
                   com.sun.imageio.,\
                   com.sun.istack.internal.,\
                   com.sun.jmx.,\
                   com.sun.media.sound.,\
                   com.sun.naming.internal.,\
                   com.sun.proxy.,\
                   ... (many lines) ...
    
    bug enhancement 
    opened by rmuir 34
  • Add support for Gradle

    Add support for Gradle

    The Elasticsearch people started with https://github.com/elastic/forbidden-apis-gradle-plugin.

    I think this should be included directly into the forbidden-apis tool. Basically this is more or less the Maven tool, just implemented as Gradle's DefaultTask extension. This can be implemented in pure Java, this is what I would prefer.

    As usual all would be packaged in the same JAR file because there are no conflicts between the tools.

    enhancement 
    opened by uschindler 31
  • Gradle plugin - Toolchain API fails on targetCompatibility

    Gradle plugin - Toolchain API fails on targetCompatibility

    When the Toolchain API is used, the configuration will be scanned for targetCompatibility properties. It seems it's not possible to limit the bundle signatures. In case an unsupported JDK (e.g. JDK 18) is used, the plugin throws an IO error "IO problem while reading files with API signatures." - e.g. see POIs build

    I'm not sure, what the correct request would be ... a) the toolchain api has to be limited in it's scan (which is of course out-of-scope here) b) there should be an alternative property in the gradle plugin c) if the classes are compiled via JDK 18, the forbidden-apis check might not work anyway -> in those cases, we might need to disable it?

    wontfix 
    opened by kiwiwings 23
  • Yet another Gradle update issue: 7.4 deprecated FileTrees using @SkipWhenEmpty

    Yet another Gradle update issue: 7.4 deprecated FileTrees using @SkipWhenEmpty

    Gradle 7.4 (release notes [1]) deprecated @SkipWhenEmpty [2], builds (with strict deprecation check) fail with:

    > Task <project>:forbiddenApisTest NO-SOURCE
    Relying on FileTrees for ignoring empty directories when using @SkipWhenEmpty has been deprecated. This is scheduled to be removed in Gradle 8.0. Annotate the property classFiles with @IgnoreEmptyDirectories or remove @SkipWhenEmpty. Consult the upgrading guide for further information: https://docs.gradle.org/7.4/userguide/upgrading_version_7.html#empty_directories_file_tree
    

    [1] https://docs.gradle.org/7.4/release-notes.html [2] https://docs.gradle.org/current/userguide/upgrading_version_7.html#empty_directories_file_tree

    opened by reta 19
  • Ability to skip class file parse errors

    Ability to skip class file parse errors

    I've tried de.thetaphi.forbiddenapis.version=3.0.1 and the error is still there, so I guess the's ASM issue.

    I've a case when forbidden-apis task fails with ArrayIndexOutOfBoundsException, and it looks like there's no way to proceed :-/

    CI failure: https://github.com/apache/calcite/runs/1058616825?check_suite_focus=true#step:6:430 Code: https://github.com/apache/calcite/pull/1929

    Unfortunately, the exception does not tell which of the classes failed to parse, and there's no way to skip the failure.

    Could you please print "unparseable" class file names in the warning messages and provide users the ability to skip unparseable class files? I think it would be OK to skip the analysis by default in case ASM fails to parse the file.

    Here's the stacktrace:

    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':core:forbiddenApisMain'.
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:208)
            at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:206)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:187)
            at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114)
            at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
            at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
            at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
            at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
            at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:409)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:399)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:157)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:242)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:150)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:94)
            at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
            at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
            at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
            at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
            at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 116 out of bounds for length 34
            at de.thetaphi.forbiddenapis.asm.ClassReader.readLabel(ClassReader.java:2650)
            at de.thetaphi.forbiddenapis.asm.ClassReader.createLabel(ClassReader.java:2666)
            at de.thetaphi.forbiddenapis.asm.ClassReader.readTypeAnnotations(ClassReader.java:2732)
            at de.thetaphi.forbiddenapis.asm.ClassReader.readCode(ClassReader.java:1899)
            at de.thetaphi.forbiddenapis.asm.ClassReader.readMethod(ClassReader.java:1488)
            at de.thetaphi.forbiddenapis.asm.ClassReader.accept(ClassReader.java:718)
            at de.thetaphi.forbiddenapis.asm.ClassReader.accept(ClassReader.java:401)
            at de.thetaphi.forbiddenapis.Checker.checkClass(Checker.java:409)
            at de.thetaphi.forbiddenapis.Checker.run(Checker.java:440)
            at de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis.checkForbidden(CheckForbiddenApis.java:601)
            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)
            at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
            at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
            at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.run(ExecuteActionsTaskExecuter.java:570)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:395)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:387)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:157)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:242)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:150)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:84)
            at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:555)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:538)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:109)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:279)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:268)
            at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33)
            at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33)
            at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
            at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:67)
            at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:36)
            at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49)
            at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34)
            at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43)
            at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
            at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
            at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34)
            at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44)
            at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54)
            at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38)
            at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
            at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:159)
            at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:72)
            at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:43)
            at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44)
            at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33)
            at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
            at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
            at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92)
            at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85)
            at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55)
            at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39)
            at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76)
            at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
            at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
            at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
            at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94)
            at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49)
            at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79)
            at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53)
            at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74)
            at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78)
            at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78)
            at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34)
            at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39)
            at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40)
            at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28)
            at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:195)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:187)
            at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114)
            at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
            at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
            at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
            at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
            at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:409)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:399)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:157)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:242)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:150)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:94)
            at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
            at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
            at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
            at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
            at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
            at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    
    enhancement 
    opened by vlsi 19
  • apply plugin: 'de.thetaphi.forbiddenapis' is very slow.

    apply plugin: 'de.thetaphi.forbiddenapis' is very slow.

    allprojects {
        apply plugin: 'de.thetaphi.forbiddenapis'
    }
    

    adds 25s to the configuration time of a multi-module build with about 500 modules.

    The reason for this is that ForbiddenApisPlugin.java is compiling the plugin-init.groovy script for every single apply call.

    You should instead re-implement the plugin-init.groovy functionality in Java or switch the ForbiddenApisPlugin to Groovy.

    enhancement 
    opened by huxi 19
  • JDK version determined incorrectly by Gradle on JDK 10

    JDK version determined incorrectly by Gradle on JDK 10

    https://github.com/policeman-tools/forbidden-apis/wiki/BundledSignatures "Gradle automatically add the compile Java version"

    forbiddenApis {
      bundledSignatures = ['jdk-internal']
    }
    

    Error: Parsing signatures failed: Invalid bundled signature reference (JDK version is invalid): jdk-internal-1.10

    Workaround:

    forbiddenApis {
      bundledSignatures = ['jdk-internal-10']
    }
    
    opened by sdavids 16
  • Support relative signatureFile location in multimodule Maven projects

    Support relative signatureFile location in multimodule Maven projects

    forbidden-apis maven plugin doesn't handle relative path properly across multimodule project. Currently I workaround it by configuring

    <configuration>
        <signaturesFiles>
            <signaturesFile>${session.executionRootDirectory}/codestyle/my-signature.txt</signaturesFile>
        </signaturesFiles>
    </configuration>
    

    But this approach has limitations, e. g. all maven builds should be done only from a root dir, not from one of submodule dirs.

    By contrast, checkstyle handles it's relative config location properly:

    <configuration>
        <configLocation>codestyle/checkstyle.xml</configLocation>
    </configuration>
    
    task discussion 
    opened by leventov 16
  • Allow signatures to be loaded as Maven artifacts

    Allow signatures to be loaded as Maven artifacts

    In issue #10 it was shown that its possible to release "signature" artifacts as 
    Maven packages. You could then add a dependency to the Maven plugin section of 
    your POM and load the signaures JAR file into the plugin's classpath. Those 
    signatures would then be available by the "bundled-signatures" config setting.
    
    The only problem is the package name: All those Maven artifacts need to have 
    the signatures in the de.thetaphi.forbiddenapis package, which violates general 
    Maven bundling, which should have package names named by the released product 
    (see also OSGI).
    
    Instead the signatures should be moved into the META-INF/ folder of the JAR, so 
    its universal. An addon signature artifact would then be a JAR file with only a 
    META-INF/ resource folder.
    

    Original issue reported on code.google.com by uwe.h.schindler on 11 Oct 2013 at 3:53

    auto-migrated enhancement 
    opened by GoogleCodeExporter 16
  • Use task configuration avoidance in gradle initialization

    Use task configuration avoidance in gradle initialization

    Gradle task creation can be heavyweight when hundreds or thousands of instances of tasks exist. This is especially true in large multi project builds. Forbidden apis currently always creates a task per source set, as well as the alias forbiddenApis task. Gradle provides a way to lazily construct the task, and only configure when the task is actually needed for a given task graph.

    This commit switches the construction of the forbidden apis tasks to use task registration, when it is available (based on gradle version).

    closes #145

    enhancement 
    opened by rjernst 13
  • Add HttpResponse.BodyHandlers.ofFile(Path) to banned method lists (buggy)

    Add HttpResponse.BodyHandlers.ofFile(Path) to banned method lists (buggy)

    Eh. Perhaps worth adding to forbidden method list with a comment saying it's likely buggy in whatever JDK one is using: https://bugs.openjdk.org/browse/JDK-8299015

    opened by dweiss 0
  • Project Loom does not play well with synchronized, so WDYT of adding support for

    Project Loom does not play well with synchronized, so WDYT of adding support for "forbid use of synchronized"?

    In pgjdbc, we replace all synchronized with explicit Lock: https://github.com/pgjdbc/pgjdbc/pull/2635 I wonder if I could use forbidden-apis to avoid more synchronized keywords creeping in the future.

    enhancement 
    opened by vlsi 3
  • Annotate task with `@CacheableTask` so that the build cache can be used

    Annotate task with `@CacheableTask` so that the build cache can be used

    We're doing some investigations on --build-cache and looking at the Gradle profiler's output to see which tasks aren't being cached.

    After fixing a few of the cases where our configuration was causing things not to be cacheable, and fixing our own custom checks, forbidden-apis is now one of the slowest tasks which isn't coming from the cache.

    It would be nice if this task were cacheable.

    Adding the annotation might be the only thing needed, but it might also change the version of Gradle the plugin is built against...

    opened by hakanai 0
  • Consider a bundleded signature set that would suggest replacing HashMap, HashSet, Collectors.toSet, Collectors.toMap with Linked alternatives for deterministic oder

    Consider a bundleded signature set that would suggest replacing HashMap, HashSet, Collectors.toSet, Collectors.toMap with Linked alternatives for deterministic oder

    HashSet, HashMap, Collectors.toSet(), and similar APIs do not keep the element order, and it might result in surprising and unexpected results.

    What if error-prone could catch those types of errors and suggest replacing the calls via LinkedHash*?

    See https://github.com/jlink/jqwik/pull/348 See https://github.com/google/error-prone/issues/3230

    opened by vlsi 2
  • Support for exclusions file

    Support for exclusions file

    It is currently supported to set signature files that allow externalizing the linting configuration. But this is not possible with exclusions. Using containers with maven is considered best to cache the dependency container layer with the pom.xml.

    FROM maven
    
    COPY pom.xml pom.xml
    
    # cache maven dependencies required for your goal - here 'package'
    RUN mvn --strict-checksums package
    
    COPY . .
    

    This allows running a prebaked container image "without" requiring an internet connection for dependencies.

    docker run -it $(docker build  -q .) package
    

    The need to modify the pom.xml just to add an exclusion would break the dependency caching.

    I could imagine a configuration option that would match the currently used naming like this

    <configuration>
        <excludesFiles>
            <excludesFile>excludes.txt</excludesFile>
        </excludesFiles>
    </configuration>
    
    opened by commodis 3
  • Method whitelist support

    Method whitelist support

    Often I find myself in a situation where an update to a library drags in a new evil method, and I only discover it after the fact. It would be nice if new methods were treated as suspicious by default.

    The syntax I was thinking of was something like:

    @defaultMessage Use `MatcherAssert` from Hamcrest instead.
    !org.junit.jupiter.api.Assertions#fail(java.lang.String)
    org.junit.jupiter.api.Assertions#*
    

    Allowing people to call fail() still while also saying that any other calls to Assertions' static methods are not OK.

    This way, when a new method appears, it's automatically blocked, and someone can come and discuss why they think they need it.

    opened by hakanai 1
Owner
Policeman Tools
Coding & Validation Tools by the Generics Policeman
Policeman Tools
EscamasDupeCheck es un Minecraft Forge Mod 1.8.9 para Hypixel Skyblock que agrega un Dupe Checker a Skyblock

EDC dupe check para Hypixel Skyblock EscamasDupeCheck es un Minecraft Forge Mod 1.8.9 para Hypixel Skyblock que agrega un Dupe Checker a Skyblock Lo q

alexander carrareas 1 Oct 26, 2022
There are two challenges one is to create a backend api the other is to create a frontend application to consume the public data api devall.

Sobre | Desafio | Resolução | Tecnologias | Execução | Itexto desafio tecnico Sobre os Desafios existem dois desafios um é criar uma api backend o out

fabricio S Miranda 1 Oct 18, 2021
Deploy this 🔥🔥🔥 BLAZING FAST 🔥🔥🔥 API to get instant access to ✨✨✨ INNOVATIVE ✨✨✨ API to quickly define whether the numbers are odd or even.

Is Odd API This ?? is ?? ?? a ?? simple API that ?? returns ?? whether ?? ?? a ?? number ?? ?? is ?? ?? odd ?? or ?? not. ♂ With ?? ?? this ?? ?? API

rferee 5 Sep 23, 2022
一个能够获取随机图片的 Api,使用 SpringBoot 构建

Random-Image-Api Random-Image-Api 一个能够获取随机图片的 Api,基于 Spring Boot 构建 可读取本地图片列表的地址,并提供随机访问服务,可配置域名白名单访问 项目说明 程序启动的时候会自动加载 项目路径/list 文件夹下的所有列表文件; 图片列表文件:

陈亚伟 1.3k Dec 21, 2022
能将对API的调用转化为对手机的操作,软件自身提供 restful API,运行于安卓,一切操作与获取信息均由软件完成。

文档地址:https://www.lookcos.cn/docs/hermit Hermit简介 Hermit,是一款用于Android自动化测试的软件,运行于安卓,通过接收restful API请求,进而转化为对设备的操作。 支持快速的点击、滑动、读取与设置剪切板(支持中文)、模拟输入、寻找控件并

Lookcos 278 Dec 13, 2022
Esse repositório disponibiliza uma versão zero de uma API de cadastro de usuários (Users) a ser melhorada com desafios ☕️ 🇧🇷

java-training-api Esse repositório disponibiliza uma versão zero de uma API de cadastro de usuários (Users) na pasta SRC a ser melhorada. DESAFIOS Os

Guillaume Falourd 91 Dec 22, 2022
Projeto para consulta de filmes na API data IMDB e construção de playlists.

Projeto IDP: Filmes API ✍️ API Requirements Must to have Comunicar com uma API externa (desenvolvida pelo colaborador ou por terceiros). Persistir dad

Sarah Andrade Toscano de Carvalho 2 Oct 9, 2022
Spring boot microservice example with Eureka Server + Eureka Client + Spring Cloud API Gateway + OAuth2.0 + Circuit Breaker + Resilience4J + FeignClient + RestTemplate

Spring boot microservice example Spring boot microservice example with Eureka Server + Eureka Client + Spring Cloud API Gateway + OAuth2.0 + Circuit B

Subhash Lamba 47 Dec 29, 2022
The Quotation Management application is a API REST created using Spring Boot framework.

✅ Quotation Management API - Done ✅ About • Features • Setup • Technologies • Author • License ?? About The Quotation Management application is a API

Vanessa Swerts 6 Apr 29, 2022
Back-End/API de uma aplicação web de agendamento desenvolvida durante o Hackaton do Programa de Formação do Grupo Fcamara

??️ Sobre o projeto ?? Agenda Laranja - é um meio prático e eficiente para programar o dia do trabalho presencial, respeitando as normas de segurança.

Lucas Gonçalves 3 Sep 17, 2021
POC showing how to divide endpoint(s) among different Open-API screens

Multiple Open-API groups: Spring boot POC showing how to divide endpoint(s) among different Open-API screens Demo Link (Select definition from top rig

null 6 Dec 15, 2022
source code of the live coding demo for "Building resilient and scalable API backends with Apache Pulsar and Spring Reactive" talk held at ApacheCon@Home 2021

reactive-iot-backend The is the source code of the live coding demo for "Building resilient and scalable API backends with Apache Pulsar and Spring Re

Lari Hotari 4 Jan 13, 2022
Spring Boot JdbcTemplate example with SQL Server: CRUD Rest API using Spring Data JDBC, Spring Web MVC

Spring Boot JdbcTemplate example with SQL Server: Build CRUD Rest API Build a Spring Boot CRUD Rest API example that uses Spring Data Jdbc to make CRU

null 7 Dec 20, 2022
Springboot CRUD api using containerized mongoDB. ☕🍃📦

Javongo ☕ ?? Springboot CRUD api using containerized mongoDB. Feel free to use it as an example for your projects. Running Make sure ports 27017 & 808

Antonio Cituk 8 Mar 19, 2022
This is a plugin for Minecraft Server (Spigot API) introduces a sector system which connects a single world across multiple servers.

OpenSourceSectors ?? ??️ This is a plugin for Minecraft Server (Spigot API) introduces a sector system which connects a single world across multiple s

null 20 Dec 28, 2022
Uma API REST com funcionalidades de CRUD que simula um sistema de leilão 💰.

Leilão API REST Essa aplicação foi feita para ajudar aqueles que ainda estão com alguma dúvida, sobre o funcionamento de um API REST em Spring. Já que

Fábio Henrique 4 Feb 23, 2022
Clivia is a scalable, high-performance, elastic and responsive API gateway based on spring weblux

clivia是一款基于spring webflux的可扩展、高性能、高弹性、响应式的 API 网关 clivia_V0.0.1 架构概览 模块介绍 clivia-admin-core : 网关配置管理后台核心模块 clivia-client-core : 网关核心模块 clivia-example

palading 14 Jan 9, 2023
OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)

OpenAPI Generator Master (5.4.x): 6.0.x (6.0.x): ⭐ ⭐ ⭐ If you would like to contribute, please refer to guidelines and a list of open tasks. ⭐ ⭐ ⭐ ‼️

OpenAPI Tools 14.8k Dec 30, 2022
Text to Speech Project for Spring Boot and Kotlin, Auth Server, Python with Fast API (gTTS)

TTS-App Text to Speech Project for Spring Boot Module (etc Resource, Auth Server, Python with Fast API (gTTS)) Python의 gTTS lib를 활용하여 텍스트를 음성으로 변환하는 서

Seokhyun 7 Dec 21, 2021