├── .github
└── workflows
│ └── codeql-analysis.yml
├── .gitignore
├── .travis.yml
├── README.md
├── config
├── FindBugsExcludeFilter.xml
├── pmd-ruleset.xml
└── version-rules.xml
├── license.txt
├── pom.xml
├── src
├── it
│ ├── brokenFiles
│ │ ├── pom.xml
│ │ ├── src
│ │ │ └── main
│ │ │ │ └── resources
│ │ │ │ ├── Broken.class
│ │ │ │ ├── Broken.java
│ │ │ │ └── Broken.xml
│ │ └── verify.bsh
│ ├── customWebAppResourcesAreConsidered
│ │ ├── pom.xml
│ │ ├── src
│ │ │ └── main
│ │ │ │ ├── java
│ │ │ │ └── WebAppServlet.java
│ │ │ │ └── webapp
│ │ │ │ └── WEB-INF
│ │ │ │ └── web.xml
│ │ └── verify.bsh
│ ├── defaultWebAppResourcesAreConsidered
│ │ ├── pom.xml
│ │ ├── src
│ │ │ └── main
│ │ │ │ ├── java
│ │ │ │ └── WebAppServlet.java
│ │ │ │ └── webapp
│ │ │ │ └── WEB-INF
│ │ │ │ └── web.xml
│ │ └── verify.bsh
│ ├── help
│ │ └── pom.xml
│ ├── pom.xml
│ ├── reactorProject
│ │ ├── emptyProject
│ │ │ └── pom.xml
│ │ ├── javaProject
│ │ │ ├── pom.xml
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ └── java
│ │ │ │ └── WebAppServlet.java
│ │ ├── pom.xml
│ │ ├── secondJavaProject
│ │ │ ├── pom.xml
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ └── java
│ │ │ │ └── UnusedClassInSecondJavaProject.java
│ │ ├── secondReactorProject
│ │ │ ├── nestedJavaProject
│ │ │ │ ├── pom.xml
│ │ │ │ └── src
│ │ │ │ │ └── main
│ │ │ │ │ └── java
│ │ │ │ │ └── UnusedClassInNestedJavaProject.java
│ │ │ └── pom.xml
│ │ ├── secondWebAppProject
│ │ │ ├── pom.xml
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── java
│ │ │ │ └── SecondServlet.java
│ │ │ │ └── webapp
│ │ │ │ └── WEB-INF
│ │ │ │ └── web.xml
│ │ ├── verify.bsh
│ │ └── webAppProject
│ │ │ ├── pom.xml
│ │ │ └── src
│ │ │ └── main
│ │ │ └── webapp
│ │ │ └── WEB-INF
│ │ │ └── web.xml
│ └── scatteredHibernate
│ │ ├── definitions
│ │ ├── pom.xml
│ │ └── src
│ │ │ └── main
│ │ │ └── java
│ │ │ └── de
│ │ │ └── is24
│ │ │ └── junit
│ │ │ └── typedefs
│ │ │ └── package-info.java
│ │ ├── overriding-definition
│ │ ├── pom.xml
│ │ └── src
│ │ │ └── main
│ │ │ └── java
│ │ │ └── de
│ │ │ └── is24
│ │ │ └── junit
│ │ │ └── overriding_typedefs
│ │ │ └── package-info.java
│ │ ├── pom.xml
│ │ ├── usages
│ │ ├── pom.xml
│ │ └── src
│ │ │ └── main
│ │ │ └── java
│ │ │ └── de
│ │ │ └── is24
│ │ │ └── junit
│ │ │ └── EntityClass.java
│ │ └── verify.bsh
├── main
│ └── java
│ │ ├── de
│ │ └── is24
│ │ │ ├── deadcode4j
│ │ │ ├── AnalysisContext.java
│ │ │ ├── AnalysisSink.java
│ │ │ ├── AnalysisStage.java
│ │ │ ├── AnalyzedCode.java
│ │ │ ├── Analyzer.java
│ │ │ ├── DeadCode.java
│ │ │ ├── DeadCodeComputer.java
│ │ │ ├── DeadCodeFinder.java
│ │ │ ├── IntermediateResult.java
│ │ │ ├── IntermediateResults.java
│ │ │ ├── Module.java
│ │ │ ├── Repository.java
│ │ │ ├── Resource.java
│ │ │ ├── Utils.java
│ │ │ ├── analyzer
│ │ │ │ ├── AnalyzerAdapter.java
│ │ │ │ ├── AnnotationsAnalyzer.java
│ │ │ │ ├── AopXmlAnalyzer.java
│ │ │ │ ├── ApacheTilesAnalyzer.java
│ │ │ │ ├── ByteCodeAnalyzer.java
│ │ │ │ ├── CastorClassesAnalyzer.java
│ │ │ │ ├── ClassDependencyAnalyzer.java
│ │ │ │ ├── CustomAnnotationsAnalyzer.java
│ │ │ │ ├── CustomInterfacesAnalyzer.java
│ │ │ │ ├── CustomSuperClassAnalyzer.java
│ │ │ │ ├── CustomXmlAnalyzer.java
│ │ │ │ ├── ExtendedXmlAnalyzer.java
│ │ │ │ ├── FacesConfigXmlAnalyzer.java
│ │ │ │ ├── HibernateAnnotationsAnalyzer.java
│ │ │ │ ├── IgnoreClassesAnalyzer.java
│ │ │ │ ├── InterfacesAnalyzer.java
│ │ │ │ ├── JavaFileAnalyzer.java
│ │ │ │ ├── JeeAnnotationsAnalyzer.java
│ │ │ │ ├── JerseyWebXmlAnalyzer.java
│ │ │ │ ├── JettyXmlAnalyzer.java
│ │ │ │ ├── LogbackXmlAnalyzer.java
│ │ │ │ ├── MainClassAnalyzer.java
│ │ │ │ ├── ReferenceToConstantsAnalyzer.java
│ │ │ │ ├── ServletContainerInitializerAnalyzer.java
│ │ │ │ ├── SimpleXmlAnalyzer.java
│ │ │ │ ├── SpringAnnotationsAnalyzer.java
│ │ │ │ ├── SpringDataCustomRepositoriesAnalyzer.java
│ │ │ │ ├── SpringNamespaceHandlerAnalyzer.java
│ │ │ │ ├── SpringWebApplicationInitializerAnalyzer.java
│ │ │ │ ├── SpringWebFlowAnalyzer.java
│ │ │ │ ├── SpringWebXmlAnalyzer.java
│ │ │ │ ├── SpringXmlAnalyzer.java
│ │ │ │ ├── SuperClassAnalyzer.java
│ │ │ │ ├── TldAnalyzer.java
│ │ │ │ ├── TypeErasureAnalyzer.java
│ │ │ │ ├── WebXmlAnalyzer.java
│ │ │ │ ├── WsddAnalyzer.java
│ │ │ │ ├── XmlAnalyzer.java
│ │ │ │ ├── javassist
│ │ │ │ │ ├── ClassPathFilter.java
│ │ │ │ │ └── ClassPoolAccessor.java
│ │ │ │ └── webxml
│ │ │ │ │ ├── BaseWebXmlAnalyzer.java
│ │ │ │ │ ├── Param.java
│ │ │ │ │ └── WebXmlHandler.java
│ │ │ └── plugin
│ │ │ │ ├── CustomXml.java
│ │ │ │ ├── DeadCodeLogger.java
│ │ │ │ ├── FindDeadCodeMojo.java
│ │ │ │ ├── FindDeadCodeOnlyMojo.java
│ │ │ │ ├── ModuleGenerator.java
│ │ │ │ ├── SubDirectoryFilter.java
│ │ │ │ ├── UsageStatisticsManager.java
│ │ │ │ └── packaginghandler
│ │ │ │ ├── DefaultPackagingHandler.java
│ │ │ │ ├── PackagingHandler.java
│ │ │ │ ├── PomPackagingHandler.java
│ │ │ │ └── WarPackagingHandler.java
│ │ │ ├── guava
│ │ │ ├── NonNullFunction.java
│ │ │ ├── NonNullFunctions.java
│ │ │ └── SequentialLoadingCache.java
│ │ │ ├── javaparser
│ │ │ ├── ImportDeclarations.java
│ │ │ └── Nodes.java
│ │ │ ├── javassist
│ │ │ └── CtClasses.java
│ │ │ └── maven
│ │ │ ├── UpdateChecker.java
│ │ │ └── slf4j
│ │ │ ├── AbstractSlf4jMojo.java
│ │ │ ├── LoggerForMavenLog.java
│ │ │ └── MavenPluginLoggerFactory.java
│ │ └── org
│ │ └── slf4j
│ │ └── impl
│ │ └── StaticLoggerBinder.java
└── test
│ ├── java
│ ├── A.java
│ ├── AnnotatedClass.java
│ ├── B.java
│ ├── ClassAnnotatedWithAnnotatedAnnotation.java
│ ├── ClassImplementingCloneable.java
│ ├── ClassImplementingExternalizable.java
│ ├── ClassWithInnerClass.java
│ ├── ClassWithTypeArgument.java
│ ├── CustomNamespaceHandler.java
│ ├── DeadServlet.java
│ ├── DependingClass.java
│ ├── IndependentClass.java
│ ├── MainClass.java
│ ├── SingleClass.java
│ ├── SomeServletInitializer.java
│ ├── SpringXmlBean.java
│ ├── SubClassOfAnnotatedClass.java
│ ├── SubClassOfClassImplementingExternalizable.java
│ ├── SubClassOfSubClassThatShouldBeLive.java
│ ├── SubClassThatShouldBeLive.java
│ ├── TagClass.java
│ ├── TagExtraInfo.java
│ ├── TagLibraryValidator.java
│ ├── TypeParameterClass.java
│ ├── WebAppFilter.java
│ ├── WebAppListener.java
│ ├── WebAppServlet.java
│ └── de
│ │ └── is24
│ │ ├── deadcode4j
│ │ ├── A_DeadCodeComputer.java
│ │ ├── A_DeadCodeFinder.java
│ │ ├── A_Module.java
│ │ ├── A_Repository.java
│ │ ├── A_Utils.java
│ │ ├── An_IntermediateResultMap.java
│ │ ├── An_IntermediateResultSet.java
│ │ ├── An_IntermediateResults.java
│ │ ├── AnalysisContextBuilder.java
│ │ ├── IntermediateResultMapBuilder.java
│ │ ├── ModuleBuilder.java
│ │ ├── analyzer
│ │ │ ├── AByteCodeAnalyzer.java
│ │ │ ├── A_ByteCodeAnalyzer.java
│ │ │ ├── A_ClassDependencyAnalyzer.java
│ │ │ ├── A_CustomAnnotationsAnalyzer.java
│ │ │ ├── A_CustomInterfacesAnalyzer.java
│ │ │ ├── A_CustomSuperClassAnalyzer.java
│ │ │ ├── A_CustomXmlAnalyzer.java
│ │ │ ├── A_HibernateAnnotationsAnalyzer.java
│ │ │ ├── A_JavaFileAnalyzer.java
│ │ │ ├── A_JerseyWebXmlAnalyzer.java
│ │ │ ├── A_LogbackXmlAnalyzer.java
│ │ │ ├── A_MainClassAnalyzer.java
│ │ │ ├── A_ReferenceToConstantsAnalyzer.java
│ │ │ ├── A_ServletContainerInitializerAnalyzer.java
│ │ │ ├── A_SimpleXmlAnalyzer.java
│ │ │ ├── A_SpringDataCustomRepositoriesAnalyzer.java
│ │ │ ├── A_SpringNamespaceHandlerAnalyzer.java
│ │ │ ├── A_SpringWebXmlAnalyzer.java
│ │ │ ├── A_SpringXmlAnalyzer.java
│ │ │ ├── A_SuperClassAnalyzer.java
│ │ │ ├── A_TldAnalyzer.java
│ │ │ ├── A_TypeErasureAnalyzer.java
│ │ │ ├── A_WebXmlAnalyzer.java
│ │ │ ├── AnAnalyzer.java
│ │ │ ├── An_AnnotationsAnalyzer.java
│ │ │ ├── An_ExtendedXmlAnalyzer.java
│ │ │ ├── An_IgnoreClassesAnalyzer.java
│ │ │ ├── An_InterfacesAnalyzer.java
│ │ │ ├── An_XmlAnalyzer.java
│ │ │ ├── classdependency
│ │ │ │ └── ClassWithInnerClasses.java
│ │ │ ├── constants
│ │ │ │ ├── AnnotationUsingConstantAsDefault.java
│ │ │ │ ├── AnonymousClassUsingConstantOfOuterClassInFieldDirectly.java
│ │ │ │ ├── ClassCallingMethodOfStaticallyImportedConstantInField.java
│ │ │ │ ├── ClassCallingMethodOnConstantOfImportedClassInField.java
│ │ │ │ ├── ClassCallingMethodOnConstantOfNestedClassOfImportedClassInField.java
│ │ │ │ ├── ClassUsingConstantInExpression.java
│ │ │ │ ├── ClassUsingConstantInField.java
│ │ │ │ ├── ClassUsingConstantInMethod.java
│ │ │ │ ├── ClassUsingConstantOfImplementedInterfaceInField.java
│ │ │ │ ├── ClassUsingConstantOfInnerClassViaStaticImportInField.java
│ │ │ │ ├── ClassUsingConstantOfSuperclassInMethod.java
│ │ │ │ ├── ClassUsingConstantViaAsteriskStaticImportInField.java
│ │ │ │ ├── ClassUsingConstantViaStaticImportInExpression.java
│ │ │ │ ├── ClassUsingConstantViaStaticImportInField.java
│ │ │ │ ├── ClassUsingConstantViaStaticImportInMethod.java
│ │ │ │ ├── ClassUsingConstantViaStaticImportInSwitch.java
│ │ │ │ ├── ClassUsingEnumConstantInSwitch.java
│ │ │ │ ├── ClassUsingFQConstantInExpression.java
│ │ │ │ ├── ClassUsingFQConstantInField.java
│ │ │ │ ├── ClassUsingFQConstantInMethod.java
│ │ │ │ ├── ClassUsingInnerClassOfConstantInField.java
│ │ │ │ ├── ClassUsingInnerClassOfConstantViaAsteriskStaticImportInField.java
│ │ │ │ ├── ClassUsingInnerClassOfConstantViaStaticImportInField.java
│ │ │ │ ├── ClassUsingNestedConstantOfImplementedInterfaceInField.java
│ │ │ │ ├── ClassUsingNestedConstantOfSuperclassInMethod.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameFieldNameBeingDeclaredAfterItIsReferencedInMethod.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameFieldNameDefinedByInnerClassInMethod.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameFieldNameInMethod.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameLocalNameInMethod.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameLocalNameInStaticInitializer.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameLocalNameInSuperiorBlocksMethod.java
│ │ │ │ ├── ClassUsingStaticImportForConstantWithSameStaticFieldNameInMethod.java
│ │ │ │ ├── ClassUsingStaticMethodInStaticField.java
│ │ │ │ ├── ClassUsingStaticMethodOfNestedClassInMethod.java
│ │ │ │ ├── ClassUsingStaticMethodOfStaticallyImportedClassInMethod.java
│ │ │ │ ├── ClassWithInnerClassNamedLikePotentialTarget.java
│ │ │ │ ├── Constants.java
│ │ │ │ ├── EnumUsingConstantInField.java
│ │ │ │ ├── InnerClassUsingConstantOfImplementedInterfaceInExpression.java
│ │ │ │ ├── InnerClassUsingConstantOfOuterClassInFieldDirectly.java
│ │ │ │ ├── InnerClassUsingConstantOfOuterClassInFieldViaQualifier.java
│ │ │ │ ├── InnerClassUsingNestedConstantOfImplementedInterfaceInExpression.java
│ │ │ │ ├── ReferenceToInheritedConstant.java
│ │ │ │ ├── ReferenceToInheritedNonConstant.java
│ │ │ │ ├── Superclass.java
│ │ │ │ └── subpackage
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageInExpression.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageInField.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageInMethod.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaAsteriskImportInExpression.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaAsteriskImportInField.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaAsteriskImportInMethod.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaAsteriskStaticImportInField.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaStaticImportInExpression.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaStaticImportInField.java
│ │ │ │ │ ├── ClassUsingConstantOfOtherPackageViaStaticImportInMethod.java
│ │ │ │ │ ├── ClassUsingFQConstantOfOtherPackageInExpression.java
│ │ │ │ │ ├── ClassUsingFQConstantOfOtherPackageInField.java
│ │ │ │ │ ├── ClassUsingFQConstantOfOtherPackageInMethod.java
│ │ │ │ │ ├── ClassUsingImportForConstantWithSameFieldNameInMethod.java
│ │ │ │ │ ├── ClassUsingImportForConstantWithSameLocalNameInMethod.java
│ │ │ │ │ ├── ClassUsingImportForConstantWithSameParameterNameInCatchClause.java
│ │ │ │ │ ├── ClassUsingImportForConstantWithSameParameterNameInConstructor.java
│ │ │ │ │ ├── ClassUsingImportForConstantWithSameParameterNameInMethod.java
│ │ │ │ │ ├── ClassUsingImportForConstantWithSameStaticFieldNameInMethod.java
│ │ │ │ │ ├── ClassUsingInnerClassOfConstantOfOtherPackageInField.java
│ │ │ │ │ └── EnumUsingImportForConstantWithSameEnumName.java
│ │ │ ├── customrepositories
│ │ │ │ ├── Foo.java
│ │ │ │ ├── FooRepository.java
│ │ │ │ ├── FooRepositoryCustom.java
│ │ │ │ └── FooRepositoryImpl.java
│ │ │ ├── hibernateannotations
│ │ │ │ ├── AnotherEntity.java
│ │ │ │ ├── AnotherEntityWithGeneratedValue.java
│ │ │ │ ├── ClassDefiningGenericGenerator.java
│ │ │ │ ├── ClassUsingGeneratedValueAtField.java
│ │ │ │ ├── ClassUsingGeneratedValueAtMethod.java
│ │ │ │ ├── ClassUsingTypeAtField.java
│ │ │ │ ├── ClassUsingTypeAtMethod.java
│ │ │ │ ├── ClassUsingTypeWithoutTypeDef.java
│ │ │ │ ├── ClassWithDuplicatedTypeDef.java
│ │ │ │ ├── ClassWithTypeDef.java
│ │ │ │ ├── Entity.java
│ │ │ │ ├── EntityWithGeneratedValue.java
│ │ │ │ ├── knownStrategies
│ │ │ │ │ ├── ClassDefiningGenericGenerator.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ ├── javassist
│ │ │ │ └── A_CtClasses.java
│ │ │ ├── typeerasure
│ │ │ │ ├── ClassWithAnonymousClasses.java
│ │ │ │ ├── ClassWithInheritedType.java
│ │ │ │ ├── ClassWithLowerBoundedWildCard.java
│ │ │ │ ├── ClassWithTypesThatShouldNotBeRecognized.java
│ │ │ │ ├── ClassWithUpperBoundedWildCard.java
│ │ │ │ ├── PackageClass.java
│ │ │ │ └── TypedArrayList.java
│ │ │ └── webxml
│ │ │ │ └── A_BaseWebXmlAnalyzer.java
│ │ ├── junit
│ │ │ ├── AUtilityClass.java
│ │ │ ├── AnnotatedAnnotation.java
│ │ │ ├── Annotation.java
│ │ │ ├── FileLoader.java
│ │ │ ├── LoggingRule.java
│ │ │ ├── SomeInterface.java
│ │ │ └── TempFileRule.java
│ │ └── plugin
│ │ │ ├── A_DeadCodeLogger.java
│ │ │ ├── A_ModuleGenerator.java
│ │ │ ├── A_UsageStatisticsManager.java
│ │ │ ├── IT_PuttingItAllTogether.java
│ │ │ ├── packaginghandler
│ │ │ └── A_PackagingHandler.java
│ │ │ └── stubs
│ │ │ └── ProjectStub.java
│ │ ├── guava
│ │ ├── A_NonNullFunctions.java
│ │ └── A_SequentialLoadingCacheTest.java
│ │ ├── javaparser
│ │ ├── A_Nodes.java
│ │ └── An_ImportDeclarations.java
│ │ └── maven
│ │ ├── An_UpdateChecker.java
│ │ └── slf4j
│ │ ├── A_LoggerForMavenLog.java
│ │ └── An_AbstractSlf4jMojo.java
│ └── resources
│ ├── META-INF
│ └── spring.handlers
│ ├── de
│ └── is24
│ │ ├── deadcode4j
│ │ ├── analyzer
│ │ │ ├── empty.xml
│ │ │ ├── jersey.web.xml
│ │ │ ├── logback.xml
│ │ │ ├── prefixed.xml
│ │ │ ├── some.xml
│ │ │ ├── spring.web.xml
│ │ │ ├── v3-metadata-complete.web.xml
│ │ │ ├── v3-metadata-incomplete.web.xml
│ │ │ ├── v3-metadata-missing.web.xml
│ │ │ └── webxml
│ │ │ │ └── web.xml
│ │ ├── java8
│ │ │ └── Lambda.java
│ │ └── plugin
│ │ │ └── projects
│ │ │ ├── misconfig.pom.xml
│ │ │ └── pom.xml
│ │ └── javaparser
│ │ └── TypeNameTestClass.java
│ ├── nospring.xml
│ ├── spring-with-prefix.xml
│ ├── spring.xml
│ ├── taglib.tld
│ └── web.xml
└── tools
├── check-code.sh
└── update-versions.sh
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | # workflow_dispatch enables manual triggering of the workflow
5 | workflow_dispatch:
6 | schedule:
7 | - cron: '27 1 * * 6'
8 | env:
9 | FAST_EMAIL: ${{ secrets.FAST_EMAIL }}
10 | FAST_USER: ${{ secrets.FAST_USER }}
11 | FAST_TOKEN: ${{ secrets.FAST_TOKEN }}
12 | FAST_HTTPAUTH: ${{ secrets.FAST_HTTPAUTH }}
13 |
14 | jobs:
15 | analyze:
16 | name: Analyze
17 | runs-on: ubuntu-latest
18 | permissions:
19 | actions: read
20 | contents: read
21 | security-events: write
22 |
23 | steps:
24 | - name: S24 static application security testing (SAST) action
25 | uses: scout24/s24-sast-action@v1
26 | with:
27 | languages: java
28 | fast_user: ${{ env.FAST_USER }}
29 | fast_token: ${{ env.FAST_TOKEN }}
30 | java_version: '11'
31 |
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #IDEA files
2 | .idea
3 | *.iml
4 | #Maven files
5 | target
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: java
3 | jdk:
4 | - openjdk6
5 | - openjdk7
6 | - oraclejdk7
7 | - oraclejdk8
8 | env:
9 | - MVN_VERSION=3.0.5
10 | - MVN_VERSION=3.1.1
11 | - MVN_VERSION=3.2.5
12 | - MVN_VERSION=3.3.9
13 | matrix:
14 | exclude:
15 | - jdk: openjdk6
16 | env: MVN_VERSION=3.3.9
17 |
18 | cache:
19 | apt: false
20 | bundler: false
21 | directories:
22 | - $HOME/.m2/repository
23 | before_cache: rm -rf $HOME/.m2/repository/de/is24/mavenplugins/deadcode4j-maven-plugin/
24 |
25 | before_install:
26 | # install Maven according to build matrix
27 | - MVN_URL=https://archive.apache.org/dist/maven/maven-3/$MVN_VERSION/binaries/apache-maven-$MVN_VERSION-bin.tar.gz
28 | - wget -q -O /tmp/maven.tar.gz $MVN_URL
29 | - tar xzf /tmp/maven.tar.gz
30 | - export M2_HOME=`pwd`/apache-maven-$MVN_VERSION
31 | - export PATH=$M2_HOME/bin:$PATH
32 | # https://github.com/travis-ci/travis-ci/issues/1689 & https://github.com/travis-ci/travis-ci/issues/4613
33 | - export MAVEN_SKIP_RC=true
34 |
35 | install:
36 | #attempt to download all dependencies in the install phase; due to http://jira.codehaus.org/browse/MDEP-82, dependency:go-offline is useless
37 | - mvn -B -U clean verify org.apache.maven.plugins:maven-war-plugin:2.6:help -Dinvoker.skip=true -Dmaven.main.skip=true -Dmaven.plugin.skip=true -Dmaven.test.skip=true -PenableCoverage,travis
38 | # surefire seems to add these dependencies dynamically
39 | - mvn -B org.apache.maven.plugins:maven-dependency-plugin:2.10:get -Dartifact=org.apache.maven.surefire:surefire-junit4:2.17
40 | - mvn -B org.apache.maven.plugins:maven-dependency-plugin:2.10:get -Dartifact=org.apache.maven.surefire:surefire-junit47:2.17
41 | script: mvn -B -o clean verify -PenableCoverage,travis
42 | after_success: mvn -B jacoco:report coveralls:jacoco
43 |
44 | notifications:
45 | webhooks:
46 | urls:
47 | - https://webhooks.gitter.im/e/217ded7d3afc66dca26a
48 | on_success: always
49 | on_failure: always
50 | on_start: false
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # deadcode4j [](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.is24.mavenplugins%22%20AND%20a%3A%22deadcode4j-maven-plugin%22) [](https://travis-ci.org/ImmobilienScout24/deadcode4j) [](https://coveralls.io/r/ImmobilienScout24/deadcode4j?branch=master)
2 |
3 | [](https://gitter.im/ImmobilienScout24/deadcode4j?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 |
5 |
6 |
7 | *deadcode4j* helps you find code that is no longer used by your application. It is especially useful for cleaning up legacy code.
8 |
9 | As *deadcode4j* is available via the Maven repository, you can simply run
10 | `mvn de.is24.mavenplugins:deadcode4j-maven-plugin:find -Dmaven.test.skip=true`
11 | to analyze your project.
12 | *deadcode4j* will trigger the _package phase_ to be executed for a project (and for all modules listed in a reactor project) before analyzing the output directories.
13 | The output will look something like this:
14 |
15 | [INFO] --- deadcode4j-maven-plugin:2.1.0:find (default-cli) @ someProject ---
16 | [INFO] Analyzed 42 class(es).
17 | [WARNING] Found 2 unused class(es):
18 | [WARNING] de.is24.deadcode4j.Foo
19 | [WARNING] de.is24.deadcode4j.Bar
20 |
21 | Have a look at the [wiki](https://github.com/ImmobilienScout24/deadcode4j/wiki) to get to know the
22 | [features](https://github.com/ImmobilienScout24/deadcode4j/wiki/deadcode4j-v2.1.0%3A-Features),
23 | read about the available [goals](https://github.com/ImmobilienScout24/deadcode4j/wiki/deadcode4j-v2.1.0%3A-Usage),
24 | understand the [configuration](https://github.com/ImmobilienScout24/deadcode4j/wiki/deadcode4j-v2.1.0%3A-Configuration)
25 | or learn *deadcode4j*'s history and principles.
26 |
27 | *deadcode4j* is tested with Maven 3.0.5, 3.1.1, 3.2.5 & 3.3.9.
28 |
--------------------------------------------------------------------------------
/config/FindBugsExcludeFilter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/config/pmd-ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | deadcode4j PMD ruleset
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/config/version-rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | .*-beta
8 |
9 |
--------------------------------------------------------------------------------
/src/it/brokenFiles/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | parent
9 | 42
10 | ../pom.xml
11 |
12 |
13 | brokenFiles
14 | 42
15 | jar
16 | This project is used to make sure failing file analysis is a) reported and b) handled gracefully
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/it/brokenFiles/src/main/resources/Broken.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Scout24/deadcode4j/166a87945398d99811f52136883476cf94aa1208/src/it/brokenFiles/src/main/resources/Broken.class
--------------------------------------------------------------------------------
/src/it/brokenFiles/src/main/resources/Broken.java:
--------------------------------------------------------------------------------
1 | public class Broken () {
2 | Barbar;
3 | }
--------------------------------------------------------------------------------
/src/it/brokenFiles/src/main/resources/Broken.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/it/brokenFiles/verify.bsh:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | File buildLog = new File(basedir, "build.log");
4 | BufferedReader reader = new BufferedReader(new FileReader(buildLog));
5 | String line;
6 | boolean analysisFailedForFile = false;
7 | while ((line = reader.readLine()) != null) {
8 | if (line.contains("At least one file could not be parsed; analysis may be inaccurate!")) {
9 | analysisFailedForFile = true;
10 | }
11 | }
12 | if (!analysisFailedForFile) {
13 | throw new RuntimeException("Should have warned about analysis issues!");
14 | }
--------------------------------------------------------------------------------
/src/it/customWebAppResourcesAreConsidered/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | parent
9 | 42
10 | ../pom.xml
11 |
12 |
13 | customWebAppResourcesAreConsidered
14 | 42
15 | war
16 |
17 |
18 |
19 |
20 | maven-war-plugin
21 |
22 | ${project.build.directory}/webapp
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/it/customWebAppResourcesAreConsidered/src/main/java/WebAppServlet.java:
--------------------------------------------------------------------------------
1 | public class WebAppServlet {
2 | }
3 |
--------------------------------------------------------------------------------
/src/it/customWebAppResourcesAreConsidered/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | aServlet
10 | WebAppServlet
11 |
12 |
--------------------------------------------------------------------------------
/src/it/customWebAppResourcesAreConsidered/verify.bsh:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | File buildLog = new File(basedir, "build.log");
4 | BufferedReader reader = new BufferedReader(new FileReader(buildLog));
5 | String line;
6 | boolean analyzed = false, success = false;
7 | while ((line = reader.readLine()) != null) {
8 | if (line.contains("Analyzed 1 class(es).")) {
9 | analyzed = true;
10 | } else if (line.contains("No unused classes found.")) {
11 | success = true;
12 | }
13 | }
14 | if (!analyzed) {
15 | throw new RuntimeException("Did not analyze any class; this is not expected!");
16 | } else if (!success) {
17 | throw new RuntimeException("Found unused classes; this is not expected!");
18 | }
--------------------------------------------------------------------------------
/src/it/defaultWebAppResourcesAreConsidered/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | parent
9 | 42
10 | ../pom.xml
11 |
12 |
13 | defaultWebAppResourcesAreConsidered
14 | 42
15 | war
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/defaultWebAppResourcesAreConsidered/src/main/java/WebAppServlet.java:
--------------------------------------------------------------------------------
1 | public class WebAppServlet {
2 | }
3 |
--------------------------------------------------------------------------------
/src/it/defaultWebAppResourcesAreConsidered/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | aServlet
10 | WebAppServlet
11 |
12 |
--------------------------------------------------------------------------------
/src/it/defaultWebAppResourcesAreConsidered/verify.bsh:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | File buildLog = new File(basedir, "build.log");
4 | BufferedReader reader = new BufferedReader(new FileReader(buildLog));
5 | String line;
6 | boolean analyzed = false, success = false;
7 | while ((line = reader.readLine()) != null) {
8 | if (line.contains("Analyzed 1 class(es).")) {
9 | analyzed = true;
10 | } else if (line.contains("No unused classes found.")) {
11 | success = true;
12 | }
13 | }
14 | if (!analyzed) {
15 | throw new RuntimeException("Did not analyze any class; this is not expected!");
16 | } else if (!success) {
17 | throw new RuntimeException("Found unused classes; this is not expected!");
18 | }
--------------------------------------------------------------------------------
/src/it/help/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | parent
9 | 42
10 | ../pom.xml
11 |
12 |
13 | help
14 | 42
15 | pom
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | de.is24.junit
7 | parent
8 | 42
9 | pom
10 |
11 |
12 | 1.6
13 | 1.6
14 | UTF-8
15 | UTF-8
16 |
17 |
18 |
19 |
20 |
21 |
22 | de.is24.mavenplugins
23 | deadcode4j-maven-plugin
24 | @project.version@
25 |
26 |
27 |
28 | maven-resources-plugin
29 | 3.0.0
30 |
31 |
32 | maven-compiler-plugin
33 | 3.5.1
34 |
35 |
36 | maven-surefire-plugin
37 | 2.17
38 |
39 |
40 | maven-jar-plugin
41 | 3.0.0
42 |
43 |
44 | maven-war-plugin
45 | 2.6
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/it/reactorProject/emptyProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-emptyProject
14 | 42
15 | jar
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/reactorProject/javaProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-javaProject
14 | 42
15 | jar
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/reactorProject/javaProject/src/main/java/WebAppServlet.java:
--------------------------------------------------------------------------------
1 | public class WebAppServlet {
2 | }
3 |
--------------------------------------------------------------------------------
/src/it/reactorProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | parent
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject
14 | 42
15 | pom
16 |
17 |
18 |
19 |
20 |
21 | de.is24.mavenplugins
22 | deadcode4j-maven-plugin
23 |
24 |
25 | secondReactorProject
26 | secondJavaProject
27 | nonExistingProject
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | emptyProject
37 | javaProject
38 | webAppProject
39 | secondWebAppProject
40 |
41 | secondJavaProject
42 | secondReactorProject
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondJavaProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-secondJavaProject
14 | 42
15 | jar
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondJavaProject/src/main/java/UnusedClassInSecondJavaProject.java:
--------------------------------------------------------------------------------
1 | public class UnusedClassInSecondJavaProject {
2 | }
3 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondReactorProject/nestedJavaProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject-secondReactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-secondReactorProject-nestedJavaProject
14 | 42
15 | jar
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondReactorProject/nestedJavaProject/src/main/java/UnusedClassInNestedJavaProject.java:
--------------------------------------------------------------------------------
1 | public class UnusedClassInNestedJavaProject {
2 | }
3 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondReactorProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-secondReactorProject
14 | 42
15 | pom
16 |
17 |
18 | nestedJavaProject
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondWebAppProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-secondWebAppProject
14 | 42
15 | war
16 |
17 |
18 |
19 | de.is24.junit
20 | reactorProject-javaProject
21 | 42
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondWebAppProject/src/main/java/SecondServlet.java:
--------------------------------------------------------------------------------
1 | public class SecondServlet {
2 | }
3 |
--------------------------------------------------------------------------------
/src/it/reactorProject/secondWebAppProject/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | secondServlet
10 | SecondServlet
11 |
12 |
--------------------------------------------------------------------------------
/src/it/reactorProject/verify.bsh:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | File buildLog = new File(basedir, "build.log");
4 | BufferedReader reader = new BufferedReader(new FileReader(buildLog));
5 | String line;
6 | boolean analyzed = false, success = false;
7 | while ((line = reader.readLine()) != null) {
8 | if (line.contains("Analyzed 2 class(es).")) {
9 | analyzed = true;
10 | } else if (line.contains("No unused classes found.")) {
11 | success = true;
12 | }
13 | }
14 | if (!analyzed) {
15 | throw new RuntimeException("Did not analyze the expected number of classes!");
16 | } else if (!success) {
17 | throw new RuntimeException("Found unused classes; this is not expected!");
18 | }
--------------------------------------------------------------------------------
/src/it/reactorProject/webAppProject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | reactorProject
9 | 42
10 | ../pom.xml
11 |
12 |
13 | reactorProject-webAppProject
14 | 42
15 | war
16 |
17 |
18 |
19 | de.is24.junit
20 | reactorProject-javaProject
21 | 42
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/it/reactorProject/webAppProject/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | aServlet
10 | WebAppServlet
11 |
12 |
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/definitions/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | scatteredHibernate
9 | 42
10 | ./../pom.xml
11 |
12 |
13 | scatteredHibernate-definitions
14 | ${project.parent.version}
15 | jar
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/definitions/src/main/java/de/is24/junit/typedefs/package-info.java:
--------------------------------------------------------------------------------
1 | @TypeDefs({
2 | @TypeDef(name = "customClass", typeClass = String.class)})
3 | package de.is24.junit.typedefs;
4 |
5 | import org.hibernate.annotations.TypeDef;
6 | import org.hibernate.annotations.TypeDefs;
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/overriding-definition/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | scatteredHibernate
9 | 42
10 | ./../pom.xml
11 |
12 |
13 | scatteredHibernate-overriding-definition
14 | ${project.parent.version}
15 | jar
16 |
17 |
18 |
19 | de.is24.junit
20 | scatteredHibernate-usages
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/overriding-definition/src/main/java/de/is24/junit/overriding_typedefs/package-info.java:
--------------------------------------------------------------------------------
1 | @TypeDefs({
2 | @TypeDef(name = "numberClass", typeClass = Number.class)})
3 | package de.is24.junit.overriding_typedefs;
4 |
5 | import org.hibernate.annotations.TypeDef;
6 | import org.hibernate.annotations.TypeDefs;
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/usages/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | de.is24.junit
8 | scatteredHibernate
9 | 42
10 | ./../pom.xml
11 |
12 |
13 | scatteredHibernate-usages
14 | ${project.parent.version}
15 | jar
16 |
17 |
18 |
19 | de.is24.junit
20 | scatteredHibernate-definitions
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/usages/src/main/java/de/is24/junit/EntityClass.java:
--------------------------------------------------------------------------------
1 | package de.is24.junit;
2 |
3 | import javax.persistence.Id;
4 | import org.hibernate.annotations.Type;
5 |
6 | public class EntityClass {
7 |
8 | @Id
9 | @Type(type = "numberClass")
10 | private long id;
11 |
12 | @Type(type = "customClass")
13 | private String content;
14 |
15 | }
--------------------------------------------------------------------------------
/src/it/scatteredHibernate/verify.bsh:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | File buildLog = new File(basedir, "build.log");
4 | BufferedReader reader = new BufferedReader(new FileReader(buildLog));
5 | String line;
6 | boolean analyzed = false, success = false;
7 | while ((line = reader.readLine()) != null) {
8 | if (line.contains("Analyzed 3 class(es).")) {
9 | analyzed = true;
10 | } else if (line.contains("No unused classes found.")) {
11 | success = true;
12 | }
13 | }
14 | if (!analyzed) {
15 | throw new RuntimeException("Did not analyze the expected number of classes!");
16 | } else if (!success) {
17 | throw new RuntimeException("Found unused classes; this is not expected!");
18 | }
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/AnalysisStage.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | /**
4 | * Represents the various stages of deadcode4j's analysis process.
5 | *
6 | * @since 2.0.0
7 | */
8 | public enum AnalysisStage {
9 | GENERAL_SETUP, MODULE_SETUP, FILE_ANALYSIS, DEADCODE_ANALYSIS
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/AnalyzedCode.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import javax.annotation.Nonnull;
4 | import java.util.EnumSet;
5 | import java.util.Map;
6 | import java.util.Set;
7 |
8 | /**
9 | * AnalyzedCode
comprises the classes being analyzed as well as the code dependencies.
10 | *
11 | * @since 1.0.0
12 | */
13 | public class AnalyzedCode {
14 | @Nonnull
15 | private final EnumSet stagesWithExceptions;
16 | @Nonnull
17 | private final Set analyzedClasses;
18 | @Nonnull
19 | private final Map> codeDependencies;
20 |
21 | public AnalyzedCode(@Nonnull EnumSet stagesWithExceptions,
22 | @Nonnull Set analyzedClasses,
23 | @Nonnull Map> codeDependencies) {
24 | this.stagesWithExceptions = stagesWithExceptions;
25 | this.analyzedClasses = analyzedClasses;
26 | this.codeDependencies = codeDependencies;
27 | }
28 |
29 | @Nonnull
30 | public Set getAnalyzedClasses() {
31 | return analyzedClasses;
32 | }
33 |
34 | /**
35 | * Returns a map consisting of code artifacts (typically classes) pointing to their dependencies.
36 | */
37 | @Nonnull
38 | public Map> getCodeDependencies() {
39 | return codeDependencies;
40 | }
41 |
42 | /**
43 | * Returns the stages for which an exception occurred.
44 | *
45 | * @since 2.0.0
46 | */
47 | @Nonnull
48 | public EnumSet getStagesWithExceptions() {
49 | return stagesWithExceptions;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/Analyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import javax.annotation.Nonnull;
4 | import java.io.File;
5 |
6 | /**
7 | * An Analyzer
analyzes code of all flavours: java classes, spring XML files, web.xml etc.
8 | *
9 | * @since 1.1.0
10 | */
11 | public interface Analyzer {
12 |
13 | /**
14 | * Perform an analysis for the specified file.
15 | * Results must be reported via the capabilities of the {@link AnalysisContext}.
16 | *
17 | * @since 1.1.0
18 | */
19 | void doAnalysis(@Nonnull AnalysisContext analysisContext, @Nonnull File fileName);
20 |
21 | /**
22 | * Indicates that all files of a module have been processed.
23 | * This method offers Analyzer
s the possibility to report dependencies based on a module or store
24 | * {@link de.is24.deadcode4j.IntermediateResult}s.
25 | *
26 | * @since 1.4
27 | */
28 | void finishAnalysis(@Nonnull AnalysisContext analysisContext);
29 |
30 | /**
31 | * Indicates that all modules have been processed.
32 | * This method offers Analyzer
s the possibility to report dependencies based on the whole project.
33 | *
34 | * @since 2.0.0
35 | */
36 | void finishAnalysis(@Nonnull AnalysisSink analysisSink, @Nonnull AnalyzedCode analyzedCode);
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/DeadCode.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import javax.annotation.Nonnull;
4 | import java.util.Collection;
5 | import java.util.EnumSet;
6 |
7 | /**
8 | * DeadCode
provides the results of the {@link DeadCodeFinder}.
9 | *
10 | * @since 1.0.0
11 | */
12 | public class DeadCode {
13 | @Nonnull
14 | private final EnumSet stagesWithExceptions;
15 | @Nonnull
16 | private final Collection analyzedClasses;
17 | @Nonnull
18 | private final Collection deadClasses;
19 |
20 | public DeadCode(@Nonnull EnumSet stagesWithExceptions,
21 | @Nonnull Collection analyzedClasses,
22 | @Nonnull Collection deadClasses) {
23 | this.stagesWithExceptions = stagesWithExceptions;
24 | this.analyzedClasses = analyzedClasses;
25 | this.deadClasses = deadClasses;
26 | }
27 |
28 | @Nonnull
29 | public Collection getAnalyzedClasses() {
30 | return this.analyzedClasses;
31 | }
32 |
33 | @Nonnull
34 | public Collection getDeadClasses() {
35 | return this.deadClasses;
36 | }
37 |
38 | /**
39 | * Returns the stages for which an exception occurred.
40 | *
41 | * @since 2.0.0
42 | */
43 | @Nonnull
44 | public EnumSet getStagesWithExceptions() {
45 | return stagesWithExceptions;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/DeadCodeComputer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import javax.annotation.Nonnull;
4 | import java.util.Collection;
5 | import java.util.List;
6 | import java.util.Set;
7 |
8 | import static com.google.common.collect.Lists.newArrayList;
9 | import static com.google.common.collect.Sets.newHashSet;
10 |
11 | /**
12 | * The DeadCodeComputer
computes the {@link DeadCode} based on {@link AnalyzedCode}.
13 | *
14 | * @since 2.0.0
15 | */
16 | public class DeadCodeComputer {
17 |
18 | @Nonnull
19 | public DeadCode computeDeadCode(@Nonnull AnalyzedCode analyzedCode) {
20 | Collection deadClasses = determineDeadClasses(analyzedCode);
21 | return new DeadCode(analyzedCode.getStagesWithExceptions(), analyzedCode.getAnalyzedClasses(), deadClasses);
22 | }
23 |
24 | @Nonnull
25 | private Collection determineDeadClasses(@Nonnull AnalyzedCode analyzedCode) {
26 | Set classesInUse = newHashSet();
27 | for (Iterable usedClasses : analyzedCode.getCodeDependencies().values()) {
28 | for (String clazz : usedClasses) {
29 | classesInUse.add(clazz);
30 | }
31 | }
32 |
33 | List deadClasses = newArrayList(analyzedCode.getAnalyzedClasses());
34 | deadClasses.removeAll(classesInUse);
35 | return deadClasses;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/IntermediateResult.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import javax.annotation.Nonnull;
4 |
5 | /**
6 | * If an IntermediateResult
is put into an {@link AnalysisContext#getCache() analysis context's cache},
7 | * it will be made available to the analysis context of those modules depending on the module the result belongs to.
8 | *
9 | * @since 2.0.0
10 | */
11 | public interface IntermediateResult {
12 |
13 | /**
14 | * If a module depends on both module A and B, each providing an intermediate result for the same key,
15 | * the results will be merged by calling this method on A's result using B's result as a parameter.
16 | * Note that if collisions occur, A's results should usually be preferred as A is listed higher in the
17 | * class path.
18 | * It is important that neither result is modified by this call.
19 | *
20 | * @param sibling the IntermediateResult
to merge with
21 | * @return a new IntermediateResult
instance
22 | * @since 2.0.0
23 | */
24 | @Nonnull
25 | IntermediateResult mergeSibling(@Nonnull IntermediateResult sibling);
26 |
27 | /**
28 | * If a module depends on module A which in turn depends on module B, both providing an intermediate
29 | * result for the same key, the results will be merged by calling this method on A's result using B's
30 | * result as a parameter.
31 | * Note that if collisions occur, A's results should be preferred as A is listed higher in the class
32 | * path.
33 | * It is important that neither result is modified by this call.
34 | *
35 | * @param parent the IntermediateResult
to merge with
36 | * @return a new IntermediateResult
instance
37 | * @since 2.0.0
38 | */
39 | @Nonnull
40 | IntermediateResult mergeParent(@Nonnull IntermediateResult parent);
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/Repository.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import javax.annotation.Nonnull;
4 | import java.io.File;
5 | import java.io.FileFilter;
6 |
7 | import static com.google.common.base.Preconditions.checkArgument;
8 | import static org.apache.commons.io.filefilter.TrueFileFilter.TRUE;
9 |
10 | /**
11 | * A Repository
represents a directory containing code, resources, configuration, etc.
12 | * along with an optional file filter.
13 | *
14 | * @since 1.2.0
15 | */
16 | public class Repository {
17 | @Nonnull
18 | private final File directory;
19 | @Nonnull
20 | private final FileFilter fileFilter;
21 |
22 | public Repository(@Nonnull File directory, @Nonnull FileFilter fileFilter) {
23 | checkArgument(directory.isDirectory(), "No valid directory: " + directory);
24 | this.directory = directory;
25 | this.fileFilter = fileFilter;
26 | }
27 |
28 | public Repository(@Nonnull File directory) {
29 | this(directory, TRUE);
30 | }
31 |
32 | @Nonnull
33 | @Override
34 | public String toString() {
35 | return "Repository @" + this.directory;
36 | }
37 |
38 | @Nonnull
39 | public File getDirectory() {
40 | return directory;
41 | }
42 |
43 | @Nonnull
44 | public FileFilter getFileFilter() {
45 | return fileFilter;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/Resource.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import com.google.common.base.Optional;
4 |
5 | import java.io.File;
6 |
7 | /**
8 | * A Resource
represents a required artifact/dependency of a Module
.
9 | * It can be a mere class path entry or a Module
which is part of the analysis.
10 | *
11 | * @since 2.0.0
12 | */
13 | public abstract class Resource {
14 |
15 | public static Resource of(final File file) {
16 | return new Resource() {
17 | @Override
18 | public Optional getClassPathEntry() {
19 | return Optional.of(file);
20 | }
21 |
22 | @Override
23 | public Optional getReferencedModule() {
24 | return Optional.absent();
25 | }
26 | };
27 | }
28 |
29 | public static Resource of(final Module module) {
30 | return new Resource() {
31 | @Override
32 | public Optional getClassPathEntry() {
33 | Repository repository = module.getOutputRepository();
34 | return repository != null ? Optional.of(repository.getDirectory()) : Optional.absent();
35 | }
36 |
37 | @Override
38 | public Optional getReferencedModule() {
39 | return Optional.of(module);
40 | }
41 | };
42 | }
43 |
44 | public abstract Optional getClassPathEntry();
45 |
46 | public abstract Optional getReferencedModule();
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/AnalyzerAdapter.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import de.is24.deadcode4j.AnalysisSink;
5 | import de.is24.deadcode4j.AnalyzedCode;
6 | import de.is24.deadcode4j.Analyzer;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import javax.annotation.Nonnull;
11 |
12 | /**
13 | * The AnalyzerAdapter
implements all non-vital methods defined for an Analyzer
with a no-op.
14 | *
15 | * @since 1.4
16 | */
17 | public abstract class AnalyzerAdapter implements Analyzer {
18 |
19 | protected final Logger logger = LoggerFactory.getLogger(getClass());
20 |
21 | @Override
22 | public String toString() {
23 | return getClass().getName();
24 | }
25 |
26 | @Override
27 | public void finishAnalysis(@Nonnull AnalysisContext analysisContext) {
28 | }
29 |
30 | @Override
31 | public void finishAnalysis(@Nonnull AnalysisSink analysisSink, @Nonnull AnalyzedCode analyzedCode) {
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/AopXmlAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes aop.xml files: lists the aspects being referenced.
5 | * This should work for both AspectJ and
6 | * AspectWerkz.
7 | *
8 | * @since 1.5
9 | */
10 | public final class AopXmlAnalyzer extends SimpleXmlAnalyzer {
11 |
12 | public AopXmlAnalyzer() {
13 | super("_AOP-XML_", "aop.xml", null);
14 | registerClassAttribute("aspect", "class");
15 | registerClassAttribute("aspect", "name");
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/ApacheTilesAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes Apache Tiles definition XML files: lists the preparer, bean & item
5 | * classes being referenced.
6 | *
7 | * @since 1.5
8 | */
9 | public final class ApacheTilesAnalyzer extends SimpleXmlAnalyzer {
10 |
11 | public ApacheTilesAnalyzer() {
12 | super("_ApacheTilesXml_", ".xml", "tiles-definitions");
13 | // http://tiles.apache.org/dtds/tiles-config_3_0.dtd
14 | registerClassAttribute("definition", "preparer");
15 | // http://tiles.apache.org/dtds/tiles-config_2_1.dtd
16 | // http://tiles.apache.org/dtds/tiles-config_2_0.dtd
17 | registerClassAttribute("bean", "classtype");
18 | registerClassAttribute("item", "classtype");
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/CastorClassesAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes class files: marks a class as being in use if it directly extends
5 | * org.exolab.castor.xml.util.XMLClassDescriptorImpl
.
6 | *
7 | * @since 1.4
8 | */
9 | public final class CastorClassesAnalyzer extends SuperClassAnalyzer {
10 |
11 | public CastorClassesAnalyzer() {
12 | super("_Castor-GeneratedClass_", "org.exolab.castor.xml.util.XMLClassDescriptorImpl");
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/ClassDependencyAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import javassist.CtClass;
5 |
6 | import javax.annotation.Nonnull;
7 | import java.util.Collection;
8 |
9 | /**
10 | * Analyzes class files: lists the classes a class is depending on.
11 | *
12 | * @since 1.0.0
13 | */
14 | public class ClassDependencyAnalyzer extends ByteCodeAnalyzer {
15 |
16 | @Override
17 | protected void analyzeClass(@Nonnull AnalysisContext analysisContext, @Nonnull CtClass clazz) {
18 | String className = clazz.getName();
19 |
20 | @SuppressWarnings("unchecked")
21 | Collection refClasses = clazz.getRefClasses();
22 |
23 | analysisContext.addAnalyzedClass(className);
24 | analysisContext.addDependencies(className, refClasses);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/CustomAnnotationsAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import de.is24.deadcode4j.AnalysisSink;
5 | import de.is24.deadcode4j.AnalyzedCode;
6 |
7 | import javax.annotation.Nonnull;
8 | import java.util.Set;
9 |
10 | import static com.google.common.collect.Sets.newHashSet;
11 |
12 | /**
13 | * Analyzes class files: marks a class as being in use if it is annotated with one of the specified annotations.
14 | *
15 | * @since 1.3
16 | */
17 | public final class CustomAnnotationsAnalyzer extends AnnotationsAnalyzer {
18 |
19 | @Nonnull
20 | private final Set annotationsNotFoundInClassPath;
21 |
22 | /**
23 | * Creates a new CustomAnnotationsAnalyzer
.
24 | *
25 | * @param customAnnotations a list of fully qualified (annotation) class names indicating a class is still in use
26 | * @since 1.3
27 | */
28 | public CustomAnnotationsAnalyzer(@Nonnull Iterable customAnnotations) {
29 | super("_custom-annotations_", customAnnotations);
30 | annotationsNotFoundInClassPath = newHashSet(customAnnotations);
31 | }
32 |
33 | @Override
34 | public void finishAnalysis(@Nonnull AnalysisContext analysisContext) {
35 | super.finishAnalysis(analysisContext);
36 | annotationsNotFoundInClassPath.removeAll(getAnnotationsFoundInClassPath(analysisContext));
37 | }
38 |
39 | @Override
40 | public void finishAnalysis(@Nonnull AnalysisSink analysisSink, @Nonnull AnalyzedCode analyzedCode) {
41 | super.finishAnalysis(analysisSink, analyzedCode);
42 | for (String interfaceName : annotationsNotFoundInClassPath) {
43 | logger.warn("Annotation [{}] wasn't ever found in the class path. You should remove the configuration entry.", interfaceName);
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/CustomInterfacesAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import de.is24.deadcode4j.AnalysisSink;
5 | import de.is24.deadcode4j.AnalyzedCode;
6 |
7 | import javax.annotation.Nonnull;
8 | import java.util.Set;
9 |
10 | import static com.google.common.collect.Sets.newHashSet;
11 |
12 | /**
13 | * Analyzes class files: marks a class as being in use if it explicitly implements one of the specified interfaces.
14 | *
15 | * @since 1.4
16 | */
17 | public final class CustomInterfacesAnalyzer extends InterfacesAnalyzer {
18 |
19 | @Nonnull
20 | private final Set interfacesNotFoundInClassPath;
21 |
22 | /**
23 | * Creates a new CustomInterfacesAnalyzer
.
24 | *
25 | * @param customInterfaces a list of fully qualified interface names indicating that the implementing class is in use
26 | * @since 1.4
27 | */
28 | public CustomInterfacesAnalyzer(@Nonnull Iterable customInterfaces) {
29 | super("_custom-interfaces_", customInterfaces);
30 | interfacesNotFoundInClassPath = newHashSet(customInterfaces);
31 | }
32 |
33 | @Override
34 | public void finishAnalysis(@Nonnull AnalysisContext analysisContext) {
35 | super.finishAnalysis(analysisContext);
36 | interfacesNotFoundInClassPath.removeAll(getInterfacesFoundInClassPath(analysisContext));
37 | }
38 |
39 | @Override
40 | public void finishAnalysis(@Nonnull AnalysisSink analysisSink, @Nonnull AnalyzedCode analyzedCode) {
41 | super.finishAnalysis(analysisSink, analyzedCode);
42 | for (String interfaceName : interfacesNotFoundInClassPath) {
43 | logger.warn("Interface [{}] wasn't ever found in the class path. You should remove the configuration entry.", interfaceName);
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/CustomSuperClassAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import de.is24.deadcode4j.AnalysisSink;
5 | import de.is24.deadcode4j.AnalyzedCode;
6 |
7 | import javax.annotation.Nonnull;
8 | import java.util.Set;
9 |
10 | import static com.google.common.collect.Sets.newHashSet;
11 |
12 | /**
13 | * Analyzes class files: marks a class as being in use if it is a direct subclass of one of the specified classes.
14 | *
15 | * @since 1.4
16 | */
17 | public final class CustomSuperClassAnalyzer extends SuperClassAnalyzer {
18 |
19 | @Nonnull
20 | private final Set superClassesNotFoundInClassPath;
21 |
22 | /**
23 | * Creates a new CustomAnnotationsAnalyzer
.
24 | *
25 | * @param customSuperClasses a list of fully qualified class names indicating that the extending class is in use
26 | * @since 1.4
27 | */
28 | public CustomSuperClassAnalyzer(@Nonnull Iterable customSuperClasses) {
29 | super("_custom-superclass_", customSuperClasses);
30 | superClassesNotFoundInClassPath = newHashSet(customSuperClasses);
31 | }
32 |
33 | @Override
34 | public void finishAnalysis(@Nonnull AnalysisContext analysisContext) {
35 | super.finishAnalysis(analysisContext);
36 | superClassesNotFoundInClassPath.removeAll(getSuperClassesFoundInClassPath(analysisContext));
37 | }
38 |
39 | @Override
40 | public void finishAnalysis(@Nonnull AnalysisSink analysisSink, @Nonnull AnalyzedCode analyzedCode) {
41 | super.finishAnalysis(analysisSink, analyzedCode);
42 | for (String interfaceName : superClassesNotFoundInClassPath) {
43 | logger.warn("SuperClass [{}] wasn't ever found in the class path. You should remove the configuration entry.", interfaceName);
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/JeeAnnotationsAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes class files: marks a class as being in use if it is annotated with one of those JEE annotations:
5 | *
6 | * - javax.annotation.ManagedBean
7 | * - javax.faces.component.behavior.FacesBehavior
8 | * - javax.faces.convert.FacesConverter
9 | * - javax.faces.event.ListenerFor
10 | * - javax.faces.event.ListenersFor
11 | * - javax.faces.event.NamedEvent
12 | * - javax.faces.render.FacesBehaviorRenderer
13 | * - javax.faces.render.FacesRenderer
14 | * - javax.faces.validator.FacesValidator
15 | * - javax.faces.view.facelets.FaceletsResourceResolver
16 | * - javax.inject.Named
17 | * - javax.persistence.metamodel.StaticMetamodel
18 | * - javax.xml.bind.annotation.XmlRegistry
19 | * - javax.xml.bind.annotation.XmlSchema
20 | *
21 | *
22 | * @since 1.3
23 | */
24 | public final class JeeAnnotationsAnalyzer extends AnnotationsAnalyzer {
25 |
26 | public JeeAnnotationsAnalyzer() {
27 | super("_JEE-Annotation_",
28 | "javax.annotation.ManagedBean",
29 | "javax.faces.component.behavior.FacesBehavior",
30 | "javax.faces.convert.FacesConverter",
31 | "javax.faces.event.ListenerFor",
32 | "javax.faces.event.ListenersFor",
33 | "javax.faces.event.NamedEvent",
34 | "javax.faces.render.FacesBehaviorRenderer",
35 | "javax.faces.render.FacesRenderer",
36 | "javax.faces.validator.FacesValidator",
37 | "javax.faces.view.facelets.FaceletsResourceResolver",
38 | "javax.inject.Named",
39 | "javax.persistence.metamodel.StaticMetamodel",
40 | "javax.xml.bind.annotation.XmlRegistry",
41 | "javax.xml.bind.annotation.XmlSchema");
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/JerseyWebXmlAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 |
4 | import de.is24.deadcode4j.AnalysisContext;
5 | import de.is24.deadcode4j.analyzer.webxml.BaseWebXmlAnalyzer;
6 | import de.is24.deadcode4j.analyzer.webxml.Param;
7 | import de.is24.deadcode4j.analyzer.webxml.WebXmlHandler;
8 |
9 | import javax.annotation.Nonnull;
10 | import java.util.List;
11 |
12 | /**
13 | * Analyzes web.xml files: looks for servlet parameters that define the JAX-RS applications.
14 | *
15 | * A user can extend the Jersey Application class. In order to use this application the user must set the init-param
16 | * "javax.ws.rs.Application" of a servlet or a filter. (We don't check the servlet or filter class because there are
17 | * several classes of this kind. See Jersey documentation
18 | * 4.7.1.1. Custom
19 | * Application subclass
20 | *
21 | * @since 2.1.0
22 | */
23 | public class JerseyWebXmlAnalyzer extends BaseWebXmlAnalyzer {
24 | @Nonnull
25 | @Override
26 | protected WebXmlHandler createWebXmlHandlerFor(@Nonnull final AnalysisContext analysisContext) {
27 | return new WebXmlHandler() {
28 | @Override
29 | public void filter(String className, List initParams) {
30 | //We don't check the filter class because there are several classes of this kind.
31 | scanParams(initParams);
32 | }
33 |
34 | @Override
35 | public void servlet(String className, List initParams) {
36 | //We don't check the servlet class because there are several classes of this kind.
37 | scanParams(initParams);
38 | }
39 |
40 | private void scanParams(List initParams) {
41 | for (Param initParam: initParams) {
42 | if (initParam.getName().equals("javax.ws.rs.Application")) {
43 | analysisContext.addDependencies("_Jersey_", initParam.getValue());
44 | }
45 | }
46 | }
47 | };
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/JettyXmlAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes Jetty XML configuration files.
5 | * Reports the {@code class} and {@code type} attributes as classes being referenced.
6 | *
7 | * @since 2.0.0
8 | */
9 | public class JettyXmlAnalyzer extends SimpleXmlAnalyzer {
10 |
11 | public JettyXmlAnalyzer() {
12 | super("_Jetty-XML_", ".xml", "Configure");
13 | registerClassAttribute("Arg", "type");
14 | registerClassAttribute("Array", "type");
15 | registerClassAttribute("Call", "class");
16 | registerClassAttribute("Configure", "class");
17 | registerClassAttribute("Get", "class");
18 | registerClassAttribute("Item", "type");
19 | registerClassAttribute("New", "class");
20 | registerClassAttribute("Put", "type");
21 | registerClassAttribute("Set", "class");
22 | registerClassAttribute("Set", "type");
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/LogbackXmlAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | *
Analyzes Logback XML configuration files (only files named logback.xml
) by reporting every
5 | * class
and actionClass
attribute as being live code.
6 | * To understand why this wildcard approach is chosen, have a look at section
7 | * Configuration file syntax and
8 | * Joran of the Logback documentation.
9 | *
10 | * @since 2.2.0
11 | */
12 | public class LogbackXmlAnalyzer extends ExtendedXmlAnalyzer {
13 |
14 | public LogbackXmlAnalyzer() {
15 | super("_Logback-XML_", "logback.xml", "configuration");
16 | anyElement().registerAttributeAsClass("actionClass");
17 | anyElement().registerAttributeAsClass("class");
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/MainClassAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import javassist.CtClass;
5 | import javassist.Modifier;
6 | import javassist.bytecode.AccessFlag;
7 | import javassist.bytecode.MethodInfo;
8 |
9 | import javax.annotation.Nonnull;
10 |
11 | import static com.google.common.collect.Iterables.filter;
12 |
13 | /**
14 | * Analyzes class files: marks a class as being in use if it defines a main method.
15 | *
16 | * @since 2.0.0
17 | */
18 | public class MainClassAnalyzer extends ByteCodeAnalyzer {
19 |
20 | private static boolean isPublicStatic(MethodInfo methodInfo) {
21 | int modifier = AccessFlag.toModifier(methodInfo.getAccessFlags());
22 | return Modifier.isPublic(modifier) && Modifier.isStatic(modifier);
23 | }
24 |
25 | private static boolean matchesSignature(MethodInfo methodInfo) {
26 | return "([Ljava/lang/String;)V".equals(methodInfo.getDescriptor());
27 | }
28 |
29 | @Override
30 | protected void analyzeClass(@Nonnull AnalysisContext analysisContext, @Nonnull CtClass clazz) {
31 | String clazzName = clazz.getName();
32 | analysisContext.addAnalyzedClass(clazzName);
33 |
34 | for (MethodInfo methodInfo : filter(clazz.getClassFile2().getMethods(), MethodInfo.class)) {
35 | if (methodInfo.isMethod()
36 | && isPublicStatic(methodInfo)
37 | && "main".equals(methodInfo.getName())
38 | && matchesSignature(methodInfo)) {
39 | analysisContext.addDependencies("_Main-Class_", clazz.getName());
40 | }
41 | }
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/SpringAnnotationsAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes class files: marks a class as being in use if it is annotated with one of those Spring annotations:
5 | *
6 | * - org.springframework.jmx.export.annotation.ManagedResource
7 | * - org.springframework.stereotype.Component
8 | *
9 | *
10 | * Those Spring annotations are marked with @Component
and thus are recursively considered as well:
11 | *
12 | * - org.springframework.context.annotation.Configuration
13 | * - org.springframework.stereotype.Controller
14 | * - org.springframework.stereotype.Service
15 | * - org.springframework.stereotype.Repository
16 | *
17 | *
18 | * @since 1.3
19 | */
20 | public final class SpringAnnotationsAnalyzer extends AnnotationsAnalyzer {
21 |
22 | public SpringAnnotationsAnalyzer() {
23 | super("_Spring-Annotation_",
24 | "org.springframework.jmx.export.annotation.ManagedResource",
25 | "org.springframework.stereotype.Component");
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/SpringNamespaceHandlerAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import org.apache.commons.io.IOUtils;
5 |
6 | import javax.annotation.Nonnull;
7 | import java.io.File;
8 | import java.io.FileInputStream;
9 | import java.io.IOException;
10 | import java.util.Properties;
11 |
12 | import static com.google.common.collect.Iterables.filter;
13 |
14 | /**
15 | * Analyzes
16 | * spring.handlers
property files and lists the defined namespace handlers as classes being
17 | * referenced.
18 | */
19 | public class SpringNamespaceHandlerAnalyzer extends AnalyzerAdapter {
20 |
21 | @Override
22 | public void doAnalysis(@Nonnull AnalysisContext analysisContext, @Nonnull File file) {
23 | if (file.getAbsolutePath().endsWith("META-INF/spring.handlers")) {
24 | logger.debug("Analyzing property file [{}]...", file);
25 | registerSpringHandlersDefinedIn(analysisContext, file);
26 | }
27 | }
28 |
29 | private void registerSpringHandlersDefinedIn(AnalysisContext analysisContext, File file) {
30 | Properties springNamespaceHandlers = readPropertyFile(file);
31 | analysisContext.addDependencies("_Spring-NamespaceHandler_", filter(springNamespaceHandlers.values(), String.class));
32 | }
33 |
34 | private Properties readPropertyFile(File file) {
35 | Properties properties = new Properties();
36 | FileInputStream in = null;
37 | try {
38 | in = new FileInputStream(file);
39 | properties.load(in);
40 | } catch (IOException e) {
41 | throw new RuntimeException("Failed to read [" + file + "]!", e);
42 | } finally {
43 | IOUtils.closeQuietly(in);
44 | }
45 | return properties;
46 | }
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/SpringWebApplicationInitializerAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes both web.xml
and class files: looks for implementations of
5 | * {@link org.springframework.web.WebApplicationInitializer} if the metadata-complete
attribute of the
6 | * web-app
element is missing or set to "false".
7 | *
8 | * @since 1.5
9 | */
10 | public class SpringWebApplicationInitializerAnalyzer extends ServletContainerInitializerAnalyzer {
11 |
12 | public SpringWebApplicationInitializerAnalyzer() {
13 | super("_Spring-WebApplicationInitializer_", "org.springframework.web.WebApplicationInitializer");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/SpringWebFlowAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes Spring Web Flow XML
5 | * files: lists
6 | *
7 | * - a
var
's class
8 | * - an
attribute
's/input
's/output
's/set
's type
9 | * - the result-type of an
evaluate
10 | *
11 | * as classes being referenced.
12 | *
13 | * @since 1.5
14 | */
15 | public final class SpringWebFlowAnalyzer extends SimpleXmlAnalyzer {
16 |
17 | public SpringWebFlowAnalyzer() {
18 | super("_SpringWebFlow-XML_", ".xml", "flow");
19 | registerClassAttribute("attribute", "type");
20 | registerClassAttribute("evaluate", "result-type");
21 | registerClassAttribute("input", "type");
22 | registerClassAttribute("output", "type");
23 | registerClassAttribute("set", "type");
24 | registerClassAttribute("var", "class");
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/TldAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes *.tld
files: lists the function, listener, tag, tag extra info & validator classes being
5 | * referenced.
6 | *
7 | * @since 1.2.0
8 | */
9 | public final class TldAnalyzer extends SimpleXmlAnalyzer {
10 |
11 | public TldAnalyzer() {
12 | super("_tld_", ".tld", "taglib");
13 | registerClassElement("function-class");
14 | registerClassElement("listener-class");
15 | registerClassElement("tag-class");
16 | registerClassElement("tei-class");
17 | registerClassElement("validator-class");
18 | // this was valid at least for J2EE 1.2, see http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd
19 | registerClassElement("tagclass");
20 | registerClassElement("teiclass");
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/WebXmlAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import de.is24.deadcode4j.analyzer.webxml.BaseWebXmlAnalyzer;
5 | import de.is24.deadcode4j.analyzer.webxml.Param;
6 | import de.is24.deadcode4j.analyzer.webxml.WebXmlHandler;
7 |
8 | import javax.annotation.Nonnull;
9 | import java.util.List;
10 |
11 | /**
12 | * Analyzes web.xml
files: lists the listener, filter & servlet classes being referenced.
13 | *
14 | * @since 1.2.0
15 | */
16 | public final class WebXmlAnalyzer extends BaseWebXmlAnalyzer {
17 |
18 | @Nonnull
19 | @Override
20 | protected WebXmlHandler createWebXmlHandlerFor(@Nonnull final AnalysisContext analysisContext) {
21 | return new WebXmlHandler() {
22 | @Override
23 | public void filter(String className, List initParams) {
24 | addDependency(className);
25 | }
26 |
27 | @Override
28 | public void listener(String className) {
29 | addDependency(className);
30 | }
31 |
32 | @Override
33 | public void servlet(String className, List initParams) {
34 | addDependency(className);
35 | }
36 |
37 | private void addDependency(String className) {
38 | analysisContext.addDependencies("_web.xml_", className);
39 | }
40 | };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/WsddAnalyzer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer;
2 |
3 | /**
4 | * Analyzes .wsdd
5 | * files: lists the defined Axis Service classes being referenced.
6 | *
7 | * @since 1.5
8 | */
9 | public final class WsddAnalyzer extends SimpleXmlAnalyzer {
10 |
11 | public WsddAnalyzer() {
12 | super("_Axis-WSSD_", ".wsdd", "deployment");
13 | registerClassAttribute("parameter", "value").withAttributeValue("name", "className");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/javassist/ClassPathFilter.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer.javassist;
2 |
3 | import de.is24.deadcode4j.AnalysisContext;
4 | import de.is24.guava.NonNullFunction;
5 | import javassist.ClassPool;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import javax.annotation.Nonnull;
10 | import java.util.Set;
11 |
12 | import static com.google.common.collect.Sets.newHashSet;
13 | import static de.is24.deadcode4j.analyzer.javassist.ClassPoolAccessor.classPoolAccessorFor;
14 |
15 | /**
16 | * This function returns a set containing only those classes that exist within the class path of the specified context.
17 | * It is intended to be used in conjunction with
18 | * {@link de.is24.deadcode4j.AnalysisContext#getOrCreateCacheEntry(Object, de.is24.guava.NonNullFunction)}.
19 | *
20 | * @since 2.0.0
21 | */
22 | public class ClassPathFilter implements NonNullFunction> {
23 | @Nonnull
24 | private final Logger logger = LoggerFactory.getLogger(getClass());
25 | @Nonnull
26 | private final Set classes;
27 |
28 | /**
29 | * Creates a new ClassPathFilter
for the given class names.
30 | *
31 | * @since 2.0.0
32 | */
33 | public ClassPathFilter(@Nonnull Set classes) {
34 | this.classes = classes;
35 | }
36 |
37 | @Nonnull
38 | @Override
39 | public Set apply(@Nonnull AnalysisContext input) {
40 | ClassPool classPool = classPoolAccessorFor(input).getClassPool();
41 | Set knownClasses = newHashSet();
42 | for (String className : this.classes) {
43 | if (classPool.find(className) != null) {
44 | knownClasses.add(className);
45 | }
46 | }
47 | logger.debug("Found those classes in the class path: {}", knownClasses);
48 | return knownClasses;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/webxml/Param.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer.webxml;
2 |
3 | /**
4 | * Representation of a {@code context-param} or {@code init-param} node.
5 | * {@code Param} is a value-based class.
6 | *
7 | * @since 2.1.0
8 | */
9 | public class Param {
10 | private final String name;
11 | private final String value;
12 |
13 | /**
14 | * Creates a new {@code Param} object.
15 | * @param name the text of the {@code param-name} node.
16 | * @param value the text of the {@code param-value} node.
17 | */
18 | public Param(String name, String value) {
19 | this.name = name;
20 | this.value = value;
21 | }
22 |
23 | /**
24 | * Returns the text of the {@code param-name} node.
25 | */
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | /**
31 | * Returns the text of the {@code param-value} node.
32 | */
33 | public String getValue() {
34 | return value;
35 | }
36 |
37 | @Override
38 | public boolean equals(Object o) {
39 | if (this == o) {
40 | return true;
41 | }
42 | if (!getClass().isInstance(o)) {
43 | return false;
44 | }
45 |
46 | Param param = (Param) o;
47 |
48 | if (name != null ? !name.equals(param.name) : param.name != null) {
49 | return false;
50 | }
51 | return !(value != null ? !value.equals(param.value) : param.value != null);
52 |
53 | }
54 |
55 | @Override
56 | public int hashCode() {
57 | int result = name != null ? name.hashCode() : 0;
58 | result = 31 * result + (value != null ? value.hashCode() : 0);
59 | return result;
60 | }
61 |
62 | @Override
63 | public String toString() {
64 | return "Param{" +
65 | "name='" + name + '\'' +
66 | ", value='" + value + '\'' +
67 | '}';
68 | }
69 | }
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/analyzer/webxml/WebXmlHandler.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.analyzer.webxml;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Base class for web.xml event handlers. {@code WebXmlHandler}s are used by
7 | * {@link BaseWebXmlAnalyzer} that translates general XML events into web.xml
8 | * events.
9 | *
10 | * @since 2.1.0
11 | */
12 | public abstract class WebXmlHandler {
13 | /**
14 | * Receive notification about a {@code context-param} node.
15 | *
16 | * @param param the param.
17 | */
18 | public void contextParam(Param param) {
19 | }
20 |
21 | /**
22 | * Receive notification about a {@code filter} node.
23 | *
24 | * @param className the text of the {@code filter-class} node.
25 | * @param initParams the filters init params.
26 | */
27 | public void filter(String className, List initParams) {
28 | }
29 |
30 | /**
31 | * Receive notification about a {@code listener} node.
32 | *
33 | * @param className the text of the {@code listener-class} node.
34 | */
35 | public void listener(String className) {
36 | }
37 |
38 | /**
39 | * Receive notification about a {@code servlet} node.
40 | *
41 | * @param className the text of the {@code servlet-class} node.
42 | * @param initParams the servlets init params.
43 | */
44 | public void servlet(String className, List initParams) {
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/plugin/CustomXml.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.plugin;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 |
5 | import java.util.List;
6 |
7 | import static com.google.common.collect.Lists.newArrayList;
8 |
9 | /**
10 | * CustomXml
is used to configure a {@link de.is24.deadcode4j.analyzer.CustomXmlAnalyzer}.
11 | *
12 | * @since 1.3
13 | */
14 | public class CustomXml {
15 |
16 | @java.lang.SuppressWarnings("UnusedDeclaration")
17 | @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Set by Plexus when configuring the plugin")
18 | private String endOfFileName;
19 | @java.lang.SuppressWarnings("UnusedDeclaration")
20 | @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Set by Plexus when configuring the plugin")
21 | private String rootElement;
22 | private final List xPaths = newArrayList();
23 |
24 | public String getEndOfFileName() {
25 | return endOfFileName;
26 | }
27 |
28 | public String getRootElement() {
29 | return rootElement;
30 | }
31 |
32 | public List getXPaths() {
33 | return xPaths;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/plugin/FindDeadCodeMojo.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.plugin;
2 |
3 | import org.apache.maven.plugins.annotations.Execute;
4 | import org.apache.maven.plugins.annotations.Mojo;
5 |
6 | import static org.apache.maven.plugins.annotations.LifecyclePhase.PACKAGE;
7 | import static org.apache.maven.plugins.annotations.ResolutionScope.COMPILE;
8 |
9 | /**
10 | * Finds dead (i.e. unused) code. Causes the
11 | * package phase to be
12 | * executed.
13 | *
14 | * @see FindDeadCodeOnlyMojo
15 | * @since 1.0.0
16 | */
17 | @Mojo(name = "find",
18 | aggregator = true,
19 | requiresProject = true,
20 | requiresDependencyCollection = COMPILE,
21 | threadSafe = true)
22 | @Execute(phase = PACKAGE)
23 | public class FindDeadCodeMojo extends FindDeadCodeOnlyMojo {
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/plugin/SubDirectoryFilter.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.plugin;
2 |
3 | import javax.annotation.Nonnull;
4 | import java.io.File;
5 | import java.io.FileFilter;
6 |
7 | /**
8 | * A SubDirectoryFilter
only accepts a specific subdirectory of a directory.
9 | *
10 | * @since 1.2.0
11 | */
12 | public class SubDirectoryFilter implements FileFilter {
13 |
14 | private final File directory;
15 | private final String subDirectoryName;
16 |
17 | public SubDirectoryFilter(@Nonnull File directory, @Nonnull String subDirectoryName) {
18 | this.directory = directory;
19 | this.subDirectoryName = subDirectoryName;
20 | }
21 |
22 | @Override
23 | public boolean accept(File file) {
24 | return file.isDirectory() && directory.equals(file.getParentFile()) && subDirectoryName.equals(file.getName());
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/plugin/packaginghandler/DefaultPackagingHandler.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.plugin.packaginghandler;
2 |
3 | import de.is24.deadcode4j.Repository;
4 | import org.apache.maven.plugin.MojoExecutionException;
5 | import org.apache.maven.project.MavenProject;
6 |
7 | import javax.annotation.Nonnull;
8 | import javax.annotation.Nullable;
9 | import java.io.File;
10 |
11 | import static de.is24.deadcode4j.Utils.getKeyFor;
12 |
13 | /**
14 | * The DefaultPackagingHandler
returns the default output directory if it exists.
15 | *
16 | * @since 1.2.0
17 | */
18 | public class DefaultPackagingHandler extends PackagingHandler {
19 |
20 | @Nullable
21 | @Override
22 | public Repository getOutputRepositoryFor(@Nonnull MavenProject project) throws MojoExecutionException {
23 | logger.debug("Project {} has {} packaging, looking for output directory...", getKeyFor(project), project.getPackaging());
24 | File outputDirectory = new File(project.getBuild().getOutputDirectory());
25 | if (!outputDirectory.exists()) {
26 | logger.warn("The output directory of " + getKeyFor(project) +
27 | " does not exist - assuming the project simply has nothing to provide!");
28 | return null;
29 | }
30 | logger.debug(" Found output directory [{}].", outputDirectory);
31 | return new Repository(outputDirectory);
32 | }
33 |
34 | @Nonnull
35 | @Override
36 | public Iterable getAdditionalRepositoriesFor(@Nonnull MavenProject project) throws MojoExecutionException {
37 | return getJavaFilesOfCompileSourceRootsAsRepositories(project);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/deadcode4j/plugin/packaginghandler/PomPackagingHandler.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j.plugin.packaginghandler;
2 |
3 | import de.is24.deadcode4j.Repository;
4 | import org.apache.maven.plugin.MojoExecutionException;
5 | import org.apache.maven.project.MavenProject;
6 |
7 | import javax.annotation.Nonnull;
8 | import javax.annotation.Nullable;
9 |
10 | import static de.is24.deadcode4j.Utils.getKeyFor;
11 |
12 | /**
13 | * The PomPackagingHandler
returns no repository, as there's nothing to analyze.
14 | *
15 | * @since 1.2.0
16 | */
17 | public class PomPackagingHandler extends PackagingHandler {
18 |
19 | @Nullable
20 | @Override
21 | public Repository getOutputRepositoryFor(@Nonnull MavenProject project) throws MojoExecutionException {
22 | logger.debug("Project {} has pom packaging, so it is skipped.", getKeyFor(project));
23 | return null;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/guava/NonNullFunction.java:
--------------------------------------------------------------------------------
1 | package de.is24.guava;
2 |
3 | import javax.annotation.Nonnull;
4 |
5 | /**
6 | * A NonNullFunction
basically is a {@link com.google.common.base.Function} that
7 | * neither accepts null
nor is it allowed to return null
.
8 | *
9 | * @since 2.0.0
10 | */
11 | public interface NonNullFunction {
12 |
13 | /**
14 | * Returns the result of applying this function to the given input.
15 | *
16 | * @since 2.0.0
17 | */
18 | @Nonnull
19 | T apply(@Nonnull F input);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/guava/NonNullFunctions.java:
--------------------------------------------------------------------------------
1 | package de.is24.guava;
2 |
3 | import com.google.common.base.Function;
4 | import com.google.common.base.Optional;
5 | import de.is24.deadcode4j.Utils;
6 |
7 | import javax.annotation.Nonnull;
8 | import javax.annotation.Nullable;
9 |
10 | /**
11 | * Provides convenience methods for {@link de.is24.guava.NonNullFunction}.
12 | *
13 | * @since 2.0.0
14 | */
15 | public final class NonNullFunctions {
16 |
17 | private NonNullFunctions() {}
18 |
19 | /**
20 | * Returns a NonNullFunction
that will call the specified functions one by one until a return value is
21 | * present or the end of the call chain is reached.
22 | *
23 | * @since 2.0.0
24 | */
25 | @Nonnull
26 | public static NonNullFunction> or(@Nonnull final NonNullFunction>... functions) {
27 | return new NonNullFunction>() {
28 | @Nonnull
29 | @Override
30 | public Optional apply(@Nonnull F input) {
31 | for (int i = 0; ; ) {
32 | Optional result = functions[i++].apply(input);
33 | if (result.isPresent() || i == functions.length) {
34 | return result;
35 | }
36 | }
37 | }
38 | };
39 | }
40 |
41 | /**
42 | * Transforms a NonNullFunction
into a Function
.
43 | * If a Function
's input is null
, a NullPointerException
is thrown.
44 | *
45 | * @since 2.0.0
46 | */
47 | @Nonnull
48 | public static Function toFunction(@Nonnull final NonNullFunction nonNullFunction) {
49 | return new Function() {
50 | @Nullable
51 | @Override
52 | @SuppressWarnings("ConstantConditions")
53 | public T apply(@Nullable F input) {
54 | return nonNullFunction.apply(Utils.checkNotNull(input));
55 | }
56 | };
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/javaparser/ImportDeclarations.java:
--------------------------------------------------------------------------------
1 | package de.is24.javaparser;
2 |
3 | import com.google.common.base.Predicate;
4 | import com.github.javaparser.ast.ImportDeclaration;
5 |
6 | import javax.annotation.Nonnull;
7 | import javax.annotation.Nullable;
8 |
9 | import static de.is24.deadcode4j.Utils.checkNotNull;
10 |
11 | /**
12 | * Provides convenience methods for dealing with {@link ImportDeclaration}s.
13 | *
14 | * @since 2.0.0
15 | */
16 | public final class ImportDeclarations {
17 |
18 | private ImportDeclarations() {}
19 |
20 | /**
21 | * Returns a Predicate
that evaluates to true
if the ImportDeclaration
being
22 | * tested is an asterisk import.
23 | *
24 | * @since 2.0.0
25 | */
26 | @Nonnull
27 | public static Predicate super ImportDeclaration> isAsterisk() {
28 | return new Predicate() {
29 | @Override
30 | @SuppressWarnings("ConstantConditions")
31 | public boolean apply(@Nullable ImportDeclaration input) {
32 | return checkNotNull(input).isAsterisk();
33 | }
34 | };
35 | }
36 |
37 | /**
38 | * Returns a Predicate
that evaluates to true
if the ImportDeclaration
being
39 | * tested is a static import.
40 | *
41 | * @since 2.0.0
42 | */
43 | @Nonnull
44 | public static Predicate super ImportDeclaration> isStatic() {
45 | return new Predicate() {
46 | @Override
47 | @SuppressWarnings("ConstantConditions")
48 | public boolean apply(@Nullable ImportDeclaration input) {
49 | return checkNotNull(input).isStatic();
50 | }
51 | };
52 | }
53 |
54 | /**
55 | * Returns a Predicate
that evaluates to true
if the last qualifier of the
56 | * ImportDeclaration
being tested matches the given String.
57 | *
58 | * @since 2.0.0
59 | */
60 | @Nonnull
61 | public static Predicate super ImportDeclaration> refersTo(@Nonnull final String lastQualifier) {
62 | return new Predicate() {
63 | @Override
64 | @SuppressWarnings("ConstantConditions")
65 | public boolean apply(@Nullable ImportDeclaration input) {
66 | return lastQualifier.equals(checkNotNull(input).getName().getName());
67 | }
68 | };
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/maven/slf4j/AbstractSlf4jMojo.java:
--------------------------------------------------------------------------------
1 | package de.is24.maven.slf4j;
2 |
3 | import org.apache.maven.plugin.AbstractMojo;
4 | import org.apache.maven.plugin.MojoExecutionException;
5 | import org.apache.maven.plugin.MojoFailureException;
6 | import org.slf4j.impl.StaticLoggerBinder;
7 |
8 | /**
9 | * A subclass of AbstractMojo
that makes sure the {@link MavenPluginLoggerFactory} is set up and torn down.
10 | *
11 | * @author Sebastian Kirsch
12 | * @since 1.5
13 | */
14 | public abstract class AbstractSlf4jMojo extends AbstractMojo {
15 | @Override
16 | public final void execute() throws MojoExecutionException, MojoFailureException {
17 | StaticLoggerBinder staticLoggerBinder = StaticLoggerBinder.getSingleton();
18 | staticLoggerBinder.setLog(getLog());
19 | try {
20 | doExecute();
21 | } finally {
22 | staticLoggerBinder.revokeLog();
23 | }
24 | }
25 |
26 | /**
27 | * Subclasses need to implement this method instead of {@link org.apache.maven.plugin.Mojo#execute()}.
28 | *
29 | * @since 1.5
30 | */
31 | protected abstract void doExecute() throws MojoExecutionException, MojoFailureException;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/de/is24/maven/slf4j/MavenPluginLoggerFactory.java:
--------------------------------------------------------------------------------
1 | package de.is24.maven.slf4j;
2 |
3 | import org.apache.maven.plugin.logging.Log;
4 | import org.slf4j.ILoggerFactory;
5 | import org.slf4j.Logger;
6 |
7 | import javax.annotation.Nonnull;
8 | import javax.annotation.Nullable;
9 |
10 | /**
11 | * An ILoggerFactory
creating instances of {@link LoggerForMavenLog}.
12 | *
13 | * @author Sebastian Kirsch
14 | * @since 1.5
15 | */
16 | public class MavenPluginLoggerFactory implements ILoggerFactory {
17 | private final Log log;
18 |
19 | public MavenPluginLoggerFactory(@Nonnull Log log) {
20 | this.log = log;
21 | }
22 |
23 | @Override
24 | public Logger getLogger(@Nullable String name) {
25 | return new LoggerForMavenLog(log, name);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/A.java:
--------------------------------------------------------------------------------
1 | public class A {
2 | private B b;
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/AnnotatedClass.java:
--------------------------------------------------------------------------------
1 | import de.is24.deadcode4j.junit.Annotation;
2 |
3 | @Annotation
4 | public class AnnotatedClass {
5 | }
6 |
--------------------------------------------------------------------------------
/src/test/java/B.java:
--------------------------------------------------------------------------------
1 | public class B {
2 | private A a;
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/ClassAnnotatedWithAnnotatedAnnotation.java:
--------------------------------------------------------------------------------
1 | import de.is24.deadcode4j.junit.AnnotatedAnnotation;
2 |
3 | @AnnotatedAnnotation
4 | @SuppressWarnings("UnusedDeclaration")
5 | public class ClassAnnotatedWithAnnotatedAnnotation {
6 | }
7 |
--------------------------------------------------------------------------------
/src/test/java/ClassImplementingCloneable.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("UnusedDeclaration")
2 | public class ClassImplementingCloneable implements Cloneable {
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/ClassImplementingExternalizable.java:
--------------------------------------------------------------------------------
1 | import java.io.Externalizable;
2 | import java.io.ObjectInput;
3 | import java.io.ObjectOutput;
4 |
5 | @SuppressWarnings("UnusedDeclaration")
6 | public class ClassImplementingExternalizable implements Externalizable {
7 | @Override
8 | public void writeExternal(ObjectOutput out) {
9 | }
10 |
11 | @Override
12 | public void readExternal(ObjectInput in) {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/ClassWithInnerClass.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("unused")
2 | public class ClassWithInnerClass {
3 | public static class InnerClass { }
4 | }
--------------------------------------------------------------------------------
/src/test/java/ClassWithTypeArgument.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | @SuppressWarnings("UnusedDeclaration")
3 | public class ClassWithTypeArgument {
4 | public ClassWithTypeArgument() { new ArrayList(); }
5 | }
6 |
--------------------------------------------------------------------------------
/src/test/java/CustomNamespaceHandler.java:
--------------------------------------------------------------------------------
1 | public class CustomNamespaceHandler {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/DeadServlet.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.http.HttpServlet;
2 | import java.io.Serializable;
3 |
4 | @Deprecated
5 | public class DeadServlet extends HttpServlet implements Serializable {
6 | }
7 |
--------------------------------------------------------------------------------
/src/test/java/DependingClass.java:
--------------------------------------------------------------------------------
1 | public class DependingClass {
2 | private IndependentClass b;
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/IndependentClass.java:
--------------------------------------------------------------------------------
1 | public class IndependentClass {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/MainClass.java:
--------------------------------------------------------------------------------
1 | public class MainClass {
2 | public static void main(String[] args) { }
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/SingleClass.java:
--------------------------------------------------------------------------------
1 | public class SingleClass {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/SomeServletInitializer.java:
--------------------------------------------------------------------------------
1 | import de.is24.deadcode4j.junit.SomeInterface;
2 | @SuppressWarnings("UnusedDeclaration")
3 | public class SomeServletInitializer implements SomeInterface { }
4 |
--------------------------------------------------------------------------------
/src/test/java/SpringXmlBean.java:
--------------------------------------------------------------------------------
1 | public class SpringXmlBean {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/SubClassOfAnnotatedClass.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("UnusedDeclaration")
2 | public class SubClassOfAnnotatedClass extends AnnotatedClass {
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/SubClassOfClassImplementingExternalizable.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("UnusedDeclaration")
2 | public class SubClassOfClassImplementingExternalizable extends ClassImplementingExternalizable {
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/SubClassOfSubClassThatShouldBeLive.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("UnusedDeclaration")
2 | public class SubClassOfSubClassThatShouldBeLive extends SubClassThatShouldBeLive {
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/SubClassThatShouldBeLive.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("UnusedDeclaration")
2 | public class SubClassThatShouldBeLive extends Thread {
3 | }
4 |
--------------------------------------------------------------------------------
/src/test/java/TagClass.java:
--------------------------------------------------------------------------------
1 | public class TagClass {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/TagExtraInfo.java:
--------------------------------------------------------------------------------
1 | public class TagExtraInfo {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/TagLibraryValidator.java:
--------------------------------------------------------------------------------
1 | public class TagLibraryValidator {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/TypeParameterClass.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("UnusedDeclaration")
2 | public class TypeParameterClass { }
3 |
--------------------------------------------------------------------------------
/src/test/java/WebAppFilter.java:
--------------------------------------------------------------------------------
1 | public class WebAppFilter {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/WebAppListener.java:
--------------------------------------------------------------------------------
1 | public class WebAppListener {
2 | }
3 |
--------------------------------------------------------------------------------
/src/test/java/WebAppServlet.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.http.HttpServlet;
2 |
3 | public class WebAppServlet extends HttpServlet {
4 | }
5 |
--------------------------------------------------------------------------------
/src/test/java/de/is24/deadcode4j/A_DeadCodeComputer.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import java.util.Collection;
7 | import java.util.EnumSet;
8 | import java.util.Map;
9 | import java.util.Set;
10 |
11 | import static com.google.common.collect.Maps.newHashMap;
12 | import static com.google.common.collect.Sets.newHashSet;
13 | import static org.hamcrest.MatcherAssert.assertThat;
14 | import static org.hamcrest.Matchers.contains;
15 | import static org.hamcrest.Matchers.hasSize;
16 |
17 | public class A_DeadCodeComputer {
18 |
19 | private DeadCodeComputer objectUnderTest;
20 | private Map> codeDependencies = newHashMap();
21 |
22 | @Before
23 | public void setUpObjectUnderTest() {
24 | this.objectUnderTest = new DeadCodeComputer();
25 | codeDependencies.clear();
26 | }
27 |
28 | @Test
29 | public void recognizesASingleClassAsDeadCode() {
30 | setUpDependency("SingleClass");
31 |
32 | Collection deadClasses = computeDeadClasses();
33 |
34 | assertThat("Should recognize one class as dead", deadClasses, hasSize(1));
35 | assertThat(deadClasses, contains("SingleClass"));
36 | }
37 |
38 | @Test
39 | public void recognizesTwoInterdependentClassesAsLiveCode() {
40 | setUpDependency("A", "B");
41 | setUpDependency("B", "A");
42 |
43 | Collection deadClasses = computeDeadClasses();
44 |
45 | assertThat("Should find NO dead code", deadClasses, hasSize(0));
46 | }
47 |
48 | @Test
49 | public void recognizesDependencyChainAsPartlyDeadCode() {
50 | setUpDependency("DependingClass", "IndependentClass");
51 | setUpDependency("IndependentClass");
52 |
53 | Collection deadClasses = computeDeadClasses();
54 |
55 | assertThat("Should recognize one class as dead", deadClasses, contains("DependingClass"));
56 | }
57 |
58 | private void setUpDependency(String depender, String... dependees) {
59 | codeDependencies.put(depender, newHashSet(dependees));
60 | }
61 |
62 | private Collection computeDeadClasses() {
63 | AnalyzedCode analyzedCode = new AnalyzedCode(
64 | EnumSet.noneOf(AnalysisStage.class), codeDependencies.keySet(), codeDependencies);
65 | DeadCode deadCode = objectUnderTest.computeDeadCode(analyzedCode);
66 | return deadCode.getDeadClasses();
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/test/java/de/is24/deadcode4j/A_Module.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 |
9 | import static de.is24.deadcode4j.ModuleBuilder.givenModule;
10 | import static java.util.Arrays.asList;
11 | import static org.hamcrest.MatcherAssert.assertThat;
12 | import static org.hamcrest.Matchers.contains;
13 |
14 | public final class A_Module {
15 |
16 | @Test
17 | public void sortsModulesByDependency() {
18 | Module c = givenModule("C");
19 | Module b = givenModule("B", c);
20 | Module a = givenModule("A", b);
21 |
22 | Iterable modules = Module.sort(asList(b, a, c));
23 |
24 | assertThat(modules, contains(c, b, a));
25 | }
26 |
27 | @Test
28 | public void sortsUnrelatedModulesAlphabetically() {
29 | Module a = givenModule("A");
30 | Module b = givenModule("B");
31 | Module c = givenModule("C");
32 |
33 | Iterable modules = Module.sort(asList(c, b, a));
34 |
35 | assertThat(modules, contains(a, b, c));
36 | }
37 |
38 | @Test
39 | public void sortsReallyComplexDependencyGraphCorrectly() {
40 | Module z = givenModule("Z");
41 | Module y = givenModule("Y", z);
42 | Module c = givenModule("C", z);
43 | Module b = givenModule("B", c, y);
44 | Module a = givenModule("A", b);
45 | Module x = givenModule("X", c);
46 |
47 | List unsortedModules = asList(a, b, c, x, y, z);
48 | Collections.shuffle(unsortedModules);
49 | Iterable modules = Module.sort(unsortedModules);
50 |
51 | assertThat(modules, contains(z, c, y, b, x, a));
52 | }
53 |
54 | @Test(expected = RuntimeException.class)
55 | public void throwsExceptionIfSortingFails() {
56 | ArrayList dependencies = new ArrayList();
57 | Module a = givenModule("A", null, dependencies);
58 | Module b = givenModule("B", a);
59 | dependencies.add(Resource.of(b));
60 |
61 | Module.sort(asList(a, b));
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/src/test/java/de/is24/deadcode4j/A_Repository.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import de.is24.deadcode4j.junit.TempFileRule;
4 | import org.junit.Rule;
5 | import org.junit.Test;
6 |
7 | import java.io.IOException;
8 |
9 | @SuppressWarnings("ConstantConditions")
10 | public class A_Repository {
11 |
12 | @Rule
13 | public final TempFileRule tempFileRule = new TempFileRule();
14 |
15 | @Test(expected = NullPointerException.class)
16 | public void throwsAnExceptionIfTheRepositoryIsNull() throws IOException {
17 | new Repository(null);
18 | }
19 |
20 | @Test(expected = IllegalArgumentException.class)
21 | public void throwsAnExceptionIfTheRepositoryIsNoDirectory() throws IOException {
22 | new Repository(tempFileRule.getTempFile());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/de/is24/deadcode4j/AnalysisContextBuilder.java:
--------------------------------------------------------------------------------
1 | package de.is24.deadcode4j;
2 |
3 | import java.util.Collections;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 |
7 | import static com.google.common.collect.Maps.newHashMap;
8 |
9 | public final class AnalysisContextBuilder {
10 |
11 | private AnalysisContextBuilder() { }
12 |
13 | public static AnalysisContext givenAnalysisContext(Module module, Map