├── .allstar └── binary_artifacts.yaml ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ └── maven-wrapper.properties ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DECLARING_DEPENDENCIES.md ├── LICENSE ├── README.md ├── RELEASING.md ├── boms ├── cloud-lts-bom │ └── pom.xml ├── cloud-oss-bom │ └── pom.xml ├── convergence-check │ └── pom.xml ├── integration-tests │ ├── pom.xml │ └── src │ │ └── test │ │ └── java │ │ └── com │ │ └── google │ │ └── cloud │ │ └── BomContentTest.java ├── pom.xml └── upper-bounds-check │ └── pom.xml ├── dashboard ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── cloud │ │ │ └── tools │ │ │ └── opensource │ │ │ └── dashboard │ │ │ ├── ArtifactCache.java │ │ │ ├── ArtifactInfo.java │ │ │ ├── ArtifactResults.java │ │ │ ├── DashboardArguments.java │ │ │ ├── DashboardMain.java │ │ │ └── PieChart.java │ └── resources │ │ ├── css │ │ └── dashboard.css │ │ ├── js │ │ └── dashboard.js │ │ ├── poms │ │ └── demo.xml │ │ └── templates │ │ ├── artifact_details.ftl │ │ ├── component.ftl │ │ ├── dependency_trees.ftl │ │ ├── index.ftl │ │ ├── macros.ftl │ │ ├── unstable_artifacts.ftl │ │ └── version_index.ftl │ └── test │ └── java │ └── com │ └── google │ └── cloud │ └── tools │ └── opensource │ └── dashboard │ ├── ArtifactResultsTest.java │ ├── DashboardArgumentsTest.java │ ├── DashboardTest.java │ ├── DashboardUnavailableArtifactTest.java │ ├── FreemarkerTest.java │ └── PieChartTest.java ├── dependencies ├── README.md ├── kokoro │ └── release_build.sh ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── cloud │ │ │ └── tools │ │ │ └── opensource │ │ │ ├── classpath │ │ │ ├── AbstractMethodProblem.java │ │ │ ├── AccessModifier.java │ │ │ ├── AnnotatedClassPath.java │ │ │ ├── ClassDumper.java │ │ │ ├── ClassFile.java │ │ │ ├── ClassMatcher.java │ │ │ ├── ClassNotFoundProblem.java │ │ │ ├── ClassPathBuilder.java │ │ │ ├── ClassPathEntry.java │ │ │ ├── ClassPathResult.java │ │ │ ├── ClassReferenceGraph.java │ │ │ ├── ClassSymbol.java │ │ │ ├── DependencyConflict.java │ │ │ ├── DependencyMediation.java │ │ │ ├── ExcludedDependency.java │ │ │ ├── ExcludedErrors.java │ │ │ ├── ExclusionFileHandler.java │ │ │ ├── ExclusionFiles.java │ │ │ ├── FieldMatcher.java │ │ │ ├── FieldSymbol.java │ │ │ ├── FixedSizeClassPathRepository.java │ │ │ ├── GradleDependencyMediation.java │ │ │ ├── InaccessibleClassProblem.java │ │ │ ├── InaccessibleMemberProblem.java │ │ │ ├── IncompatibleClassChangeProblem.java │ │ │ ├── InterfaceSymbol.java │ │ │ ├── LinkageCheckClassPath.java │ │ │ ├── LinkageCheckResultException.java │ │ │ ├── LinkageChecker.java │ │ │ ├── LinkageCheckerArguments.java │ │ │ ├── LinkageCheckerMain.java │ │ │ ├── LinkageErrorMatcher.java │ │ │ ├── LinkageProblem.java │ │ │ ├── LinkageProblemCause.java │ │ │ ├── LinkageProblemCauseAnnotator.java │ │ │ ├── LinkageProblemMatcher.java │ │ │ ├── LinkageProblemSourceMatcher.java │ │ │ ├── LinkageProblemTargetMatcher.java │ │ │ ├── MavenDependencyMediation.java │ │ │ ├── MethodMatcher.java │ │ │ ├── MethodSymbol.java │ │ │ ├── MissingDependency.java │ │ │ ├── PackageMatcher.java │ │ │ ├── ReturnTypeChangedProblem.java │ │ │ ├── SourceMatcher.java │ │ │ ├── SuperClassSymbol.java │ │ │ ├── Symbol.java │ │ │ ├── SymbolNotFoundProblem.java │ │ │ ├── SymbolReferences.java │ │ │ ├── TargetMatcher.java │ │ │ └── UnknownCause.java │ │ │ └── dependencies │ │ │ ├── ArtifactProblem.java │ │ │ ├── Artifacts.java │ │ │ ├── BanOptionalDependencySelector.java │ │ │ ├── Bom.java │ │ │ ├── CycleBreakerGraphTransformer.java │ │ │ ├── DependencyGraph.java │ │ │ ├── DependencyGraphBuilder.java │ │ │ ├── DependencyLister.java │ │ │ ├── DependencyPath.java │ │ │ ├── DependencyTreeFormatter.java │ │ │ ├── DependencyTreePrinter.java │ │ │ ├── DirectProvidedDependencySelector.java │ │ │ ├── DirectReport.java │ │ │ ├── FilteringZipDependencySelector.java │ │ │ ├── InvalidClassFileProblem.java │ │ │ ├── ManagedDependencyLister.java │ │ │ ├── MavenRepositoryException.java │ │ │ ├── NonTestDependencySelector.java │ │ │ ├── OsProperties.java │ │ │ ├── PathToNode.java │ │ │ ├── RepositoryUtility.java │ │ │ ├── UniquePathRecordingDependencyVisitor.java │ │ │ ├── UnresolvableArtifactProblem.java │ │ │ ├── Update.java │ │ │ ├── UpdateReport.java │ │ │ └── VersionComparator.java │ └── resources │ │ ├── linkage-checker-exclusion-default.xml │ │ └── linkage-checker-exclusion.rng │ └── test │ ├── java │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── opensource │ │ ├── classpath │ │ ├── ClassDumperTest.java │ │ ├── ClassFileTest.java │ │ ├── ClassPathBuilderTest.java │ │ ├── ClassPathEntryTest.java │ │ ├── ClassPathResultTest.java │ │ ├── ClassReferenceGraphTest.java │ │ ├── ClassSymbolTest.java │ │ ├── DependencyConflictTest.java │ │ ├── ExcludedDependencyTest.java │ │ ├── ExcludedErrorsTest.java │ │ ├── ExclusionFilesIntegrationTest.java │ │ ├── ExclusionFilesTest.java │ │ ├── FieldSymbolTest.java │ │ ├── FixedSizeClassPathRepositoryTest.java │ │ ├── GradleDependencyMediationTest.java │ │ ├── InaccessibleClassProblemTest.java │ │ ├── LinkageCheckResultExceptionTest.java │ │ ├── LinkageCheckerArgumentsTest.java │ │ ├── LinkageCheckerMainIntegrationTest.java │ │ ├── LinkageCheckerTest.java │ │ ├── LinkageProblemCauseAnnotatorTest.java │ │ ├── LinkageProblemCauseTest.java │ │ ├── LinkageProblemTest.java │ │ ├── MavenDependencyMediationTest.java │ │ ├── MethodSymbolTest.java │ │ ├── MissingDependencyTest.java │ │ ├── SuperClassSymbolTest.java │ │ ├── SymbolReferencesTest.java │ │ └── TestHelper.java │ │ └── dependencies │ │ ├── ArtifactProblemTest.java │ │ ├── ArtifactsTest.java │ │ ├── BomTest.java │ │ ├── CycleBreakerGraphTransformerTest.java │ │ ├── DependencyGraphBuilderIntegrationTest.java │ │ ├── DependencyGraphBuilderTest.java │ │ ├── DependencyGraphIntegrationTest.java │ │ ├── DependencyGraphTest.java │ │ ├── DependencyPathTest.java │ │ ├── DependencyTreeFormatterTest.java │ │ ├── FilteringZipDependencySelectorTest.java │ │ ├── InvalidClassFileProblemTest.java │ │ ├── LevelOrderQueueItemTest.java │ │ ├── RepositoryUtilityTest.java │ │ ├── UniquePathRecordingDependencyVisitorTest.java │ │ ├── UnresolvableArtifactProblemTest.java │ │ └── VersionComparatorTest.java │ └── resources │ ├── bom-with-classifier-artifacts.pom │ ├── exclusion-sample-rules │ ├── duplicate-source-element.xml │ ├── expected-exclusion-output-file.xml │ ├── reason.xml │ ├── source-and-target.xml │ ├── source-class.xml │ ├── source-method.xml │ ├── source-package.xml │ ├── target-field.xml │ ├── target-method.xml │ ├── target-package.xml │ └── target-with-namespace.xml │ ├── libraries-bom-2.7.0.pom │ └── testdata │ ├── LICENSE_THIRDPARTY_APACHE2.txt │ ├── LICENSE_THIRDPARTY_BSD.txt │ ├── README.md │ ├── api-common-1.7.0.jar │ ├── conscrypt-openjdk-uber-1.4.2.jar │ ├── dummy-boot-inf-prefix.jar │ ├── gax-1.32.0.jar │ ├── gax-1.48.1.jar │ ├── gax-grpc-1.38.0.jar │ ├── google-cloud-core-1.48.0.jar │ ├── google-cloud-core-grpc-1.48.0.jar │ ├── google-cloud-firestore-0.65.0-beta.jar │ ├── google-cloud-firestore-0.66.0-beta.jar │ ├── grpc-google-cloud-firestore-v1beta1-0.28.0.jar │ ├── grpc-google-cloud-firestore-v1beta1-0.28.0_FirestoreGrpc.class │ ├── guava-23.5-jre.jar │ └── proto-google-cloud-firestore-v1beta1-0.28.0.jar ├── docs ├── .gitignore ├── 0001-what-is-a-diamond-dependency-conflict.md ├── 0002-why-doesnt-the-compiler-catch-diamond-dependency-conficts.md ├── 0003-how-does-version-resolution-work-in-maven-and-gradle.md ├── CNAME ├── DECLARING_DEPENDENCIES.md ├── Gemfile ├── JLBP-0001.md ├── JLBP-0002.md ├── JLBP-0003.md ├── JLBP-0004.md ├── JLBP-0005.md ├── JLBP-0006.md ├── JLBP-0007.md ├── JLBP-0008.md ├── JLBP-0009.md ├── JLBP-0010.md ├── JLBP-0011.md ├── JLBP-0012.md ├── JLBP-0013.md ├── JLBP-0014.md ├── JLBP-0015.md ├── JLBP-0016.md ├── JLBP-0017.md ├── JLBP-0018.md ├── JLBP-0019.md ├── JLBP-0020.md ├── JLBP-0021.md ├── JLBP-0022.md ├── README.md ├── _config.yml ├── _layouts │ └── default.html ├── assets │ ├── css │ │ └── style.css │ └── images │ │ ├── Cloud_Logo_Nav.svg │ │ ├── ddc-00.png │ │ ├── ddc-01.png │ │ ├── ddc-02.png │ │ ├── ddc-03.png │ │ ├── ddc-04.png │ │ ├── ddc-05.png │ │ ├── ddc-06.png │ │ ├── ddc-compiler-00.png │ │ ├── ddc-compiler-01.png │ │ ├── ddc-compiler-02.png │ │ ├── ddc-compiler-03.png │ │ ├── ddc-compiler-04.png │ │ ├── ddc-compiler-05.png │ │ ├── ddc-compiler-06.png │ │ ├── ddc-resolution-00.png │ │ ├── ddc-resolution-01.png │ │ ├── ddc-resolution-02.png │ │ ├── ddc-resolution-03.png │ │ ├── ddc-resolution-04.png │ │ ├── ddc-resolution-05.png │ │ ├── ddc-resolution-06.png │ │ ├── ddc-resolution-07.png │ │ ├── ddc-resolution-07b.png │ │ ├── ddc-resolution-08.png │ │ └── ddc-resolution-09.png ├── favicon.png └── glossary.md ├── enforcer-rules ├── README.md ├── kokoro │ └── release_build.sh ├── pom.xml └── src │ ├── it │ ├── abstract-method-errors │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── bom-project-error │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── bom-project-no-error │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── bom-project-no-packaging │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── bom-project-using-spring-repository │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── fail-build-for-linkage-errors │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── inaccessible-class-error │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── missing-filter-file-error │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── report-only-reachable-bom │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── report-only-reachable │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── return-type-mismatch │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── test-scope │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ └── war-project-private-modifier │ │ ├── invoker.properties │ │ ├── pom.xml │ │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com.google.example │ │ │ └── Dummy.java │ │ └── verify.groovy │ ├── main │ └── java │ │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── dependencies │ │ └── enforcer │ │ └── LinkageCheckerRule.java │ └── test │ ├── java │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── dependencies │ │ └── enforcer │ │ └── LinkageCheckerRuleTest.java │ └── resources │ ├── appengine-exclusion.xml │ └── dummy-0.0.1.jar ├── example-problems ├── README.md ├── appengine-api-sdk │ ├── README.md │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── examples │ │ └── AppEngineApiSdkExample.java ├── gradle-project │ ├── README.md │ ├── build.gradle │ ├── build │ │ └── classes │ │ │ └── java │ │ │ └── main │ │ │ └── App.class │ └── src │ │ └── main │ │ └── java │ │ └── App.java └── no-such-method-error-signature-mismatch │ ├── README.md │ ├── pom.xml │ └── src │ └── main │ └── java │ └── io │ └── grpc │ └── internal │ └── App.java ├── gradle-plugin ├── README.md ├── build.gradle ├── gradle.properties ├── gradle │ ├── functional-test.gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kokoro │ └── release.sh ├── settings.gradle └── src │ ├── functionalTest │ └── groovy │ │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── dependencies │ │ └── gradle │ │ ├── BuildStatusFunctionalTest.groovy │ │ └── ExclusionFileFunctionalTest.groovy │ ├── main │ └── java │ │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── dependencies │ │ └── gradle │ │ ├── DependencyNode.java │ │ ├── LinkageCheckTask.java │ │ ├── LinkageCheckerPlugin.java │ │ └── LinkageCheckerPluginExtension.java │ └── test │ └── groovy │ └── com │ └── google │ └── cloud │ └── tools │ └── dependencies │ └── gradle │ └── LinkageCheckerPluginTest.groovy ├── kokoro ├── continuous.bat ├── continuous.sh ├── gcp_windows │ ├── continuous.cfg │ └── presubmit.cfg ├── parent_release_build.sh └── ubuntu │ ├── continuous.cfg │ ├── java8-incompatible-reference-check.sh │ ├── linkage-monitor-gcs.cfg │ ├── linkage-monitor-gcs.sh │ ├── periodic.cfg │ ├── periodic.sh │ └── presubmit.cfg ├── library-best-practices ├── JLBP-1.md ├── JLBP-10.md ├── JLBP-11.md ├── JLBP-12.md ├── JLBP-13.md ├── JLBP-14.md ├── JLBP-15.md ├── JLBP-16.md ├── JLBP-17.md ├── JLBP-18.md ├── JLBP-19.md ├── JLBP-2.md ├── JLBP-20.md ├── JLBP-3.md ├── JLBP-4.md ├── JLBP-5.md ├── JLBP-6.md ├── JLBP-7.md ├── JLBP-8.md ├── JLBP-9.md ├── README.md └── glossary.md ├── linkage-monitor ├── README.md ├── action.yml ├── kokoro │ └── release_build.sh ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── dependencies │ │ └── linkagemonitor │ │ ├── HttpUtil.java │ │ ├── LinkageMonitor.java │ │ ├── PlaceholderConstants.java │ │ └── VersionSubstitutingModelResolver.java │ └── test │ ├── java │ └── com │ │ └── google │ │ └── cloud │ │ └── tools │ │ └── dependencies │ │ └── linkagemonitor │ │ ├── HttpUtilTest.java │ │ ├── LinkageMonitorTest.java │ │ └── VersionSubstitutingModelResolverTest.java │ └── resources │ └── testproject │ ├── gax-bom │ └── pom.xml │ ├── linkage-monitor-artifacts-invalid-format.txt │ ├── linkage-monitor-artifacts-nonexistent-coordinates.txt │ ├── linkage-monitor-artifacts-with-empty-line.txt │ ├── linkage-monitor-artifacts.txt │ ├── pom.xml │ └── testsubproject │ ├── build │ └── pom.xml │ └── pom.xml ├── mvnw ├── mvnw.cmd ├── pom.xml ├── renovate.json ├── scripts ├── cancel_release.sh ├── release.sh └── update_docs.sh └── temurin-install-testing ├── .gitignore ├── README.md ├── connect.sh ├── inputs.auto.tfvars ├── main.tf ├── outputs.tf ├── startup.ps1 ├── startup.sh ├── test-all.sh └── variables.tf /.allstar/binary_artifacts.yaml: -------------------------------------------------------------------------------- 1 | # Linkage Checker has test to examine JAR files and class files 2 | ignorePaths: 3 | - enforcer-rules/src/test/resources/dummy-0.0.1.jar 4 | - example-problems/gradle-project/build/classes/java/main/App.class 5 | 6 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | pull_request: 6 | name: ci 7 | jobs: 8 | units: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | java: [8, 11] 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-java@v1 16 | with: 17 | java-version: ${{matrix.java}} 18 | - name: Get current date 19 | id: date 20 | run: echo "date=$(date +'%Y-%m-%d' --utc)" >> "$GITHUB_OUTPUT" 21 | - uses: actions/cache@v4 22 | id: mvn-cache 23 | with: 24 | path: ~/.m2/repository 25 | key: ${{ runner.os }}-maven-unified-${{ steps.date.outputs.date }} 26 | - run: java -version 27 | # The http connection settings avoid Maven's HTTP connection reset in GitHub Actions 28 | # https://github.com/actions/virtual-environments/issues/1499#issuecomment-689467080 29 | - run: | 30 | ./mvnw -B -e -ntp install \ 31 | -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false \ 32 | -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 33 | - run: cd gradle-plugin && ./gradlew build publishToMavenLocal 34 | 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin/ 3 | proxy_bin/ 4 | target/ 5 | generated-sources/ 6 | .metadata/ 7 | **/.*.swp 8 | RemoteSystemsTempFiles/ 9 | .project 10 | .classpath 11 | .settings 12 | *.iml 13 | .idea 14 | .factorypath 15 | .apt_generated/ 16 | example-problems/*/.gradle 17 | example-problems/*/gradle 18 | example-problems/*/gradlew 19 | example-problems/*/gradlew.bat 20 | gradle-plugin/.gradle/ 21 | .mvn/wrapper/maven-wrapper.jar 22 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, 4 | and in the interest of fostering an open and welcoming community, 5 | we pledge to respect all people who contribute through reporting issues, 6 | posting feature requests, updating documentation, 7 | submitting pull requests or patches, and other activities. 8 | 9 | We are committed to making participation in this project 10 | a harassment-free experience for everyone, 11 | regardless of level of experience, gender, gender identity and expression, 12 | sexual orientation, disability, personal appearance, 13 | body size, race, ethnicity, age, religion, or nationality. 14 | 15 | Examples of unacceptable behavior by participants include: 16 | 17 | * The use of sexualized language or imagery 18 | * Personal attacks 19 | * Trolling or insulting/derogatory comments 20 | * Public or private harassment 21 | * Publishing other's private information, 22 | such as physical or electronic 23 | addresses, without explicit permission 24 | * Other unethical or unprofessional conduct. 25 | 26 | Project maintainers have the right and responsibility to remove, edit, or reject 27 | comments, commits, code, wiki edits, issues, and other contributions 28 | that are not aligned to this Code of Conduct. 29 | By adopting this Code of Conduct, 30 | project maintainers commit themselves to fairly and consistently 31 | applying these principles to every aspect of managing this project. 32 | Project maintainers who do not follow or enforce the Code of Conduct 33 | may be permanently removed from the project team. 34 | 35 | This code of conduct applies both within project spaces and in public spaces 36 | when an individual is representing the project or its community. 37 | 38 | Instances of abusive, harassing, or otherwise unacceptable behavior 39 | may be reported by opening an issue 40 | or contacting one or more of the project maintainers. 41 | 42 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, 43 | available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![unstable](http://badges.github.io/stability-badges/dist/unstable.svg)](http://github.com/badges/stability-badges) 2 | 3 | This project explores common infrastructure and best practices for open source 4 | Java projects for the Google Cloud Platform (GCP). 5 | 6 | # Google Cloud Platform Java Dependency Dashboard 7 | 8 | [Google Cloud Platform Java Dependency Dashboard]( 9 | https://storage.googleapis.com/cloud-opensource-java-dashboard/com.google.cloud/libraries-bom/snapshot/index.html) 10 | (runs daily; work in progress) shows multiple checks on the consistency among 11 | Google Cloud Java libraries. For manually generating the dashboard, see 12 | [its README](./dashboard/README.md). 13 | 14 | # Google Best Practices for Java Libraries 15 | 16 | [Google Best Practices for Java Libraries](https://googlecloudplatform.github.io/cloud-opensource-java/) 17 | are rules that minimize problems for consumers of interconnected Java libraries. 18 | 19 | # Linkage Checker 20 | 21 | ## Linkage Checker Maven Enforcer Rule 22 | 23 | [Linkage Checker Enforcer Rule](./enforcer-rules) detects [linkage errors]( 24 | ./library-best-practices/glossary.md#types-of-conflicts-and-compatibility) in 25 | the current Maven project as part of build. 26 | 27 | For its usage, see [the enforcer rule documentation]( 28 | https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-Enforcer-Rule). 29 | 30 | ## Linkage Checker Gradle Plugin 31 | 32 | [Linkage Checker Gradle Plugin](./gradle-plugin) provides the linkageCheck task that detects 33 | [linkage errors]( 34 | ./library-best-practices/glossary.md#types-of-conflicts-and-compatibility) in the current 35 | Gradle project. 36 | 37 | For its usage, see [the plugin documentation]( 38 | https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-with-Gradle). 39 | 40 | # GCP Libraries BOM 41 | 42 | The [GCP Libraries BOM](https://cloud.google.com/java/docs/bom) is a Bill-of-Materials (BOM) that 43 | provides consistent versions of Google Cloud Java libraries that work together 44 | without linkage errors. 45 | 46 | # Development 47 | 48 | This project is built using _Maven_. 49 | 50 | ## Requirements 51 | 52 | 1. Maven 3.6.0 or later. 53 | 54 | 1. JDK 8 or 11. 55 | 56 | 1. git 57 | 58 | 1. Clone the project to a local directory using `git clone 59 | git@github.com:GoogleCloudPlatform/cloud-opensource-java.git`. 60 | 61 | # Disclaimer 62 | 63 | This is not an officially supported Google product. 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /boms/convergence-check/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | com.google.cloud 9 | convergence-check 10 | 0.0.1-SNAPSHOT 11 | pom 12 | 13 | Cloud Platform Supported Libraries Convergence Check 14 | 15 | Import the Cloud Platform supported libraries and check for dependency convergence. 16 | 17 | 18 | 19 | Google LLC 20 | https://cloud.google.com 21 | 22 | 23 | 24 | 25 | The Apache License, Version 2.0 26 | http://www.apache.org/licenses/LICENSE-2.0.txt 27 | 28 | 29 | 30 | 31 | UTF-8 32 | 33 | 34 | 35 | 36 | 37 | com.google.cloud 38 | libraries-bom 39 | 2.5.0-SNAPSHOT 40 | pom 41 | import 42 | 43 | 44 | 45 | 46 | 47 | 48 | com.google.cloud 49 | google-cloud-core 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-enforcer-plugin 58 | 3.0.0-M2 59 | 60 | 61 | enforce 62 | 63 | enforce 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /boms/integration-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.google.cloud 8 | integration-tests 9 | 1.2.0-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | 1.8 14 | 1.8 15 | 16 | 17 | 18 | 19 | com.google.cloud.tools 20 | dependencies 21 | 1.5.16-SNAPSHOT 22 | 23 | 24 | junit 25 | junit 26 | 4.13.2 27 | test 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-surefire-plugin 37 | 2.22.2 38 | 39 | 40 | false 41 | -Xms128m -Xmx4g 42 | false 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /boms/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | com.google.cloud.tools.opensource 9 | cloud-tools-opensource-boms 10 | 1.0-SNAPSHOT 11 | pom 12 | 13 | BOM Parent 14 | https://github.com/GoogleCloudPlatform/cloud-opensource-java/boms 15 | 16 | Google LLC 17 | http://www.google.com 18 | 19 | 20 | 21 | UTF-8 22 | 23 | 24 | 25 | 26 | The Apache License, Version 2.0 27 | http://www.apache.org/licenses/LICENSE-2.0.txt 28 | 29 | 30 | 31 | 32 | cloud-oss-bom 33 | cloud-lts-bom 34 | upper-bounds-check 35 | integration-tests 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.codehaus.mojo 43 | exec-maven-plugin 44 | 3.0.0 45 | 46 | true 47 | none 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /dashboard/README.md: -------------------------------------------------------------------------------- 1 | To generate the dashboard from the root directory run: 2 | 3 | ``` 4 | $ mvn clean install 5 | $ cd dashboard 6 | $ mvn exec:java -Dexec.arguments="-f ../boms/cloud-oss-bom/pom.xml" 7 | ``` 8 | -------------------------------------------------------------------------------- /dashboard/src/main/java/com/google/cloud/tools/opensource/dashboard/ArtifactCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dashboard; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | import org.eclipse.aether.artifact.Artifact; 23 | 24 | import com.google.cloud.tools.opensource.dependencies.DependencyGraph; 25 | 26 | /** 27 | * Unified return type to bundle a lot of information about multiple artifacts together. 28 | */ 29 | class ArtifactCache { 30 | 31 | private Map infoMap; 32 | private List globalDependencies; 33 | 34 | void setInfoMap(Map infoMap) { 35 | this.infoMap = infoMap; 36 | } 37 | 38 | void setGlobalDependencies(List globalDependencies) { 39 | this.globalDependencies = globalDependencies; 40 | } 41 | 42 | Map getInfoMap() { 43 | return infoMap; 44 | } 45 | 46 | List getGlobalDependencies() { 47 | return globalDependencies; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /dashboard/src/main/java/com/google/cloud/tools/opensource/dashboard/ArtifactInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dashboard; 18 | 19 | import org.eclipse.aether.RepositoryException; 20 | 21 | import com.google.cloud.tools.opensource.dependencies.DependencyGraph; 22 | 23 | /** 24 | * Cache of info looked up for an artifact. 25 | */ 26 | class ArtifactInfo { 27 | 28 | private DependencyGraph completeDependencies; 29 | private DependencyGraph transitiveDependencies; 30 | private RepositoryException exception; 31 | 32 | ArtifactInfo(DependencyGraph completeDependencies, 33 | DependencyGraph transitiveDependencies) { 34 | this.completeDependencies = completeDependencies; 35 | this.transitiveDependencies = transitiveDependencies; 36 | } 37 | 38 | ArtifactInfo(RepositoryException ex) { 39 | this.exception = ex; 40 | } 41 | 42 | DependencyGraph getCompleteDependencies() { 43 | return completeDependencies; 44 | } 45 | 46 | DependencyGraph getTransitiveDependencies() { 47 | return transitiveDependencies; 48 | } 49 | 50 | RepositoryException getException() { 51 | return exception; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /dashboard/src/main/java/com/google/cloud/tools/opensource/dashboard/PieChart.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dashboard; 18 | 19 | import java.awt.geom.Point2D; 20 | 21 | public class PieChart { 22 | 23 | /** 24 | * Calculate SVG arc end for a pie piece. Assumes the piece starts at the top of the circle. 25 | * 26 | * Do not forget: 27 | * 28 | * 1. SVG origin starts at top left. 29 | * 2. x increases to the right and y increases **down**. 30 | */ 31 | static Point2D calculateEndPoint(double radius, double centerX, double centerY, double ratio) { 32 | if (ratio > 1) { 33 | ratio = 1.0; 34 | } 35 | 36 | double radians = ratio * 2 * Math.PI; 37 | 38 | // Since we're starting at the top of the circle this is rotated 90 degrees 39 | // from the normal coordinates. This is why we use sine for x and cosine for y. 40 | double x = radius * (1 + Math.sin(radians)); 41 | double y = radius * (1 - Math.cos(radians)); 42 | return new Point2D.Double(x + centerX - radius, y + centerY - radius); 43 | } 44 | 45 | // so I can avoid teaching FreeMarker how to wrap a java.awt.Point 46 | public static double calculateEndPointX( 47 | double radius, double centerX, double centerY, double ratio) { 48 | return calculateEndPoint(radius, centerX, centerY, ratio).getX(); 49 | } 50 | 51 | public static double calculateEndPointY( 52 | double radius, double centerX, double centerY, double ratio) { 53 | return calculateEndPoint(radius, centerX, centerY, ratio).getY(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /dashboard/src/main/resources/js/dashboard.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Toggles the visibility of an HTML element below the button. 19 | * @param button clicked button element 20 | */ 21 | function toggleNextSiblingVisibility(button) { 22 | const nextSibling = button.parentElement.nextElementSibling; 23 | const currentVisibility = nextSibling.style.display !== "none"; 24 | const nextVisibility = !currentVisibility; 25 | nextSibling.style.display = nextVisibility ? "" : "none"; 26 | button.innerText = nextVisibility ? "▼" : "▶"; 27 | } 28 | -------------------------------------------------------------------------------- /dashboard/src/main/resources/poms/demo.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.google.cloud 7 | demo 8 | 1.0-SNAPSHOT 9 | jar 10 | 11 | demo-pom 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 17 | 18 | 19 | 20 | ${dependencyGroupId} 21 | ${dependencyArtifactId} 22 | ${dependencyVersion} 23 | test 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-enforcer-plugin 32 | 3.0.0-M1 33 | 34 | 35 | enforce 36 | 37 | enforce 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /dashboard/src/main/resources/templates/dependency_trees.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "macros.ftl"> 4 | 5 | 6 | Google Cloud Platform Java Open Source Dependency Dashboard: Dependency Trees 7 | 8 | 9 | 10 | 11 |

Dependency Tree of the Artifacts in ${coordinates}

12 |

BOM: ${coordinates?html}

13 | <#list dependencyGraphs as graph> 14 | <#assign rootPath = graph.getRootPath() /> 15 |

Dependency Tree of ${rootPath.getLeaf()?html}

16 | <@formatDependencyGraph graph rootPath "" /> 17 | 18 | 19 |
20 |

Last generated at ${lastUpdated}

21 | 22 | -------------------------------------------------------------------------------- /dashboard/src/main/resources/templates/unstable_artifacts.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "macros.ftl"> 4 | 5 | 6 | Google Cloud Platform Java Open Source Dependency Dashboard: Unstable Artifacts 7 | 8 | 9 | 10 | 11 |

Dependency Status of ${coordinates}

12 |

BOM: ${coordinates?html}

13 |

Pre 1.0 Versions

14 | 15 |

16 | These are dependencies found in the GCP orbit that have not yet reached 1.0. 17 | No 1.0 or later library should depend on them. 18 | If the libraries are stable, advance them to 1.0. 19 | Otherwise replace the dependency with something else. 20 |

21 | 22 | <#assign unstableCount = 0> 23 |
    24 | <#list latestArtifacts as artifact, version> 25 | <#if version[0] == '0'> 26 | <#assign unstableCount++> 27 |
  • ${artifact}:${version}
  • 28 | 29 | 30 |
31 | 32 | <#if unstableCount == 0> 33 |

All versions are 1.0 or later.

34 | 35 | 36 | 37 |
38 |

Last generated at ${lastUpdated}

39 | 40 | -------------------------------------------------------------------------------- /dashboard/src/main/resources/templates/version_index.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ${groupId}:${artifactId} 6 | 7 | 8 | 9 |

${groupId}:${artifactId}

10 | 11 |
    12 | <#list versions as version> 13 |
  • 14 | ${version} 15 |
  • 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /dashboard/src/test/java/com/google/cloud/tools/opensource/dashboard/ArtifactResultsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dashboard; 18 | 19 | import org.eclipse.aether.artifact.DefaultArtifact; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | public class ArtifactResultsTest { 24 | 25 | private ArtifactResults results = 26 | new ArtifactResults(new DefaultArtifact("com.google.guava:guava:23.0")); 27 | 28 | @Test 29 | public void testAddResult() { 30 | results.addResult("foo", 0); 31 | results.addResult("bar", 10); 32 | Assert.assertTrue(results.getResult("foo")); 33 | Assert.assertFalse(results.getResult("bar")); 34 | Assert.assertNull(results.getResult("baz")); 35 | } 36 | 37 | @Test 38 | public void testGetFailureCount() { 39 | results.addResult("foo", 0); 40 | results.addResult("bar", 10); 41 | Assert.assertEquals(0, results.getFailureCount("foo")); 42 | Assert.assertEquals(10, results.getFailureCount("bar")); 43 | Assert.assertEquals(0, results.getFailureCount("baz")); 44 | } 45 | 46 | @Test 47 | public void testGetCoordinates() { 48 | Assert.assertEquals("com.google.guava:guava:23.0", results.getCoordinates()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /dependencies/kokoro/release_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands to stderr. 6 | set -x 7 | 8 | cd github/cloud-opensource-java/dependencies 9 | 10 | mvn -V -Prelease -B -U verify 11 | 12 | # copy pom with the name expected in the Maven repository 13 | ARTIFACT_ID=$(mvn -B help:evaluate -Dexpression=project.artifactId 2>/dev/null | grep -v "^\[") 14 | PROJECT_VERSION=$(mvn -B help:evaluate -Dexpression=project.version 2>/dev/null| grep -v "^\[") 15 | cp pom.xml target/${ARTIFACT_ID}-${PROJECT_VERSION}.pom 16 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/AccessModifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import org.apache.bcel.Const; 20 | 21 | /** A modifier that controls access to classes, fields, or methods. */ 22 | enum AccessModifier { 23 | PUBLIC("is public"), 24 | PRIVATE("is private"), 25 | PROTECTED("is private"), 26 | DEFAULT("has default access"); 27 | 28 | private String description; 29 | 30 | AccessModifier(String description) { 31 | this.description = description; 32 | } 33 | 34 | static AccessModifier fromFlag(int modifierFlag) { 35 | if ((modifierFlag & Const.ACC_PUBLIC) != 0) { 36 | return PUBLIC; 37 | } else if ((modifierFlag & Const.ACC_PRIVATE) != 0) { 38 | return PRIVATE; 39 | } else if ((modifierFlag & Const.ACC_PROTECTED) != 0) { 40 | return PROTECTED; 41 | } else { 42 | return DEFAULT; 43 | } 44 | } 45 | 46 | String describe(String item) { 47 | return item + " " + description; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/ClassMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Matcher on class names. */ 20 | class ClassMatcher implements LinkageProblemTargetMatcher, LinkageProblemSourceMatcher { 21 | 22 | private final String className; 23 | 24 | ClassMatcher(String className) { 25 | this.className = className; 26 | } 27 | 28 | @Override 29 | public boolean match(Symbol symbol) { 30 | return symbol.getClassBinaryName().equals(className); 31 | } 32 | 33 | @Override 34 | public boolean match(ClassFile sourceClass) { 35 | return sourceClass.getBinaryName().equals(className); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/ClassNotFoundProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** The {@code classSymbol}, referenced by {@code sourceClass} is not found in the class path. */ 20 | public final class ClassNotFoundProblem extends LinkageProblem { 21 | 22 | public ClassNotFoundProblem(ClassFile sourceClass, ClassSymbol classSymbol) { 23 | super("is not found", sourceClass, classSymbol, null); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/ClassSymbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import java.util.Objects; 20 | 21 | /** Symbol for a class. */ 22 | public class ClassSymbol extends Symbol { 23 | public ClassSymbol(String className) { 24 | super(className); 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "Class " + getClassBinaryName(); 30 | } 31 | 32 | @Override 33 | public int hashCode() { 34 | return Objects.hash(this.getClassBinaryName()); 35 | } 36 | 37 | @Override 38 | public boolean equals(Object other) { 39 | if (this == other) { 40 | return true; 41 | } 42 | if (other == null || getClass() != other.getClass()) { 43 | return false; 44 | } 45 | Symbol symbol = (Symbol) other; 46 | return this.getClassBinaryName().equals(symbol.getClassBinaryName()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/DependencyMediation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import com.google.cloud.tools.opensource.dependencies.DependencyGraph; 20 | import org.eclipse.aether.version.InvalidVersionSpecificationException; 21 | 22 | /** 23 | * Algorithm to select artifacts when there are multiple versions for the same groupId and 24 | * artifactId in a dependency graph. 25 | * 26 | *

The algorithm does not take classifier or extension into account. 27 | */ 28 | public interface DependencyMediation { 29 | 30 | DependencyMediation MAVEN = new MavenDependencyMediation(); 31 | DependencyMediation GRADLE = new GradleDependencyMediation(); 32 | 33 | /** 34 | * Returns {@link AnnotatedClassPath} after performing dependency mediation. This means that the 35 | * returned list of class path entries has no duplicate artifacts in terms of the groupId and 36 | * artifactId combination. 37 | * 38 | * @param dependencyGraph dependency graph that may have duplicate artifacts that have the same 39 | * groupId and artifactId combination 40 | */ 41 | AnnotatedClassPath mediate(DependencyGraph dependencyGraph) 42 | throws InvalidVersionSpecificationException; 43 | } 44 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/FieldMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | 21 | /** Matcher on field symbols. */ 22 | class FieldMatcher implements LinkageProblemTargetMatcher { 23 | 24 | private final String className; 25 | private final String fieldName; 26 | 27 | FieldMatcher(String className, String fieldName) { 28 | this.className = checkNotNull(className); 29 | this.fieldName = checkNotNull(fieldName); 30 | } 31 | 32 | /** Returns true if {@code symbol} is {@link #fieldName} of {@link #className}. */ 33 | @Override 34 | public boolean match(Symbol symbol) { 35 | if (symbol instanceof FieldSymbol) { 36 | FieldSymbol fieldSymbol = (FieldSymbol) symbol; 37 | return fieldSymbol.getClassBinaryName().equals(className) 38 | && fieldSymbol.getName().equals(fieldName); 39 | } 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/InaccessibleMemberProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * The {@code symbol} (method or field) defined in {@code targetClass} is inaccessible to the {@code 21 | * sourceClass}. 22 | * 23 | *

If the source class is in a different package than the target class, the member is not public. 24 | * If the source is in the same package, the member is private. If the source is a subclass of the 25 | * target class, the member is not protected or public. 26 | */ 27 | final class InaccessibleMemberProblem extends LinkageProblem { 28 | private AccessModifier modifier; 29 | 30 | InaccessibleMemberProblem( 31 | ClassFile sourceClass, ClassFile targetClass, Symbol symbol, AccessModifier modifier) { 32 | super("is not accessible", sourceClass, symbol, targetClass); 33 | this.modifier = modifier; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/IncompatibleClassChangeProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * The {@code symbol} (class or interface) defined in {@code targetClass} is not binary-compatible 21 | * with the {@code sourceClass}. 22 | * 23 | *

An example case of breaking binary-compatibility is when a superclass changes a method to 24 | * {@code final} and a subclass is still overriding the method. Another example is when there is a 25 | * method call to an interface and the interface is changed to a class with the same name. For 26 | * details, see "Interface Method Resolution" below). 27 | * 28 | * @see Java 29 | * Language Specification: 13.4.9. final Fields and static Constant Variables 30 | * @see Java 31 | * Virtual Machine Specification: 5.4.3.4. Interface Method Resolution 32 | */ 33 | final class IncompatibleClassChangeProblem extends LinkageProblem { 34 | 35 | IncompatibleClassChangeProblem(ClassFile sourceClass, ClassFile targetClass, Symbol symbol) { 36 | super("has changed incompatibly", sourceClass, symbol, targetClass); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/InterfaceSymbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * Symbol for an interface. This symbol is a special case of {@link ClassSymbol} when a referencing 21 | * class is declared to implement the interface. 22 | */ 23 | final class InterfaceSymbol extends ClassSymbol { 24 | InterfaceSymbol(String className) { 25 | super(className); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/LinkageCheckResultException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * {@link LinkageCheckerMain} throws this exception when it finds linkage errors. 21 | * 22 | *

The caller of the tool can tell the existence of linkage errors by checking the exit status of 23 | * the {@link LinkageCheckerMain}. 24 | */ 25 | public final class LinkageCheckResultException extends Exception { 26 | LinkageCheckResultException(int linkageErrorCount) { 27 | super( 28 | "Found " 29 | + (linkageErrorCount == 1 30 | ? "1 linkage error" 31 | : (linkageErrorCount + " linkage errors"))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/LinkageErrorMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | 21 | import javax.annotation.Nullable; 22 | 23 | /** Matcher for linkage errors. A linkage error has a target symbol and a source class file. */ 24 | class LinkageErrorMatcher implements LinkageProblemMatcher { 25 | 26 | /** Matcher for the source class of the linkage error. Null if no Source element. */ 27 | @Nullable private SourceMatcher sourceMatcher; 28 | 29 | /** Matcher for the target symbol of the linkage error. Null if no Target element. */ 30 | @Nullable private TargetMatcher targetMatcher; 31 | 32 | void setSourceMatcher(SourceMatcher sourceMatcher) { 33 | this.sourceMatcher = checkNotNull(sourceMatcher); 34 | } 35 | 36 | void setTargetMatcher(TargetMatcher targetMatcher) { 37 | this.targetMatcher = checkNotNull(targetMatcher); 38 | } 39 | 40 | /** 41 | * Returns true if {@link #sourceMatcher} matches if present and {@link #targetMatcher} matches if 42 | * present. 43 | */ 44 | @Override 45 | public boolean match(LinkageProblem problem) { 46 | if (sourceMatcher != null && !sourceMatcher.match(problem)) { 47 | return false; 48 | } 49 | if (targetMatcher != null && !targetMatcher.match(problem)) { 50 | return false; 51 | } 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/LinkageProblemCause.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Annotation for {@link LinkageProblem} that explains why the invalid reference is introduced. */ 20 | abstract class LinkageProblemCause {} 21 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/LinkageProblemMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Matcher for LinkageProblems. */ 20 | interface LinkageProblemMatcher { 21 | boolean match(LinkageProblem problem); 22 | 23 | default void addChild(LinkageProblemTargetMatcher child) { 24 | throw new IllegalStateException("This element is not supposed to take child element"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/LinkageProblemSourceMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Matchers for the sources of linkage errors. */ 20 | interface LinkageProblemSourceMatcher { 21 | boolean match(ClassFile sourceClass); 22 | } 23 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/LinkageProblemTargetMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Matchers for the targets of linkage errors. */ 20 | interface LinkageProblemTargetMatcher { 21 | boolean match(Symbol symbol); 22 | } 23 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/MethodMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | 21 | /** Matcher on method symbols. */ 22 | class MethodMatcher implements LinkageProblemTargetMatcher { 23 | 24 | private final String className; 25 | private final String methodName; 26 | 27 | MethodMatcher(String className, String methodName) { 28 | this.className = checkNotNull(className); 29 | this.methodName = checkNotNull(methodName); 30 | } 31 | 32 | /** Returns true if {@code symbol} has {@link #methodName} of {@link #className}. */ 33 | @Override 34 | public boolean match(Symbol symbol) { 35 | if (symbol instanceof MethodSymbol) { 36 | MethodSymbol methodSymbol = (MethodSymbol) symbol; 37 | return methodSymbol.getClassBinaryName().equals(className) 38 | && methodSymbol.getName().equals(methodName); 39 | } 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/PackageMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | 21 | /** 22 | * Matcher on the classes of a package and its subpackages. 23 | * 24 | *

For example, {@code PackageMatcher("com.google")} matches {@code com.google.Foo} class as well 25 | * as {@code com.google.cloud.Bar}. 26 | */ 27 | class PackageMatcher implements LinkageProblemTargetMatcher, LinkageProblemSourceMatcher { 28 | 29 | private final String packageName; 30 | 31 | PackageMatcher(String packageName) { 32 | this.packageName = checkNotNull(packageName); 33 | } 34 | 35 | @Override 36 | public boolean match(Symbol problem) { 37 | return problem.getClassBinaryName().startsWith(packageName + "."); 38 | } 39 | 40 | @Override 41 | public boolean match(ClassFile source) { 42 | return source.getBinaryName().startsWith(packageName); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/ReturnTypeChangedProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import java.util.Objects; 20 | import javax.annotation.Nullable; 21 | import org.apache.bcel.classfile.Utility; 22 | 23 | /** 24 | * The {@code sourceClass} references the {@code expectedMethodSymbol}, but the {@code 25 | * expectedMethodSymbol.getClassBinaryName} has the method with a different return type ({@code 26 | * actualTypeName}). 27 | */ 28 | class ReturnTypeChangedProblem extends LinkageProblem { 29 | private String actualType; 30 | 31 | ReturnTypeChangedProblem( 32 | ClassFile sourceClass, 33 | @Nullable ClassFile targetClass, 34 | MethodSymbol expectedMethodSymbol, 35 | String actualType) { 36 | super( 37 | "is expected to return " 38 | + Utility.methodSignatureReturnType(expectedMethodSymbol.getDescriptor()) 39 | + " but instead returns " 40 | + actualType, 41 | sourceClass, 42 | expectedMethodSymbol, 43 | targetClass); 44 | this.actualType = actualType; 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return Objects.hash(super.hashCode(), actualType); 50 | } 51 | 52 | @Override 53 | public boolean equals(Object other) { 54 | return super.equals(other) // this checks the class equality 55 | && Objects.equals(actualType, ((ReturnTypeChangedProblem) other).actualType); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/SourceMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Matcher on the source class file of linkage errors. */ 20 | class SourceMatcher implements LinkageProblemMatcher { 21 | 22 | private LinkageProblemSourceMatcher matcher; 23 | 24 | @Override 25 | public void addChild(LinkageProblemTargetMatcher child) { 26 | this.matcher = (LinkageProblemSourceMatcher) child; 27 | } 28 | 29 | @Override 30 | public boolean match(LinkageProblem problem) { 31 | return matcher.match(problem.getSourceClass()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/SuperClassSymbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * Symbol for a super class. This symbol is a special case of {@link ClassSymbol} when it is 21 | * referenced only from its subclasses. Treating super class symbols apart from {@link ClassSymbol} 22 | * helps to validate the relationship between a superclass and its subclasses, with regard to {code 23 | * final} keyword. 24 | * 25 | * @see Java 26 | * Virtual Machine Specification: 4.10. Verification of class Files 27 | */ 28 | final class SuperClassSymbol extends ClassSymbol { 29 | SuperClassSymbol(String className) { 30 | super(className); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/Symbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | 21 | import com.google.common.base.MoreObjects; 22 | 23 | /** 24 | * The referent of symbolic references (class, method, or field references) in the run-time constant 25 | * pool of JVM. 26 | * 27 | * @see Java 28 | * Virtual Machine Specification: The Run-Time Constant Pool 29 | */ 30 | public abstract class Symbol { 31 | private final String classBinaryName; 32 | 33 | Symbol(String className) { 34 | this.classBinaryName = checkNotNull(className); 35 | } 36 | 37 | /** 38 | * Returns the binary name of the class that contains the symbol. If this is a class symbol, the 39 | * class name itself. 40 | * 41 | * @see Java 42 | * Language Specification: 13.1. The Form of a Binary 43 | */ 44 | public String getClassBinaryName() { 45 | return classBinaryName; 46 | } 47 | 48 | @Override 49 | public abstract boolean equals(Object other); 50 | 51 | @Override 52 | public abstract int hashCode(); 53 | 54 | @Override 55 | public String toString() { 56 | return MoreObjects.toStringHelper(this) 57 | .add("className", classBinaryName) 58 | .toString(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/SymbolNotFoundProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * The {@code sourceClass} references the {@code symbol}, but the {@code targetClass} does not have 21 | * the symbol. 22 | */ 23 | public final class SymbolNotFoundProblem extends LinkageProblem { 24 | public SymbolNotFoundProblem(ClassFile sourceClass, ClassFile targetClass, Symbol symbol) { 25 | super("is not found", sourceClass, symbol, targetClass); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/TargetMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** Matcher on the target symbol of linkage errors. */ 20 | class TargetMatcher implements LinkageProblemMatcher { 21 | 22 | private LinkageProblemTargetMatcher matcher; 23 | 24 | @Override 25 | public void addChild(LinkageProblemTargetMatcher child) { 26 | this.matcher = child; 27 | } 28 | 29 | @Override 30 | public boolean match(LinkageProblem problem) { 31 | return matcher.match(problem.getSymbol()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/classpath/UnknownCause.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | /** 20 | * Linkage Checker cannot determine the cause of the linkage error. 21 | * 22 | *

This occurs when the POM file that used in building a library and the published POM file are 23 | * different. 24 | */ 25 | public final class UnknownCause extends LinkageProblemCause { 26 | 27 | private static UnknownCause instance = new UnknownCause(); 28 | 29 | static UnknownCause getInstance() { 30 | return instance; 31 | } 32 | 33 | private UnknownCause() {} 34 | 35 | @Override 36 | public String toString() { 37 | return "Unknown"; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object obj) { 42 | return obj == instance; 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | return super.hashCode(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/Artifacts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.eclipse.aether.artifact.Artifact; 20 | 21 | /** 22 | * Common utilities for operating on {@code org.eclipse.aether.artifact.Artifact} objects. 23 | */ 24 | public final class Artifacts { 25 | 26 | private Artifacts() { 27 | } 28 | 29 | /** 30 | * Returns the artifact's Maven coordinates in the form groupId:artifactId:version. Repo and 31 | * packaging are not included. 32 | */ 33 | public static String toCoordinates(Artifact artifact) { 34 | return (artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion()); 35 | } 36 | 37 | public static String makeKey(Artifact artifact) { 38 | return (artifact.getGroupId() + ":" + artifact.getArtifactId()); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/BanOptionalDependencySelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.eclipse.aether.collection.DependencyCollectionContext; 20 | import org.eclipse.aether.collection.DependencySelector; 21 | import org.eclipse.aether.graph.Dependency; 22 | 23 | /** 24 | * A dependency selector that disallows all optional dependencies regardless of depth. 25 | */ 26 | class BanOptionalDependencySelector implements DependencySelector { 27 | 28 | @Override 29 | public boolean selectDependency(Dependency dependency) { 30 | return !dependency.isOptional(); 31 | } 32 | 33 | @Override 34 | public DependencySelector deriveChildSelector(DependencyCollectionContext context) { 35 | return this; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/DependencyLister.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import com.google.common.collect.ImmutableList; 20 | import java.util.List; 21 | import org.eclipse.aether.artifact.DefaultArtifact; 22 | 23 | class DependencyLister { 24 | 25 | public static void main(String[] args) { 26 | 27 | if (args.length != 1 || !args[0].contains(":")) { 28 | System.err.println("Usage: java " + DependencyLister.class.getCanonicalName() 29 | + " groupdId:artifactId:version"); 30 | return; 31 | } 32 | 33 | try { 34 | DefaultArtifact artifact = new DefaultArtifact(args[0]); 35 | 36 | DependencyGraphBuilder dependencyGraphBuilder = new DependencyGraphBuilder(); 37 | DependencyGraph graph = 38 | dependencyGraphBuilder 39 | .buildFullDependencyGraph(ImmutableList.of(artifact)); 40 | 41 | List paths = graph.list(); 42 | for (DependencyPath path : paths) { 43 | System.out.println(path); 44 | } 45 | } catch (IllegalArgumentException ex) { 46 | System.err.println("Bad Maven coordinates " + args[0]); 47 | return; 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/DependencyTreePrinter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import com.google.common.collect.ImmutableList; 20 | import org.eclipse.aether.artifact.DefaultArtifact; 21 | 22 | /** Prints the dependency tree of Maven artifacts. */ 23 | class DependencyTreePrinter { 24 | 25 | public static void main(String[] args) { 26 | if (args.length < 1) { 27 | System.err.println("Maven coordinates not provided. E.g., 'io.grpc:grpc-auth:1.19.0'"); 28 | return; 29 | } 30 | for (String coordinates : args) { 31 | printDependencyTree(coordinates); 32 | } 33 | } 34 | 35 | private static void printDependencyTree(String coordinates) { 36 | DefaultArtifact rootArtifact = new DefaultArtifact(coordinates); 37 | DependencyGraphBuilder dependencyGraphBuilder = new DependencyGraphBuilder(); 38 | DependencyGraph dependencyGraph = dependencyGraphBuilder.buildFullDependencyGraph( 39 | ImmutableList.of(rootArtifact)); 40 | 41 | for (UnresolvableArtifactProblem problem : dependencyGraph.getUnresolvedArtifacts()) { 42 | System.out.println(problem); 43 | } 44 | 45 | System.out.println("Dependencies for " + coordinates); 46 | System.out.println(DependencyTreeFormatter.formatDependencyPaths(dependencyGraph.list())); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/DirectProvidedDependencySelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.eclipse.aether.collection.DependencyCollectionContext; 20 | import org.eclipse.aether.collection.DependencySelector; 21 | import org.eclipse.aether.graph.Dependency; 22 | 23 | /** Selects direct provided-scope dependencies. */ 24 | public class DirectProvidedDependencySelector implements DependencySelector { 25 | 26 | private int depth; 27 | 28 | DirectProvidedDependencySelector() { 29 | this(0); 30 | } 31 | 32 | private DirectProvidedDependencySelector(int depth) { 33 | this.depth = depth; 34 | } 35 | 36 | @Override 37 | public boolean selectDependency(Dependency dependency) { 38 | if (depth < 2) { 39 | return true; 40 | } 41 | 42 | return !"provided".equals(dependency.getScope()); 43 | } 44 | 45 | @Override 46 | public DependencySelector deriveChildSelector( 47 | DependencyCollectionContext dependencyCollectionContext) { 48 | if (depth >= 2) { 49 | return this; 50 | } 51 | return new DirectProvidedDependencySelector(depth + 1); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/FilteringZipDependencySelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import java.util.Map; 20 | import org.eclipse.aether.artifact.Artifact; 21 | import org.eclipse.aether.collection.DependencyCollectionContext; 22 | import org.eclipse.aether.collection.DependencySelector; 23 | import org.eclipse.aether.graph.Dependency; 24 | 25 | /** Excludes artifacts with {@code zip} type. */ 26 | public final class FilteringZipDependencySelector implements DependencySelector { 27 | // To exclude log4j-api-java9:zip:2.11.1, which is not published. 28 | // https://github.com/GoogleCloudPlatform/cloud-opensource-java/issues/339 29 | 30 | @Override 31 | public boolean selectDependency(Dependency dependency) { 32 | Artifact artifact = dependency.getArtifact(); 33 | Map properties = artifact.getProperties(); 34 | // Because LinkageChecker only checks jar file, zip files are not needed 35 | return !"zip".equals(properties.get("type")); 36 | } 37 | 38 | @Override 39 | public DependencySelector deriveChildSelector( 40 | DependencyCollectionContext dependencyCollectionContext) { 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/InvalidClassFileProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import static com.google.common.base.Preconditions.checkArgument; 20 | 21 | import com.google.common.collect.ImmutableList; 22 | import java.util.List; 23 | import org.eclipse.aether.graph.DependencyNode; 24 | 25 | /** Problem describing a Maven artifact containing invalid class files. */ 26 | public final class InvalidClassFileProblem extends ArtifactProblem { 27 | /** The invalid class file names. Never empty. */ 28 | private final ImmutableList classFileNames; 29 | 30 | InvalidClassFileProblem(List dependencyPath, List classFileNames) { 31 | super(dependencyPath.get(dependencyPath.size() - 1).getArtifact(), dependencyPath); 32 | checkArgument(!classFileNames.isEmpty(), "ClassFileNames cannot be empty"); 33 | this.classFileNames = ImmutableList.copyOf(classFileNames); 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | int classFileCount = classFileNames.size(); 39 | 40 | String classFileDescription; 41 | if (classFileCount == 1) { 42 | classFileDescription = "an invalid class file " + classFileNames.get(0) + "."; 43 | } else { 44 | classFileDescription = 45 | classFileCount + " invalid class files (example: " + classFileNames.get(0) + ")."; 46 | } 47 | return artifact + " contains " + classFileDescription + " Dependency path: " + getPath(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/ManagedDependencyLister.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.eclipse.aether.RepositorySystem; 20 | import org.eclipse.aether.RepositorySystemSession; 21 | import org.eclipse.aether.artifact.DefaultArtifact; 22 | import org.eclipse.aether.graph.Dependency; 23 | import org.eclipse.aether.resolution.ArtifactDescriptorException; 24 | import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 25 | import org.eclipse.aether.resolution.ArtifactDescriptorResult; 26 | 27 | /** 28 | * Demo retrieving list of managed dependencies from Maven coordinates. 29 | */ 30 | class ManagedDependencyLister { 31 | 32 | private static final RepositorySystem system = RepositoryUtility.newRepositorySystem(); 33 | 34 | public static void main(String[] args) throws ArtifactDescriptorException { 35 | DefaultArtifact artifact = 36 | new DefaultArtifact("com.google.cloud:libraries-bom:pom:1.0.0"); 37 | 38 | RepositorySystemSession session = RepositoryUtility.newSession(system); 39 | 40 | ArtifactDescriptorRequest request = new ArtifactDescriptorRequest(); 41 | request.addRepository(RepositoryUtility.CENTRAL); 42 | request.setArtifact(artifact); 43 | 44 | ArtifactDescriptorResult resolved = system.readArtifactDescriptor(session, request); 45 | for (Dependency dependency : resolved.getManagedDependencies()) { 46 | System.out.println(dependency); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/MavenRepositoryException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | /** 20 | * Error interacting with a remote or local Maven repository such as artifact not found. 21 | */ 22 | public class MavenRepositoryException extends Exception { 23 | 24 | MavenRepositoryException(Exception ex) { 25 | super(ex); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/NonTestDependencySelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.eclipse.aether.collection.DependencyCollectionContext; 20 | import org.eclipse.aether.collection.DependencySelector; 21 | import org.eclipse.aether.graph.Dependency; 22 | 23 | /** 24 | * Selects dependencies except {@code test} scope. 25 | * 26 | *

This class selects all dependencies except {@code test}-scoped ones, while Maven's default 27 | * {@link org.eclipse.aether.util.graph.selector.ScopeDependencySelector} selects all direct 28 | * dependencies (including {@code test} scope). 29 | */ 30 | public class NonTestDependencySelector implements DependencySelector { 31 | @Override 32 | public boolean selectDependency(Dependency dependency) { 33 | return !"test".equals(dependency.getScope()); 34 | } 35 | 36 | @Override 37 | public DependencySelector deriveChildSelector( 38 | DependencyCollectionContext dependencyCollectionContext) { 39 | return this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/PathToNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import java.util.Objects; 20 | 21 | /** 22 | * A path to a node in a {@link DependencyGraph}. 23 | * 24 | * @param The type of the graph node. It's {@code org.eclipse.aether.graph.DependencyNode} for 25 | * Maven's graph and {@code org.gradle.api.artifacts.ResolvedDependency} for Gradle's graph. 26 | */ 27 | public final class PathToNode { 28 | private final T node; 29 | 30 | // This may be null for the root 31 | private final DependencyPath parentPath; 32 | 33 | /** Returns the node in the graph traversal. */ 34 | public T getNode() { 35 | return node; 36 | } 37 | 38 | /** Returns the path from the root of the graph to the parent of the node. */ 39 | public DependencyPath getParentPath() { 40 | return parentPath; 41 | } 42 | 43 | public PathToNode(T node, DependencyPath parentPath) { 44 | this.node = node; 45 | this.parentPath = parentPath; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object other) { 50 | if (this == other) { 51 | return true; 52 | } 53 | if (other == null || getClass() != other.getClass()) { 54 | return false; 55 | } 56 | PathToNode that = (PathToNode) other; 57 | return Objects.equals(node, that.node) && Objects.equals(parentPath, that.parentPath); 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | return Objects.hash(node, parentPath); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/UnresolvableArtifactProblem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import com.google.common.collect.ImmutableList; 20 | import java.util.List; 21 | import org.eclipse.aether.artifact.Artifact; 22 | import org.eclipse.aether.graph.DependencyNode; 23 | 24 | /** Problem describing unresolvable Maven artifact in a dependency tree. */ 25 | public final class UnresolvableArtifactProblem extends ArtifactProblem { 26 | 27 | /** 28 | * Problem when Maven cannot resolve {@code artifact} in a dependency tree. 29 | * 30 | *

Prefer {@link #UnresolvableArtifactProblem(List)} when the dependency path to the artifact 31 | * is available, because it gives a more detailed error message. 32 | * 33 | * @param artifact the unavailable artifact 34 | */ 35 | public UnresolvableArtifactProblem(Artifact artifact) { 36 | super(artifact, ImmutableList.of()); 37 | } 38 | 39 | /** 40 | * Problem when Maven cannot resolve the artifact at the leaf of {@code dependencyPath} in a 41 | * dependency tree. 42 | * 43 | * @param dependencyPath to the unavailable artifact 44 | */ 45 | public UnresolvableArtifactProblem(List dependencyPath) { 46 | super(dependencyPath.get(dependencyPath.size() - 1).getArtifact(), dependencyPath); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | if (dependencyPath.isEmpty()) { 52 | return artifact + " was not resolved. Dependency path is unknown."; 53 | } else { 54 | return artifact + " was not resolved. Dependency path: " + getPath(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dependencies/src/main/java/com/google/cloud/tools/opensource/dependencies/VersionComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import java.util.Comparator; 20 | 21 | import org.apache.maven.artifact.versioning.ComparableVersion; 22 | 23 | /** 24 | * Compare semantically by version. 25 | */ 26 | public class VersionComparator implements Comparator { 27 | 28 | @Override 29 | public int compare(String version1, String version2) { 30 | return new ComparableVersion(version1).compareTo(new ComparableVersion(version2)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/classpath/ClassFileTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.common.testing.EqualsTester; 22 | import com.google.common.testing.NullPointerTester; 23 | import com.google.common.testing.NullPointerTester.Visibility; 24 | import java.nio.file.Paths; 25 | import org.junit.Test; 26 | 27 | public class ClassFileTest { 28 | 29 | @Test 30 | public void testCreation() { 31 | ClassPathEntry entry = new ClassPathEntry(Paths.get("foo", "bar.jar")); 32 | ClassFile file = new ClassFile(entry, "com.test.Foo"); 33 | assertEquals("com.test.Foo", file.getBinaryName()); 34 | assertEquals(new ClassPathEntry(Paths.get("foo", "bar.jar")), file.getClassPathEntry()); 35 | } 36 | 37 | @Test 38 | public void testNull() { 39 | new NullPointerTester() 40 | .setDefault(ClassPathEntry.class, new ClassPathEntry(Paths.get("foo", "bar.jar"))) 41 | .testConstructors(ClassFile.class, Visibility.PACKAGE); 42 | } 43 | 44 | @Test 45 | public void testEquality() { 46 | new EqualsTester() 47 | .addEqualityGroup( 48 | new ClassFile(new ClassPathEntry(Paths.get("foo", "bar.jar")), "com.test.Foo"), 49 | new ClassFile(new ClassPathEntry(Paths.get("foo", "bar.jar")), "com.test.Foo")) 50 | .addEqualityGroup( 51 | new ClassFile(new ClassPathEntry(Paths.get("abc", "bar.jar")), "com.test.Foo")) 52 | .addEqualityGroup(new ClassFile(new ClassPathEntry(Paths.get("foo", "bar.jar")), "abc.Boo")) 53 | .testEquals(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/classpath/ClassSymbolTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.common.testing.EqualsTester; 22 | import com.google.common.testing.NullPointerTester; 23 | import com.google.common.testing.NullPointerTester.Visibility; 24 | import org.junit.Test; 25 | 26 | public class ClassSymbolTest { 27 | 28 | @Test 29 | public void testClassSymbolCreation() { 30 | ClassSymbol classSymbol = new ClassSymbol("java.lang.Object"); 31 | assertEquals("java.lang.Object", classSymbol.getClassBinaryName()); 32 | } 33 | 34 | @Test 35 | public void testNull() { 36 | new NullPointerTester().testConstructors(ClassSymbol.class, Visibility.PACKAGE); 37 | } 38 | 39 | @Test 40 | public void testClassSymbolEquality() { 41 | new EqualsTester() 42 | .addEqualityGroup(new ClassSymbol("java.lang.Object"), new ClassSymbol("java.lang.Object")) 43 | .addEqualityGroup(new ClassSymbol("java.lang.Long")) 44 | .addEqualityGroup(new SuperClassSymbol("java.lang.Object")) 45 | .addEqualityGroup( 46 | new MethodSymbol("java.lang.Object", "equals", "(Ljava/lang/Object;)Z", false)) 47 | .testEquals(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/classpath/ExcludedDependencyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.cloud.tools.opensource.dependencies.DependencyPath; 22 | import org.eclipse.aether.artifact.Artifact; 23 | import org.eclipse.aether.artifact.DefaultArtifact; 24 | import org.eclipse.aether.graph.Dependency; 25 | import org.junit.Test; 26 | 27 | public class ExcludedDependencyTest { 28 | 29 | @Test 30 | public void testToString() { 31 | Artifact root = new DefaultArtifact("a:b:1"); 32 | Artifact foo = new DefaultArtifact("com.google:foo:1"); 33 | Artifact bar = new DefaultArtifact("com.google:bar:1"); 34 | 35 | DependencyPath pathRootFooBar = 36 | new DependencyPath(root) 37 | .append(new Dependency(foo, "test", false)) 38 | .append(new Dependency(bar, "compile", true)); 39 | 40 | ExcludedDependency cause = new ExcludedDependency(pathRootFooBar, foo); 41 | 42 | assertEquals( 43 | "The valid symbol is in com.google:bar:jar:1 at a:b:jar:1 / " 44 | + "com.google:foo:1 (test) / com.google:bar:1 (compile, optional) " 45 | + "but it was not selected because com.google:foo:1 excludes com.google:bar.", 46 | cause.toString()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/classpath/FieldSymbolTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.common.testing.EqualsTester; 22 | import com.google.common.testing.NullPointerTester; 23 | import com.google.common.testing.NullPointerTester.Visibility; 24 | import org.junit.Test; 25 | 26 | public class FieldSymbolTest { 27 | 28 | @Test 29 | public void testFieldSymbolCreation() { 30 | FieldSymbol fieldSymbol = new FieldSymbol("java.lang.Integer", "MAX_VALUE", "I"); 31 | assertEquals("java.lang.Integer", fieldSymbol.getClassBinaryName()); 32 | assertEquals("MAX_VALUE", fieldSymbol.getName()); 33 | assertEquals("I", fieldSymbol.getDescriptor()); 34 | } 35 | 36 | @Test 37 | public void testNull() { 38 | new NullPointerTester().testConstructors(FieldSymbol.class, Visibility.PACKAGE); 39 | } 40 | 41 | @Test 42 | public void testFieldSymbolEquality() { 43 | new EqualsTester() 44 | .addEqualityGroup( 45 | new FieldSymbol("java.lang.Integer", "MAX_VALUE", "I"), 46 | new FieldSymbol("java.lang.Integer", "MAX_VALUE", "I")) 47 | .addEqualityGroup(new FieldSymbol("java.lang.Float", "MAX_VALUE", "I")) 48 | .addEqualityGroup(new FieldSymbol("java.lang.Integer", "MIN_VALUE", "I")) 49 | .addEqualityGroup(new FieldSymbol("java.lang.Integer", "MAX_VALUE", "F")) 50 | .addEqualityGroup(new MethodSymbol("java.lang.Integer", "MAX_VALUE", "(I)Lcom.Foo;", false)) 51 | .testEquals(); 52 | } 53 | 54 | @Test 55 | public void testToString() { 56 | FieldSymbol fieldSymbol = new FieldSymbol("java.lang.Integer", "MAX_VALUE", "I"); 57 | assertEquals("java.lang.Integer's field \"int MAX_VALUE\"", fieldSymbol.toString()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/classpath/LinkageCheckResultExceptionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import org.junit.Test; 22 | 23 | public class LinkageCheckResultExceptionTest { 24 | 25 | @Test 26 | public void testSingular() { 27 | LinkageCheckResultException exception = new LinkageCheckResultException(1); 28 | assertEquals("Found 1 linkage error", exception.getMessage()); 29 | } 30 | 31 | @Test 32 | public void testPlurla() { 33 | LinkageCheckResultException exception = new LinkageCheckResultException(2); 34 | assertEquals("Found 2 linkage errors", exception.getMessage()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/classpath/SuperClassSymbolTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.classpath; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.common.testing.EqualsTester; 22 | import com.google.common.testing.NullPointerTester; 23 | import com.google.common.testing.NullPointerTester.Visibility; 24 | import org.junit.Test; 25 | 26 | public class SuperClassSymbolTest { 27 | 28 | @Test 29 | public void testClassSymbolCreation() { 30 | SuperClassSymbol classSymbol = new SuperClassSymbol("java.lang.Object"); 31 | assertEquals("java.lang.Object", classSymbol.getClassBinaryName()); 32 | } 33 | 34 | @Test 35 | public void testNull() { 36 | new NullPointerTester().testConstructors(SuperClassSymbol.class, Visibility.PACKAGE); 37 | } 38 | 39 | @Test 40 | public void testClassSymbolEquality() { 41 | new EqualsTester() 42 | .addEqualityGroup( 43 | new SuperClassSymbol("java.lang.Object"), new SuperClassSymbol("java.lang.Object")) 44 | .addEqualityGroup(new SuperClassSymbol("java.lang.Long")) 45 | .addEqualityGroup(new ClassSymbol("java.lang.Object")) 46 | .addEqualityGroup( 47 | new MethodSymbol("java.lang.Object", "equals", "(Ljava/lang/Object;)Z", false)) 48 | .testEquals(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/dependencies/ArtifactsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.eclipse.aether.artifact.Artifact; 20 | import org.eclipse.aether.artifact.DefaultArtifact; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | 24 | public class ArtifactsTest { 25 | 26 | @Test 27 | public void testToCoordinates() { 28 | Artifact artifact = new DefaultArtifact("com.google.example:example:1.3.2"); 29 | Assert.assertEquals("com.google.example:example:1.3.2", Artifacts.toCoordinates(artifact)); 30 | } 31 | 32 | @Test 33 | public void testToCoordinates_withPackaging() { 34 | Artifact artifact = new DefaultArtifact("com.google.example", "example", "jar", "1.3.2"); 35 | Assert.assertEquals("com.google.example:example:1.3.2", Artifacts.toCoordinates(artifact)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/dependencies/DependencyGraphBuilderIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import com.google.common.collect.ImmutableList; 20 | import com.google.common.truth.Correspondence; 21 | import com.google.common.truth.Truth; 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.nio.file.Files; 25 | import org.eclipse.aether.artifact.Artifact; 26 | import org.eclipse.aether.artifact.DefaultArtifact; 27 | import org.junit.Test; 28 | 29 | public class DependencyGraphBuilderIntegrationTest { 30 | 31 | private Correspondence problemOnArtifact = 32 | Correspondence.transforming( 33 | (UnresolvableArtifactProblem problem) -> Artifacts.toCoordinates(problem.getArtifact()), 34 | "has artifact"); 35 | 36 | @Test 37 | public void testConfigureAdditionalMavenRepositories_notToUseMavenCentral() 38 | throws IOException { 39 | 40 | DependencyGraphBuilder graphBuilder = 41 | new DependencyGraphBuilder(ImmutableList.of("https://dl.google.com/dl/android/maven2")); 42 | 43 | File localRepository = Files.createTempDirectory(".m2").toFile(); 44 | localRepository.deleteOnExit(); 45 | 46 | graphBuilder.setLocalRepository(localRepository.toPath()); 47 | 48 | // This artifact does not exist in Android's repository 49 | Artifact artifact = new DefaultArtifact("com.google.guava:guava:15.0-rc1"); 50 | 51 | DependencyGraph result = graphBuilder.buildFullDependencyGraph(ImmutableList.of(artifact)); 52 | Truth.assertThat(result.getUnresolvedArtifacts()) 53 | .comparingElementsUsing(problemOnArtifact) 54 | .contains("com.google.guava:guava:15.0-rc1"); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/dependencies/FilteringZipDependencySelectorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import static org.junit.Assert.assertFalse; 20 | import static org.junit.Assert.assertSame; 21 | import static org.junit.Assert.assertTrue; 22 | 23 | import com.google.common.collect.ImmutableMap; 24 | import org.eclipse.aether.artifact.Artifact; 25 | import org.eclipse.aether.artifact.DefaultArtifact; 26 | import org.eclipse.aether.collection.DependencySelector; 27 | import org.eclipse.aether.graph.Dependency; 28 | import org.junit.Test; 29 | 30 | public class FilteringZipDependencySelectorTest { 31 | 32 | private final FilteringZipDependencySelector selector = new FilteringZipDependencySelector(); 33 | 34 | @Test 35 | public void testDeriveChildSelector() { 36 | DependencySelector derivedSelector = selector.deriveChildSelector(null); 37 | assertSame(selector, derivedSelector); 38 | } 39 | 40 | @Test 41 | public void testFilteringZip() { 42 | Artifact artifact = new DefaultArtifact("test:dummy:zip:1.0.0", ImmutableMap.of("type", "zip")); 43 | Dependency dependency = new Dependency(artifact, "compile"); 44 | assertFalse(selector.selectDependency(dependency)); 45 | } 46 | 47 | @Test 48 | public void testFilteringNonZip() { 49 | Artifact artifact = new DefaultArtifact("test", "dummy", "jar", "1.0.0"); 50 | Dependency dependency = new Dependency(artifact, "compile"); 51 | assertTrue(selector.selectDependency(dependency)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/dependencies/LevelOrderQueueItemTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import com.google.common.testing.EqualsTester; 20 | import org.eclipse.aether.artifact.Artifact; 21 | import org.eclipse.aether.artifact.DefaultArtifact; 22 | import org.eclipse.aether.graph.Dependency; 23 | import org.junit.Test; 24 | 25 | public class LevelOrderQueueItemTest { 26 | 27 | @Test 28 | public void testEquality() { 29 | Artifact foo = new DefaultArtifact("com.google:foo:1"); 30 | Artifact bar = new DefaultArtifact("com.google:bar:1"); 31 | DependencyPath path1 = new DependencyPath(null).append(new Dependency(foo, "compile")); 32 | DependencyPath path2 = 33 | new DependencyPath(null) 34 | .append(new Dependency(foo, "compile")) 35 | .append(new Dependency(bar, "compile")); 36 | 37 | new EqualsTester() 38 | .addEqualityGroup(new PathToNode<>(1, path1), new PathToNode<>(1, path1)) 39 | .addEqualityGroup(new PathToNode<>(1, path2)) 40 | .addEqualityGroup(new PathToNode<>(2, path2), new PathToNode<>(2, path2)) 41 | .testEquals(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dependencies/src/test/java/com/google/cloud/tools/opensource/dependencies/VersionComparatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.opensource.dependencies; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | public class VersionComparatorTest { 23 | 24 | private VersionComparator comparator = new VersionComparator(); 25 | 26 | @Test 27 | public void testGuava() { 28 | Assert.assertEquals(0, comparator.compare("20.0", "20.0")); 29 | Assert.assertTrue(comparator.compare("20.0", "10.0") > 0); 30 | Assert.assertTrue(comparator.compare("10.0", "20.0") < 0); 31 | Assert.assertTrue(comparator.compare("20.0.1", "20.0") > 0); 32 | Assert.assertTrue(comparator.compare("20.0.1", "20.0.0") > 0); 33 | Assert.assertTrue(comparator.compare("25.1-jre", "25.1-android") > 0); 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/duplicate-source-element.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/expected-exclusion-output-file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/reason.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Reactor's Trace Java 9 classes generate false positives 7 | 8 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/source-and-target.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/source-class.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/source-method.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/source-package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/target-field.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/target-method.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/target-package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/exclusion-sample-rules/target-with-namespace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/LICENSE_THIRDPARTY_BSD.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016, Google Inc. 2 | All rights reserved. 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/README.md: -------------------------------------------------------------------------------- 1 | # 3rd-party files used in tests 2 | 3 | This directory contains 3rd-party files used in the tests. 4 | 5 | ## Licenses 6 | 7 | The following files are under [Apache License 2.0](./LICENSE_THIRDPARTY_APACHE2.txt): 8 | 9 | - google-cloud-core-1.48.0.jar 10 | 11 | https://github.com/googleapis/google-cloud-java/blob/master/LICENSE 12 | - google-cloud-core-grpc-1.48.0.jar 13 | 14 | https://github.com/googleapis/google-cloud-java/blob/master/LICENSE 15 | - google-cloud-firestore-0.65.0-beta.jar 16 | 17 | https://github.com/googleapis/google-cloud-java/blob/master/LICENSE 18 | - google-cloud-firestore-0.66.0-beta.jar 19 | 20 | https://github.com/googleapis/google-cloud-java/blob/master/LICENSE 21 | - grpc-google-cloud-firestore-v1beta1-0.28.0.jar 22 | 23 | https://github.com/googleapis/google-cloud-java/blob/master/LICENSE 24 | - grpc-google-cloud-firestore-v1beta1-0.28.0_FirestoreGrpc.class 25 | 26 | https://github.com/googleapis/google-cloud-java/blob/master/LICENSE 27 | - guava-26.0-jre.jar 28 | 29 | https://github.com/google/guava/blob/master/COPYING 30 | 31 | 32 | The following files are under [BSD License](./LICENSE_THIRDPARTY_BSD.txt): 33 | 34 | - api-common-1.7.0.jar 35 | 36 | https://github.com/googleapis/api-common-java/blob/master/LICENSE 37 | - gax-1.32.0.jar 38 | 39 | https://github.com/googleapis/gax-java/blob/master/LICENSE 40 | 41 | -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/api-common-1.7.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/api-common-1.7.0.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/conscrypt-openjdk-uber-1.4.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/conscrypt-openjdk-uber-1.4.2.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/dummy-boot-inf-prefix.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/dummy-boot-inf-prefix.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/gax-1.32.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/gax-1.32.0.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/gax-1.48.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/gax-1.48.1.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/gax-grpc-1.38.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/gax-grpc-1.38.0.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/google-cloud-core-1.48.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/google-cloud-core-1.48.0.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/google-cloud-core-grpc-1.48.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/google-cloud-core-grpc-1.48.0.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/google-cloud-firestore-0.65.0-beta.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/google-cloud-firestore-0.65.0-beta.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/google-cloud-firestore-0.66.0-beta.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/google-cloud-firestore-0.66.0-beta.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/grpc-google-cloud-firestore-v1beta1-0.28.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/grpc-google-cloud-firestore-v1beta1-0.28.0.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/grpc-google-cloud-firestore-v1beta1-0.28.0_FirestoreGrpc.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/grpc-google-cloud-firestore-v1beta1-0.28.0_FirestoreGrpc.class -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/guava-23.5-jre.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/guava-23.5-jre.jar -------------------------------------------------------------------------------- /dependencies/src/test/resources/testdata/proto-google-cloud-firestore-v1beta1-0.28.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/dependencies/src/test/resources/testdata/proto-google-cloud-firestore-v1beta1-0.28.0.jar -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _site/ 2 | Gemfile.lock 3 | vendor/ 4 | .bundle/ 5 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | jlbp.dev -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'github-pages', group: :jekyll_plugins 3 | -------------------------------------------------------------------------------- /docs/JLBP-0002.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-2 4 | permalink: /JLBP-2 5 | --- 6 | # Minimize API surface 7 | 8 | Avoid exposing types from your dependencies. 9 | 10 | - Method arguments and return values from public methods should be standard Java 11 | types such as `java.time.LocalDate` or classes defined in the library itself, 12 | not third party types such as `org.joda.time.LocalDate`. 13 | 14 | - Your own public types should not be subclasses or implementations of types 15 | in third party libraries. 16 | 17 | - If a third party type on the surface of your API changes or is removed, 18 | you either have to break your own API or remain with an older, 19 | unsupported version of the library that is likely to cause diamond dependency 20 | problems. Historically this was a big problem for libraries that exposed Guava types 21 | such as `com.google.common.io.OutputSupplier` because Guava incremented major versions 22 | every 6 months. 23 | 24 | - A type you've exposed on your own API surface cannot be shaded. This removes 25 | one of the available techniques for resolving diamond dependency conflicts. 26 | 27 | Use package-protected classes and methods for internal APIs that should not be used by consumers. 28 | 29 | Do not mark methods and classes public by default. Assume non-public until a need is 30 | known.[1](#item15) 31 | 32 | Design for inheritance or prohibit it. That is, mark classes final unless there is a clear 33 | reason for them to be subclassed. Mark methods in non-final classes final unless they 34 | are meant to be overridden.[2](#item19) 35 | 36 | Prefer fewer packages over more packages to avoid 37 | unnecessarily publicizing internal details, 38 | since any dependency across package boundaries needs to be 39 | public. (We may revisit this when we can rely on 40 | the new module system in Java 11 or later.) 41 | 42 | If you absolutely must create public classes that clients should not depend on, 43 | one of the superpackages that contains these classes should be named `internal`. 44 | For example, `com.foo.utilities.internal.xml`. 45 | 46 | 1 Bloch, Joshua. "Item 15: Minimize the accessibility of classes and members." 47 | Effective Java, 3rd Edition. Boston: Addison-Wesley, 2018. p. 73[↩](#a1) 48 | 49 | 2 Bloch, Joshua. "Item 19: Design and document for inheritance or else 50 | prohibit it." Effective Java, 3rd Edition. Boston: Addison-Wesley, 2018. p. 93[↩](#a2) 51 | -------------------------------------------------------------------------------- /docs/JLBP-0004.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-4 4 | permalink: /JLBP-4 5 | --- 6 | # Avoid dependencies on unstable libraries and features 7 | 8 | Do not depend on libraries that are pre-1.0 or on unstable features in 9 | libraries that are 1.0 or later. 10 | Unstable libraries allow breaking changes to their 11 | public APIs within the same major version. For libraries following semantic 12 | versioning, this means libraries with a 0.x.y version. See [JLBP-3](JLBP-0003.md) 13 | for more details on semantic versioning. 14 | Unstable features within an otherwise stable library 15 | are marked with an annotation such as `@Beta`. See 16 | [JLBP-3](JLBP-0003.md) for more details on annotating unstable features. 17 | 18 | If your library depends on an unstable library or feature which 19 | experiences a breaking change between versions, your library is locked to 20 | a specific version of that dependency. 21 | If you expose the unstable feature on your library's surface, then your 22 | library's current major version is permanently locked to the version 23 | you initially exposed, and you cannot upgrade without making a 24 | breaking change to your users. 25 | If you only use the unstable feature in your implementation, then each minor 26 | or patch version of your library requires a very specific version of 27 | your dependency. It is unsafe for users to upgrade your library on its own, 28 | creating opportunities for hard-to-diagnose runtime conflicts. 29 | 30 | Depending on unstable features between submodules of a single library is 31 | acceptable, provided that users can easily force their build system to use 32 | compatible versions of the submodules. Some strategies for library owners 33 | include: 34 | 35 | - Using the same version number for all submodules in a library 36 | - Providing a [BOM](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies) 37 | -------------------------------------------------------------------------------- /docs/JLBP-0007.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-7 4 | permalink: /JLBP-7 5 | --- 6 | # Make breaking transitions easy 7 | 8 | When a library makes an in-place breaking change (meaning that the Java package 9 | is not renamed - see [JLBP-6](JLBP-0006.md) for more discussion on renaming rules), 10 | this can create a lot of work for consumers to adapt to the change. If a change 11 | is "atomic" (meaning that the old version of something like a method is removed 12 | at the same time the new version is added), all usages of the old method must be 13 | converted to the new method in a single change to each consumer's codebase. If 14 | the usage is widespread enough, and especially if usage spans packages by 15 | multiple owners and spans multiple levels of the dependency tree, the cost of 16 | transitioning may be too high to do at all. 17 | 18 | Consequently, libraries should instead make two-phase breaking changes to stable 19 | features: 20 | 21 | 1. Mark old methods/classes as `@Deprecated` at the same time as adding new 22 | methods/classes. This is a "stepping stone" release. 23 | 2. Delete the deprecated methods/classes. This should wait until major consumers 24 | have stopped using the deprecated functionality, where major consumers means 25 | consumers with high usage or consumers that are deep in the dependency tree. 26 | 27 | When a breaking change is introduced in two phases, consumers can adapt to the 28 | change in #1 incrementally. Then when they have completed the transition, 29 | adapting to #2 is trivial - upgrading to the version with the removed methods 30 | and classes shouldn't cause any build failures. The ideal breaking-change 31 | release would have *only* removals of deprecated features. 32 | 33 | The larger the number of places that use the old version's code, and the deeper 34 | in the tree that the library is used, the longer the time needs to be between #1 35 | and #2. Such a phase can even last years, depending on the release cadence of 36 | all the libraries and apps using the old code. 37 | 38 | As an example, OkHttp 1.6 was released to help users upgrade to OkHttp 2. 39 | OkHttp 1.6 added some new 2.0 APIs which enabled users to transition large code 40 | bases to the OkHttp 2 API (in 1.6) before flipping from OkHttp 1 to 41 | OkHttp 2.[1](#okh) 42 | 43 | 1Wilson, Jesse. [OkHttp 2.0](https://medium.com/square-corner-blog/okhttp-2-0-6da3fe12c879), Square Corner Blog, June 23, 2014[↩](#a1) 44 | -------------------------------------------------------------------------------- /docs/JLBP-0008.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-8 4 | permalink: /JLBP-8 5 | --- 6 | # Advance widely used functionality to a stable version 7 | 8 | Libraries at 0.x versions and unstable features (which should be marked with 9 | annotations if they live in a stable library, as outlined in 10 | [JLBP-3](JLBP-0003.md)) make no promises about stability. If they become widely 11 | used, they can cause problems when there are surface breakages (which is allowed 12 | per the rules of unstable functionality, explained in [JLBP-3](JLBP-0003.md)). If 13 | such breakages can cause widespread pain, the unstable features can become 14 | de facto GA. Promote widely-used unstable libraries and features to 1.0 15 | and commit to their APIs, even if the functionality is not complete. 16 | Stability is not about completeness but about guarantees not to break 17 | users' code frequently. 18 | 19 | If the surface needs to change before it stabilizes, follow the process in 20 | [JLBP-7](JLBP-0007.md) to minimize disruption to the ecosystem. (TL;DR: Mark the old 21 | surface `@Deprecated` and add the new surface in phase 1, delete the old surface 22 | in phase 2). However, if it would take a long time for the ecosystem to complete 23 | phase 2 (remove all references to the old surface), consider promoting the 24 | library or feature to stable before phase 2 is completed because there is more 25 | value to having a stable surface than there is to having a surface with zero 26 | deprecated methods. 27 | 28 | To avoid getting stuck in the first place, do not evangelize your pre-1.0 library 29 | or suggest that other teams and projects depend on it. 30 | 31 | - Be very clear with any teams and projects you work with that the library is unstable 32 | and should only be adopted if they are prepared to upgrade their own product regularly. 33 | - Add an [unstable or experimental badge](https://github.com/badges/stability-badges) 34 | to your Github `README.md`. 35 | - Consider not pushing a pre-1.0 artifact to the Central repository. 36 | 37 | Once the API is stable and has reached 1.0 is the time to seek customers, 38 | not before. 39 | -------------------------------------------------------------------------------- /docs/JLBP-0009.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-9 4 | permalink: /JLBP-9 5 | --- 6 | # Support the minimum Java version of your consumers 7 | 8 | Imagine that library B depends on library A and both work with Java 8. 9 | If library A releases a new version that requires Java 11, library B cannot upgrade 10 | to the new version of library A unless it also starts requiring Java 11. 11 | If library B is not able to do that—for instance because it must work in an environment 12 | such as App Engine that does not yet support Java 11—it must keep using the older 13 | version of library A, missing out on security and bug fixes in the newer version. 14 | 15 | Thus, libraries should not require a new minimum Java version until 16 | actively-maintained dependents already require that version of Java. 17 | It is rarely possible to wait for all dependents to upgrade. 18 | Some projects are abandoned or lightly maintained and may never upgrade. 19 | 20 | As an alternative, to support both dependents on the old version of 21 | Java and dependents wanting features provided by a newer version of Java, 22 | you can continue development in two forks, version N for the older version of 23 | Java and version N+1 for the newer version of Java. Typically in this case, 24 | the major version is incremented to distinguish the two versions. 25 | The Java package and Maven coordinates should be the same in the new major version. 26 | -------------------------------------------------------------------------------- /docs/JLBP-0011.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-11 4 | permalink: /JLBP-11 5 | --- 6 | # Keep dependencies up to date 7 | 8 | Release no later than 6 weeks after any of your dependencies 9 | releases a higher version. Time is important, not just how many versions behind, 10 | because a dependency tree that is up to date at each point in time is 11 | more likely to be internally consistent and compatible. 12 | Staying up to date is also important to ensure that security fixes are rolled 13 | out promptly. 14 | 15 | There are several tools that make upgrading dependencies easier by performing much of the grunt work: 16 | 17 | * The [Versions Maven Plugin](https://www.mojohaus.org/versions-maven-plugin/) 18 | can inform you of new versions of dependencies or rewrite a 19 | pom.xml to use the new versions. 20 | * [Renovate](https://renovate.whitesourcesoftware.com/) notices when a new 21 | version of a dependency is released and files a pull or merge request to 22 | update your repository. 23 | * GitHub's [Dependabot](https://dependabot.com/) creates pull requests to address security advisories and dependency upgrades. 24 | 25 | These tools assume that the new versions are compatible with the older versions. 26 | In cases where they're not fully compatible, a dependency upgrade can still require 27 | manual attention to rewrite and update affected code. However these tools do remove 28 | much of the pain from small updates. 29 | 30 | If your library does not have the investment necessary to keep up to date with 31 | dependencies, advise consumers to move to a library that is kept more up to 32 | date. 33 | 34 | Rarely a project will maintain multiple incompatible branches at the same time. 35 | For instance, Apache HttpClient 4.x and 5.x are both maintained and supported. 36 | They have different Maven artifact IDs and different Java packages. In this case, 37 | there's no need to update to the latest version if you prefer the older one. 38 | Either version is equally acceptable, though you do need to stay up-to-date 39 | within the branch you pick. 40 | -------------------------------------------------------------------------------- /docs/JLBP-0012.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-12 4 | permalink: /JLBP-12 5 | --- 6 | # Make level of support and API stability clear 7 | 8 | Document the lifecycle status and corresponding level of support 9 | of the library. Examples include: 10 | 11 | - Incubating: no support expected 12 | - Stable: SLOs in place to handle issues 13 | - Maintenance: only bugs will be addressed 14 | - Deprecated: critical bugs might be addressed for a limited period of time 15 | - Archived: no work is expected 16 | 17 | Clearly state the API and behavioral stability clients can expect from the 18 | library. For example you might say: 19 | 20 | - This API is stable and suitable for production use, aside from packages, 21 | classes, and methods marked internal or experimental. 22 | - This API is beta and will not experience an API or behavior breaking change 23 | unless a bug or design flaw is uncovered. 24 | - This API is in development. Anything may change at any time. Stable products 25 | should not depend on it. 26 | 27 | Provide and document a feedback mechanism. For example: 28 | 29 | - File an issue at https://github.com/... 30 | - Send email to dev@fooproject.example.com 31 | -------------------------------------------------------------------------------- /docs/JLBP-0013.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-13 4 | permalink: /JLBP-13 5 | --- 6 | # Remove references to deprecated features in dependencies at the first opportunity 7 | 8 | The earlier you remove usages of external deprecated functionality, the 9 | more versions of your product will work with your dependency once the 10 | deprecated features are fully deleted or hidden in the dependency. 11 | 12 | For example, api-common-java 1.6.0 refers to `Futures.transform(ListenableFuture, Function)` 13 | in Guava, which was deprecated in 19.0 and removed in 26.0. In 14 | api-common-java 1.7, the code was changed to instead call 15 | `Futures.transform(ListenableFuture, Function, Executor)`, 16 | which is not deprecated. The oldest version of api-common-java that 17 | can be used with Guava 26.0 or later is 1.7.0, because 1.6.0 and earlier 18 | refer to a deleted method. If api-common-java had moved to the new 19 | method even earlier (for example, if this had been done in 1.0.0), then 20 | more versions of api-common-java would be compatible with Guava 26.0 and 21 | later (1.0.0+ instead of 1.7.0+), making it easier to find compatible 22 | combinations of versions. 23 | 24 | This best practice refers to code that *uses* deprecated functionality from 25 | another library or the JDK, not to the deprecated functionality itself. 26 | It does not apply to usage of deprecated features within a library. 27 | -------------------------------------------------------------------------------- /docs/JLBP-0020.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-20 4 | permalink: /JLBP-20 5 | --- 6 | # Give each JAR file a module name 7 | 8 | For compatibility with the Java Platform Module System (JPMS) in Java 9 and 9 | later, every JAR file you publish should have a module name, even if the library 10 | does not itself use modules. More precisely, the JAR manifest in 11 | META-INF/MANIFEST.MF should have an Automatic-Module-Name field such as 12 | this one for `com.google.http-client:google-http-client`: 13 | 14 | ``` 15 | Automatic-Module-Name: com.google.api.client 16 | ``` 17 | 18 | The module name should be globally unique and composed of 19 | dot-separated Java identifiers. It should usually be a reversed domain name such 20 | as commonly found in Java package names. It should have the same name as the root 21 | package of the JAR file. For example, if a JAR file contains `com.google.utilities.i18n` 22 | and `com.google.utilities.strings` then `com.google.utilities` is a good 23 | choice for module name. However if there's a second artifact that contains 24 | `com.google.utilities.math` and `com.google.utilities.stats`, you can't choose 25 | the name `com.google.utilities` for both modules. 26 | 27 | Automatic-Module-Name is similar to the OSGI Bundle-SymbolicName and should 28 | probably have the same value as that field. 29 | 30 | To add an Automatic-Module-Name field to a JAR file using Maven, configure the 31 | Maven jar plugin in pom.xml like so: 32 | 33 | ```xml 34 | 35 | maven-jar-plugin 36 | 37 | 38 | 39 | com.google.api.client 40 | 41 | 42 | 43 | 44 | ``` 45 | 46 | To add an Automatic-Module-Name field using Gradle, add the following to 47 | build.gradle: 48 | 49 | ``` 50 | ext.moduleName = "com.google.api.client" 51 | 52 | jar { 53 | inputs.property("moduleName", moduleName) 54 | 55 | manifest { 56 | attributes 'Automatic-Module-Name': moduleName 57 | } 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/JLBP-0021.md: -------------------------------------------------------------------------------- 1 | --- 2 | jlbp: 3 | id: JLBP-21 4 | permalink: /JLBP-21 5 | --- 6 | # Upload artifacts to Maven Central 7 | 8 | Developers expect to find artifacts in [Maven 9 | Central](https://repo1.maven.org/maven2/). All artifacts intended for 10 | public consumption should be published in the [Maven Central repository 11 | maintained by Sonatype](https://search.maven.org). Even if a project is 12 | not built with Maven, its artifacts can and should be published to Maven 13 | Central. From here the artifacts are mirrored to many different local and public 14 | repositories. 15 | 16 | While Maven can download artifacts from repositories other than Maven Central, 17 | this requires extra configuration in the pom.xml or build.gradle files of 18 | projects that depend on these artifacts. Tools other than Maven itself 19 | that use the repository system do not always read this information from 20 | the pom.xml files and often cannot load artifacts that are not available 21 | in Maven Central. 22 | 23 | Developers who manually search for particular artifacts usually start at 24 | Maven Central and sometimes don't look elsewhere. 25 | 26 | Firewalls sometimes block access to Maven repositories. Access to Maven Central 27 | is either specifically allowed, or a local mirror of Maven Central is provided 28 | behind the firewall. However, these 29 | special arrangements are not normally in place for other repositories. 30 | Builds behind the firewall fail until the local developer convinces wary 31 | network administrators to open another hole in the firewall. 32 | 33 | Maven repositories also become unreachable from time to time, breaking builds. 34 | While this is true of all repositories incuding the central repository, almost all 35 | projects already depend on libraries they load from Maven Central. Publishing 36 | another artifact to Maven Central does not introduce an additional point of failure. 37 | Publishing an artifact to some other repository does. 38 | 39 | It is far more convenient for library consumers when the library and all its 40 | transitive dependencies are available in Maven Central. 41 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: 3 | title: Google Best Practices for Java Libraries 4 | permalink: / 5 | --- 6 | 7 | # Google Best Practices for Java Libraries 8 | 9 | Google Best Practices for Java Libraries are rules that minimize 10 | problems for consumers of interconnected Java libraries. These practices come 11 | from decades of aggregated experience in maintaining open source Java libraries 12 | and are informed by many hard-learned lessons from mistakes that have been 13 | made. We have found that following these rules results in higher quality 14 | Java libraries with fewer dependency conflicts and other kinds of problems. The 15 | list is open-ended, so new ones may be added from time to time. 16 | 17 | ## Best practices 18 | 19 | {% for p in site.pages %}{% if p.jlbp -%} 20 | - [{{ p.jlbp.id }}]({{ p.url | relative_url }}): {{ p.title }} 21 | {% endif %}{% endfor -%} 22 | 23 | ## Concepts 24 | 25 | {% for p in site.pages %}{% if p.concepts -%} 26 | - [{{ p.title}}]({{ p.url | relative_url }}) 27 | {% endif %}{% endfor -%} 28 | 29 | ## Reference 30 | 31 | - [Glossary](glossary.md): Terms used in the best practices and other places in 32 | cloud-opensource-java. 33 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | name: Google Best Practices for Java Libraries 2 | title: Google Best Practices for Java Libraries 3 | google_analytics: UA-43239122-3 4 | -------------------------------------------------------------------------------- /docs/_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {%- if page.jlbp %}[{{ page.jlbp.id }}] {% endif %}{{ page.title -}} 6 | 7 | 8 | 9 | 10 | {% seo %} 11 | 12 | 13 | {% if site.google_analytics and jekyll.environment == 'production' %} 14 | 22 | {% endif %} 23 | 24 | 25 |

29 | {% if page.jlbp %} 30 |

[{{ page.jlbp.id }}]

31 | {% endif %} 32 | {{ content }} 33 | 34 |
35 | 36 |
37 | {% if site.google_analytics %} 38 |

This site uses cookies from Google to deliver its services and to analyze traffic. Learn more

39 |

Privacy

40 | {% endif %} 41 |

42 | 44 | View on GitHub 45 |

46 |

Copyright 2019 Google LLC

47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /docs/assets/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Roboto, sans-serif; 3 | line-height: 1.15; 4 | font-size: 16pt; 5 | } 6 | 7 | h1 { 8 | font-family: Roboto, sans-serif; 9 | font-weight: lighter; 10 | font-size: 96pt; 11 | margin-bottom: 1ex; 12 | } 13 | 14 | .cloud-logo { 15 | height: 22px; 16 | margin-top: 20px; 17 | margin-bottom: 10px; 18 | } 19 | 20 | p, li { 21 | width: 40em; 22 | max-width: 90%; 23 | } 24 | 25 | footer p { 26 | margin: 0.15ex; 27 | } 28 | 29 | li { 30 | margin-top: 0.5ex; 31 | margin-bottom: 0.5ex; 32 | } 33 | 34 | @media only screen and (min-width : 1024px) { 35 | body { 36 | margin-left: 8em; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /docs/assets/images/ddc-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-00.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-01.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-02.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-03.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-04.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-05.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-06.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-00.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-01.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-02.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-03.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-04.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-05.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-compiler-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-compiler-06.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-00.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-01.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-02.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-03.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-04.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-05.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-06.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-07.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-07b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-07b.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-08.png -------------------------------------------------------------------------------- /docs/assets/images/ddc-resolution-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/assets/images/ddc-resolution-09.png -------------------------------------------------------------------------------- /docs/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/docs/favicon.png -------------------------------------------------------------------------------- /enforcer-rules/README.md: -------------------------------------------------------------------------------- 1 | # Linkage Checker Enforcer Rule 2 | 3 | Linkage Checker Enforcer Rule verifies that the transitive dependency tree of `pom.xml` does not have 4 | any [linkage errors](https://jlbp.dev/glossary.html#linkage-error). 5 | 6 | User documentation: [Linkage Checker Enforcer Rule]( 7 | https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-Enforcer-Rule) 8 | 9 | # Debug 10 | 11 | For developers to debug the enforcer rule implementation, set the `MAVEN_OPTS` environment variable 12 | to wait for debuggers (`suspend=y`) before running `mvn` command. 13 | 14 | ``` 15 | $ export MAVEN_OPTS='-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005' 16 | $ mvn verify 17 | Listening for transport dt_socket at address: 5005 18 | ``` 19 | 20 | When you debug one of the integration tests in the "src/it" directory, check the 21 | `build.log` files in the `enforcer-rules/target/it` directory (run 22 | `find enforcer-rules -name 'build.log'`). 23 | The file is used in verification scripts and usually contains build errors. 24 | 25 | If you want to attach a debugger, use the following command to specify the test 26 | case and to provide the debug parameter to Maven invoker plugin. 27 | 28 | ``` 29 | mvn install -Dmaven.test.skip -Dinvoker.test=bom-project-using-spring-repository \ 30 | -Dinvoker.mavenOpts='-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005' 31 | ``` 32 | 33 | Then run remote debug to the port (5005) via your IDE. 34 | -------------------------------------------------------------------------------- /enforcer-rules/kokoro/release_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands to stderr. 6 | set -x 7 | 8 | cd github/cloud-opensource-java 9 | # 'Enforcer-rules' needs to be built with 'dependencies' (without 'boms') 10 | mvn -V -pl 'dependencies,enforcer-rules' -Prelease -B -U verify 11 | cd enforcer-rules 12 | 13 | # copy pom with the name expected in the Maven repository 14 | ARTIFACT_ID=$(mvn -B help:evaluate -Dexpression=project.artifactId 2>/dev/null | grep -v "^\[") 15 | PROJECT_VERSION=$(mvn -B help:evaluate -Dexpression=project.version 2>/dev/null| grep -v "^\[") 16 | cp pom.xml target/${ARTIFACT_ID}-${PROJECT_VERSION}.pom 17 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/abstract-method-errors/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/abstract-method-errors/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('''\ 4 | com.google.api.gax.grpc.InstantiatingGrpcChannelProvider (in com.google.api:gax-grpc:1.38.0) does not implement com.google.api.gax.rpc.TransportChannelProvider withCredentials(com.google.auth.Credentials), required by com.google.api.gax.rpc.TransportChannelProvider (in com.google.api:gax:1.48.0) 5 | Cause: 6 | Dependency conflict: com.google.api:gax:1.48.0 defines incompatible version of com.google.api.gax.rpc.TransportChannelProvider but com.google.api:gax:1.38.0 defines compatible one. 7 | selected: com.google.cloud.tools.opensource:abstract-method-error-example:jar:1.0-SNAPSHOT / com.google.api:gax:1.48.0 (compile) 8 | unselected: com.google.cloud.tools.opensource:abstract-method-error-example:jar:1.0-SNAPSHOT / com.google.api:gax-grpc:1.38.0 (compile) / com.google.api:gax:1.38.0 (compile)''') 9 | 10 | 11 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-error/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-error/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('''\ 4 | [ERROR] Linkage Checker rule found 1 error: 5 | (com.google.guava:guava:20.0) com.google.common.base.Verify's method "void verify(boolean, String, Object)" is not found; 6 | referenced by 3 class files 7 | io.grpc.internal.ServiceConfigInterceptor (io.grpc:grpc-core:1.17.1) 8 | io.grpc.internal.JndiResourceResolverFactory (io.grpc:grpc-core:1.17.1) 9 | io.grpc.internal.DnsNameResolver (io.grpc:grpc-core:1.17.1) 10 | Cause: 11 | Dependency conflict: com.google.guava:guava:20.0 does not define com.google.common.base.Verify's method "void verify(boolean, String, Object)" but com.google.guava:guava:26.0-android defines it. 12 | selected: com.google.api-client:google-api-client:1.27.0 (compile) / com.google.guava:guava:20.0 (compile) 13 | unselected: io.grpc:grpc-core:1.17.1 (compile) / com.google.guava:guava:26.0-android (compile) 14 | ''') 15 | 16 | assert buildLog.contains('''Problematic artifacts in the dependency tree: 17 | com.google.guava:guava:20.0 is at: 18 | com.google.api-client:google-api-client:1.27.0 (compile) / com.google.guava:guava:20.0 (compile) 19 | and 3 other dependency paths. 20 | io.grpc:grpc-core:1.17.1 is at: 21 | io.grpc:grpc-core:1.17.1 (compile) 22 | '''); 23 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-no-error/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=success 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-no-error/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log") 2 | 3 | assert buildLog.text.contains("No reachable error found") 4 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-no-packaging/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=success 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-no-packaging/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log") 2 | 3 | assert buildLog.text.contains("[WARNING] A BOM should have packaging pom") 4 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-using-spring-repository/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify -Pspring 2 | 3 | # The artifacts in reactor-bom have linkage errors. 4 | invoker.buildResult=failure 5 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/bom-project-using-spring-repository/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log") 2 | 3 | // Profile "spring" should set the Spring Milestones repository, which has this reactor-bom. 4 | assert !buildLog.text.contains( 5 | "Could not find artifact io.projectreactor:reactor-bom:pom:2020.0.0-M2 in central") 6 | 7 | // io.projectreactor.netty:reactor-netty:jar:1.0.0-M2 is in the reactor-bom. It's available in 8 | // Spring Milestones repository: 9 | // https://repo.spring.io/milestone/io/projectreactor/netty/reactor-netty/1.0.0-M2/ 10 | assert !buildLog.text.contains( 11 | "io.projectreactor.netty:reactor-netty:jar:1.0.0-M2 was not resolved") 12 | 13 | assert !buildLog.text.contains("NullPointerException") 14 | 15 | // 4 linkage errors are references to java.util.concurrent.Flow class, which does not exist in 16 | // Java 8 runtime yet. 17 | def expectedErrorCount = System.getProperty("java.version").startsWith("1.8.") ? 111 : 108 18 | 19 | assert buildLog.text.contains("Linkage Checker rule found $expectedErrorCount errors:") 20 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/fail-build-for-linkage-errors/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/fail-build-for-linkage-errors/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('''\ 4 | (com.google.guava:guava:20.0) com.google.common.base.Verify's method "void verify(boolean, String, Object)" is not found; 5 | referenced by 3 class files 6 | io.grpc.internal.ServiceConfigInterceptor (io.grpc:grpc-core:1.17.1) 7 | io.grpc.internal.JndiResourceResolverFactory (io.grpc:grpc-core:1.17.1) 8 | io.grpc.internal.DnsNameResolver (io.grpc:grpc-core:1.17.1) 9 | Cause: 10 | Dependency conflict: com.google.guava:guava:20.0 does not define com.google.common.base.Verify's method "void verify(boolean, String, Object)" but com.google.guava:guava:26.0-android defines it. 11 | selected: com.google.cloud.tools.opensource:test-no-such-method-error-example:jar:1.0-SNAPSHOT / com.google.api-client:google-api-client:1.27.0 (compile) / com.google.guava:guava:20.0 (compile) 12 | unselected: com.google.cloud.tools.opensource:test-no-such-method-error-example:jar:1.0-SNAPSHOT / io.grpc:grpc-core:1.17.1 (compile) / com.google.guava:guava:26.0-android (compile) 13 | ''') 14 | 15 | assert buildLog.contains('''\ 16 | Problematic artifacts in the dependency tree: 17 | com.google.guava:guava:20.0 is at: 18 | com.google.cloud.tools.opensource:test-no-such-method-error-example:jar:1.0-SNAPSHOT \ 19 | / com.google.api-client:google-api-client:1.27.0 (compile) \ 20 | / com.google.guava:guava:20.0 (compile) 21 | io.grpc:grpc-core:1.17.1 is at: 22 | com.google.cloud.tools.opensource:test-no-such-method-error-example:jar:1.0-SNAPSHOT \ 23 | / io.grpc:grpc-core:1.17.1 (compile) 24 | ''') 25 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/inaccessible-class-error/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/inaccessible-class-error/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('''\ 4 | (io.grpc:grpc-core:0.15.0) Class io.grpc.internal.SingleTransportChannel has default access; 5 | referenced by 1 class file in a different package 6 | io.grpc.grpclb.GrpclbLoadBalancer (io.grpc:grpc-grpclb:0.12.0)''') 7 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/missing-filter-file-error/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/missing-filter-file-error/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log") 2 | 3 | assert buildLog.text.contains("NoSuchFileException: no-such-file.xml") 4 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/report-only-reachable-bom/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/report-only-reachable-bom/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('''\ 4 | (io.opencensus:opencensus-api:0.28.1) Class io.opencensus.trace.unsafe.ContextUtils has default access; 5 | referenced by 2 class files in a different package 6 | io.grpc.census.CensusTracingModule (io.grpc:grpc-census:1.35.0) 7 | io.grpc.testing.integration.AbstractInteropTest (io.grpc:grpc-interop-testing:1.35.0) 8 | ''') 9 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/report-only-reachable/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/report-only-reachable/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('''\ 4 | (com.google.guava:guava:20.0) com.google.common.base.Verify's method "void verify(boolean, String, Object)" is not found; 5 | referenced by 3 class files 6 | io.grpc.internal.ServiceConfigInterceptor (io.grpc:grpc-core:1.17.1) 7 | io.grpc.internal.JndiResourceResolverFactory (io.grpc:grpc-core:1.17.1) 8 | io.grpc.internal.DnsNameResolver (io.grpc:grpc-core:1.17.1) 9 | Cause: 10 | Dependency conflict: com.google.guava:guava:20.0 does not define com.google.common.base.Verify's method "void verify(boolean, String, Object)" but com.google.guava:guava:26.0-android defines it. 11 | selected: com.google.cloud.tools.opensource:test-report-only-reachable:jar:1.0-SNAPSHOT / com.google.api-client:google-api-client:1.27.0 (compile) / com.google.guava:guava:20.0 (compile) 12 | unselected: com.google.cloud.tools.opensource:test-report-only-reachable:jar:1.0-SNAPSHOT / io.grpc:grpc-core:1.17.1 (compile) / com.google.guava:guava:26.0-android (compile) 13 | ''') 14 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/return-type-mismatch/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=failure 3 | invoker.java.version=1.8 -------------------------------------------------------------------------------- /enforcer-rules/src/it/return-type-mismatch/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | // protobuf-java 3.12.4 has wrong reference to ByteBuffer's methods that are unavailable in Java 8. 4 | // In this message below, the expectation is wrong. 5 | println(buildLog) 6 | assert buildLog.contains('''\ 7 | java.nio.ByteBuffer's method "java.nio.ByteBuffer position(int)" is expected to return java.nio.ByteBuffer\ 8 | but instead returns java.nio.Buffer; 9 | referenced by 8 class files 10 | com.google.protobuf.AllocatedBuffer (com.google.protobuf:protobuf-java:3.12.4) 11 | com.google.protobuf.BinaryWriter (com.google.protobuf:protobuf-java:3.12.4) 12 | com.google.protobuf.ByteBufferWriter (com.google.protobuf:protobuf-java:3.12.4) 13 | com.google.protobuf.CodedInputStream (com.google.protobuf:protobuf-java:3.12.4) 14 | com.google.protobuf.CodedOutputStream (com.google.protobuf:protobuf-java:3.12.4) 15 | com.google.protobuf.IterableByteBufferInputStream (com.google.protobuf:protobuf-java:3.12.4) 16 | com.google.protobuf.NioByteString (com.google.protobuf:protobuf-java:3.12.4) 17 | com.google.protobuf.Utf8 (com.google.protobuf:protobuf-java:3.12.4)''') -------------------------------------------------------------------------------- /enforcer-rules/src/it/test-scope/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=success 3 | invoker.java.version=1.8 -------------------------------------------------------------------------------- /enforcer-rules/src/it/test-scope/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log").text.replaceAll("\\r\\n", "\n") 2 | 3 | assert buildLog.contains('No reachable error found') -------------------------------------------------------------------------------- /enforcer-rules/src/it/war-project-private-modifier/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=verify 2 | invoker.buildResult=success 3 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/war-project-private-modifier/src/main/java/com.google.example/Dummy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.example; 18 | 19 | class Dummy { 20 | private int privateField = 0; 21 | 22 | private int privateMethod() { 23 | return 1; 24 | } 25 | 26 | public static void main(String[] arguments) { 27 | Dummy dummy = new Dummy(); 28 | int sum = dummy.privateField + dummy.privateMethod(); 29 | System.out.println(sum); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /enforcer-rules/src/it/war-project-private-modifier/verify.groovy: -------------------------------------------------------------------------------- 1 | def buildLog = new File(basedir, "build.log") 2 | 3 | assert buildLog.text.contains("No error found") 4 | -------------------------------------------------------------------------------- /enforcer-rules/src/test/resources/appengine-exclusion.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /enforcer-rules/src/test/resources/dummy-0.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/enforcer-rules/src/test/resources/dummy-0.0.1.jar -------------------------------------------------------------------------------- /example-problems/README.md: -------------------------------------------------------------------------------- 1 | # Example Problems 2 | 3 | This directory contains Maven projects that demonstrate runtime errors 4 | caused by missing names in the classpath. 5 | 6 | - [NoSuchMethodError due to signature mismatch](no-such-method-error-signature-mismatch/README.md) 7 | - [NoSuchMethodError due to failure to list or shade external dependencies](appengine-api-sdk/README.md) 8 | -------------------------------------------------------------------------------- /example-problems/appengine-api-sdk/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | com.google.cloud.tools.examples 7 | appengineapisdkexample 8 | 0.0.1-SNAPSHOT 9 | appengineapisdkexample 10 | 11 | 12 | UTF-8 13 | 1.8 14 | 1.8 15 | 16 | 17 | 18 | 19 | com.google.appengine 20 | appengine-api-1.0-sdk 21 | 1.9.71 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.codehaus.mojo 29 | exec-maven-plugin 30 | 1.6.0 31 | 32 | com.google.cloud.tools.examples.AppEngineApiSdkExample 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /example-problems/appengine-api-sdk/src/main/java/com/google/cloud/tools/examples/AppEngineApiSdkExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.examples; 18 | 19 | import com.google.protos.cloud.sql.SqlService; 20 | import com.google.protos.cloud.sql.SqlService.ServerInterface; 21 | 22 | public class AppEngineApiSdkExample { 23 | 24 | public static void main(String[] args) { 25 | ServerInterface impl = null; 26 | SqlService.newService(impl); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /example-problems/gradle-project/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | plugins { 17 | id "java" 18 | id "com.google.cloud.tools.linkagechecker" version "1.5.10" 19 | } 20 | 21 | repositories { 22 | mavenCentral() 23 | } 24 | 25 | dependencies { 26 | compile 'com.google.cloud:google-cloud-logging:1.101.1' 27 | compile 'io.grpc:grpc-core:1.29.0' 28 | } 29 | 30 | linkageChecker { 31 | configurations = ['compile'] 32 | reportOnlyReachable = true 33 | } 34 | linkageCheck.dependsOn('build') 35 | 36 | -------------------------------------------------------------------------------- /example-problems/gradle-project/build/classes/java/main/App.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/example-problems/gradle-project/build/classes/java/main/App.class -------------------------------------------------------------------------------- /example-problems/gradle-project/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import com.google.common.collect.ImmutableList; 18 | 19 | public class App { 20 | 21 | public static void main(String[] arguments) { 22 | ImmutableList list = ImmutableList.of("hello"); 23 | System.out.println(list); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example-problems/no-such-method-error-signature-mismatch/src/main/java/io/grpc/internal/App.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.grpc.internal; 18 | 19 | import com.google.common.collect.ImmutableList; 20 | import com.google.common.collect.ImmutableMap; 21 | import java.util.Map; 22 | import java.util.Random; 23 | 24 | public class App { 25 | 26 | public static void main(String[] args) { 27 | Map choice = ImmutableMap.of("clientLanguage", ImmutableList.of("en")); 28 | 29 | // Throws java.lang.NoSuchMethodError when Guava 20.0 is in the class path: 30 | // com.google.common.base.Verify.verify(ZLjava/lang/String;Ljava/lang/Object;)V 31 | DnsNameResolver.maybeChooseServiceConfig(choice, new Random(), "localhost"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gradle-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Linkage Checker Gradle Plugin 2 | 3 | For usage of this plugin, see [the plugin documentation]( 4 | https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-with-Gradle). 5 | 6 | # Build Instruction 7 | 8 | This Gradle project depends on the `dependencies` module through the local Maven repository. 9 | 10 | At the root of the cloud-opensource-java project, first install the Maven projects to the local 11 | Maven repository: 12 | 13 | ``` 14 | $ mvn install 15 | ``` 16 | 17 | Then build this Gradle project: 18 | 19 | ``` 20 | $ cd gradle-plugin 21 | $ ./gradlew build publishToMavenLocal 22 | ``` 23 | 24 | This command installs the Linkage Checker Gradle plugin in the local Maven repository. 25 | 26 | ``` 27 | suztomo-macbookpro44% ls ~/.m2/repository/com/google/cloud/tools/linkage-checker-gradle-plugin/0.1.0-SNAPSHOT/ 28 | linkage-checker-gradle-plugin-0.1.0-SNAPSHOT.jar 29 | linkage-checker-gradle-plugin-0.1.0-SNAPSHOT.pom 30 | ``` 31 | 32 | ## Using the plugin in the local Maven repository 33 | 34 | To use the plugin that is installed in the local Maven repository, write the following code 35 | in your `settings.gradle`. 36 | 37 | ``` 38 | buildscript{ 39 | repositories { 40 | mavenLocal() 41 | 42 | dependencies{ 43 | classpath 'com.google.cloud.tools:linkage-checker-gradle-plugin:1.5.10-SNAPSHOT' 44 | } 45 | } 46 | } 47 | ``` 48 | 49 | If you do this, remove the version of the plugin in `build.gradle`; otherwise Gradle shows an error 50 | message to do so. 51 | 52 | # Debug 53 | 54 | ``` 55 | ./gradlew check --stacktrace -Dorg.gradle.debug=true --no-daemon 56 | ``` 57 | 58 | ## Debugging Functional Tests (src/functionalTest) 59 | 60 | To enable break points in the Groovy scripts in IntelliJ, install 'Spock Framework Enhancement'. 61 | 62 | To enable break points in the Java code of the Gradle plugin during the functional tests, add 63 | `-Dorg.gradle.testkit.debug=true` to the VM argument ( 64 | [Testing Build Logic with TestKit: Debugging build logic]( 65 | https://docs.gradle.org/current/userguide/test_kit.html#sub:test-kit-debug)). 66 | When you see IntelliJ has outdated class files, run `./gradlew build publishToMavenLocal` to 67 | reflect the latest code. 68 | -------------------------------------------------------------------------------- /gradle-plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | # scripts/prepare_release.sh maintains this value. 2 | version = 1.5.16-SNAPSHOT 3 | -------------------------------------------------------------------------------- /gradle-plugin/gradle/functional-test.gradle: -------------------------------------------------------------------------------- 1 | sourceSets { 2 | functionalTest { 3 | groovy.srcDir file('src/functionalTest/groovy') 4 | resources.srcDir file('src/functionalTest/resources') 5 | compileClasspath += sourceSets.main.output + configurations.testRuntime 6 | runtimeClasspath += output + compileClasspath 7 | } 8 | } 9 | 10 | configurations { 11 | functionalTestImplementation.extendsFrom testImplementation 12 | functionalTestRuntimeOnly.extendsFrom testRuntimeOnly 13 | } 14 | 15 | task functionalTest(type: Test) { 16 | description = 'Runs the functional tests.' 17 | group = 'verification' 18 | testClassesDirs = sourceSets.functionalTest.output.classesDirs 19 | classpath = sourceSets.functionalTest.runtimeClasspath 20 | mustRunAfter test 21 | } 22 | 23 | check.dependsOn functionalTest 24 | 25 | gradlePlugin { 26 | testSourceSets sourceSets.functionalTest 27 | } 28 | -------------------------------------------------------------------------------- /gradle-plugin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-opensource-java/6cac87c609e962057c002cd2bd916f77c800beb7/gradle-plugin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle-plugin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradle-plugin/kokoro/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o xtrace 5 | 6 | mkdir -p $HOME/.gradle 7 | export GRADLE_USER_HOME="$HOME/.gradle" 8 | readonly HOME_GRADLE_PROPERTY="$GRADLE_USER_HOME/gradle.properties" 9 | 10 | # Recommended way to store API key in 11 | # https://guides.gradle.org/publishing-plugins-to-gradle-plugin-portal/ 12 | # and go/yaqs/5342701566951424 for ISE check. 13 | echo -n 'gradle.publish.key=' >> $HOME_GRADLE_PROPERTY 14 | cat "${KOKORO_KEYSTORE_DIR}/72743_gradle_publish_key" >> $HOME_GRADLE_PROPERTY 15 | echo >> $HOME_GRADLE_PROPERTY 16 | echo -n 'gradle.publish.secret=' >> $HOME_GRADLE_PROPERTY 17 | cat "${KOKORO_KEYSTORE_DIR}/72743_gradle_publish_secret" >> $HOME_GRADLE_PROPERTY 18 | 19 | # The gradle plugin depends on the dependencies module 20 | cd github/cloud-opensource-java 21 | ./mvnw -V -B -ntp clean install 22 | 23 | cd gradle-plugin 24 | 25 | ./gradlew -v 26 | 27 | ./gradlew build 28 | 29 | ./gradlew publishPlugins --info --stacktrace 30 | -------------------------------------------------------------------------------- /gradle-plugin/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | rootProject.name = 'linkage-checker-gradle-plugin' -------------------------------------------------------------------------------- /gradle-plugin/src/main/java/com/google/cloud/tools/dependencies/gradle/LinkageCheckerPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.dependencies.gradle; 18 | 19 | import org.gradle.api.Plugin; 20 | import org.gradle.api.Project; 21 | 22 | /** 23 | * Gradle plugin to create a "linkageCheck" in a Gradle project. 24 | */ 25 | public class LinkageCheckerPlugin implements Plugin { 26 | @Override 27 | public void apply(Project project) { 28 | project.getExtensions().create("linkageChecker", LinkageCheckerPluginExtension.class); 29 | project.getTasks().create("linkageCheck", LinkageCheckTask.class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/java/com/google/cloud/tools/dependencies/gradle/LinkageCheckerPluginExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.dependencies.gradle; 18 | 19 | import com.google.common.collect.ImmutableSet; 20 | import java.util.List; 21 | 22 | /** 23 | * Properties to control the behavior of the Linkage Checker plugin. 24 | * 25 | *

TODO(suztomo): Implement real configuration as in go/jdd-gradle-plugin. 26 | */ 27 | public class LinkageCheckerPluginExtension { 28 | 29 | private boolean reportOnlyReachable = false; 30 | 31 | public boolean isReportOnlyReachable() { 32 | return reportOnlyReachable; 33 | } 34 | 35 | public void setReportOnlyReachable(boolean reportOnlyReachable) { 36 | this.reportOnlyReachable = reportOnlyReachable; 37 | } 38 | 39 | private ImmutableSet configurations = ImmutableSet.of(); 40 | 41 | public ImmutableSet getConfigurations() { 42 | return configurations; 43 | } 44 | 45 | public void setConfigurations(List configurationNames) { 46 | configurations = ImmutableSet.copyOf(configurationNames); 47 | } 48 | 49 | private String exclusionFile; 50 | 51 | public String getExclusionFile() { 52 | return exclusionFile; 53 | } 54 | 55 | public void setExclusionFile(String exclusionFile) { 56 | this.exclusionFile = exclusionFile; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /gradle-plugin/src/test/groovy/com/google/cloud/tools/dependencies/gradle/LinkageCheckerPluginTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.dependencies.gradle; 18 | 19 | import org.junit.Test 20 | import org.gradle.testfixtures.ProjectBuilder 21 | import org.gradle.api.Project 22 | import static org.junit.Assert.* 23 | 24 | class LinkageCheckerPluginTest { 25 | @Test 26 | public void linkage_checker_plugin_should_add_task_to_project() { 27 | Project project = ProjectBuilder.builder().build() 28 | project.getPlugins().apply 'com.google.cloud.tools.linkagechecker' 29 | 30 | assertTrue(project.tasks.linkageCheck instanceof LinkageCheckTask) 31 | } 32 | } -------------------------------------------------------------------------------- /kokoro/continuous.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | 3 | set JAVA_HOME=c:\program files\java\jdk1.8.0_211 4 | set PATH=%JAVA_HOME%\bin;%PATH% 5 | set MAVEN_OPTS="-Xmx12g" 6 | 7 | cd github/cloud-opensource-java 8 | 9 | call mvnw.cmd -V -B -ntp clean install javadoc:jar 10 | 11 | if %errorlevel% neq 0 exit /b %errorlevel% 12 | @echo on 13 | 14 | cd gradle-plugin 15 | call gradlew.bat build publishToMavenLocal 16 | 17 | exit /b %ERRORLEVEL% 18 | -------------------------------------------------------------------------------- /kokoro/continuous.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands being run. 6 | set -x 7 | 8 | export MAVEN_OPTS="-Xmx8g" 9 | 10 | cd github/cloud-opensource-java 11 | 12 | ./mvnw -V -B -X -ntp clean install -Djavadoc.skip 13 | 14 | cd gradle-plugin 15 | ./gradlew build publishToMavenLocal 16 | -------------------------------------------------------------------------------- /kokoro/gcp_windows/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Location of the continuous build bash script in git. 4 | build_file: "cloud-opensource-java/kokoro/continuous.bat" 5 | -------------------------------------------------------------------------------- /kokoro/gcp_windows/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Location of the presubmit build bash script in git. 4 | build_file: "cloud-opensource-java/kokoro/continuous.bat" 5 | -------------------------------------------------------------------------------- /kokoro/parent_release_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands to stderr. 6 | set -x 7 | 8 | cd github/cloud-opensource-java 9 | 10 | # Build the project (excluding boms) to ensure validity of parent pom 11 | # The artifact is unused in this parent-pom build. 12 | ./mvnw -V -pl 'dependencies,enforcer-rules' -Prelease -B -ntp -U verify 13 | 14 | # copy pom with the name expected in the Maven repository 15 | ARTIFACT_ID=$(mvn -B help:evaluate -Dexpression=project.artifactId 2>/dev/null | grep -v "^\[") 16 | PROJECT_VERSION=$(mvn -B help:evaluate -Dexpression=project.version 2>/dev/null| grep -v "^\[") 17 | # This build is only for parent pom. Target directory is not automatically created. 18 | mkdir -p target 19 | cp pom.xml target/${ARTIFACT_ID}-${PROJECT_VERSION}.pom 20 | -------------------------------------------------------------------------------- /kokoro/ubuntu/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Location of the continuous build bash script in git. 4 | build_file: "cloud-opensource-java/kokoro/continuous.sh" 5 | -------------------------------------------------------------------------------- /kokoro/ubuntu/java8-incompatible-reference-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands being run. 6 | set -x 7 | 8 | cd github/cloud-opensource-java/dependencies 9 | mvn -V -B clean install 10 | 11 | mvn exec:java -e -Pjava8-incompatible-reference-check -------------------------------------------------------------------------------- /kokoro/ubuntu/linkage-monitor-gcs.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Location of the periodic build bash script in git. 4 | build_file: "cloud-opensource-java/kokoro/ubuntu/linkage-monitor-gcs.sh" 5 | 6 | action { 7 | define_artifacts { 8 | regex: "**/target/linkage-monitor-latest-all-deps.jar" 9 | strip_prefix: "github/cloud-opensource-java/linkage-monitor/target" 10 | fail_if_no_artifacts: true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /kokoro/ubuntu/linkage-monitor-gcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands being run. 6 | set -x 7 | 8 | cd github/cloud-opensource-java 9 | mvn -V -B clean install 10 | 11 | cd linkage-monitor/target 12 | # mv linkage-monitor-*-all-deps.jar linkage-monitor-latest-all-deps.jar 13 | -------------------------------------------------------------------------------- /kokoro/ubuntu/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Location of the periodic build bash script in git. 4 | build_file: "cloud-opensource-java/kokoro/ubuntu/periodic.sh" 5 | 6 | timeout_mins: 240 7 | 8 | action { 9 | define_artifacts { 10 | regex: "**/target/com.google.cloud/**" 11 | strip_prefix: "github/cloud-opensource-java/dashboard/target" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /kokoro/ubuntu/periodic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands being run. 6 | set -x 7 | 8 | cd github/cloud-opensource-java 9 | # No need to run tests 10 | ./mvnw -V -B -ntp clean install -DskipTests -Denforcer.skip -Dinvoker.skip 11 | 12 | # Running target of dashboard submodule 13 | # https://stackoverflow.com/questions/3459928/running-a-specific-maven-plugin-goal-from-the-command-line-in-a-sub-module-of-a/26448447#26448447 14 | # https://stackoverflow.com/questions/11091311/maven-execjava-goal-on-a-multi-module-project 15 | cd dashboard 16 | 17 | # For all versions available in Maven Central and local repository 18 | ../mvnw -V -B -ntp exec:java -Dexec.mainClass="com.google.cloud.tools.opensource.dashboard.DashboardMain" \ 19 | -Dexec.arguments="-a com.google.cloud:libraries-bom" 20 | 21 | ../mvnw -V -B -ntp exec:java -Dexec.mainClass="com.google.cloud.tools.opensource.dashboard.DashboardMain" \ 22 | -Dexec.arguments="-a com.google.cloud:gcp-lts-bom" 23 | -------------------------------------------------------------------------------- /kokoro/ubuntu/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Location of the presubmit build bash script in git. 4 | build_file: "cloud-opensource-java/kokoro/continuous.sh" 5 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-1.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-1 Minimize dependencies](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-1.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-10.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-10 Maintain API stability as long as needed for consumers](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-10.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-11.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-11 Stay up to date with compatible dependencies](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-11.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-12.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-12 Make level of support and API stability clear](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-12.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-13.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-13 Quickly remove references to deprecated features in dependencies](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-13.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-14.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-14 Do not use version ranges](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-14.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-15.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-15.html Produce a BOM for multi-module projects](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-15.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-16.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-16 Ensure upper version alignment of dependencies for consumers](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-16.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-17.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-17 Coordinate rollout of breaking changes](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-17.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-18.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-18 Only shade dependencies as a last resort](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-18.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-19.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-19 Place each package in only one module](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-19.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-2.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-2 Minimize API surface](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-2.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-20.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-20 Give each jar a module name](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-20.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-3.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-3 Use semantic versioning](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-3.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-4.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-4 Avoid dependencies on unstable libraries and features](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-4.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-5.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-5 Avoid dependencies that overlap classes with other dependencies](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-5.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-6.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-6 Rename artifacts and packages together](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-6.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-7.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-7 Make breaking transitions easy](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-7.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-8.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-8 Advance widely used functionality to a stable version](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-8.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/JLBP-9.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [JLBP-9 Support the minimum Java version of your consumers](https://googlecloudplatform.github.io/cloud-opensource-java/JLBP-9.html) 4 | -------------------------------------------------------------------------------- /library-best-practices/README.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [Java Library Best Practices](https://googlecloudplatform.github.io/cloud-opensource-java/) 4 | -------------------------------------------------------------------------------- /library-best-practices/glossary.md: -------------------------------------------------------------------------------- 1 | This page has moved to: 2 | 3 | - [Java Dependency Glossary](https://googlecloudplatform.github.io/cloud-opensource-java/glossary.html) 4 | -------------------------------------------------------------------------------- /linkage-monitor/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Linkage Monitor' 2 | description: 'Checks the compatibility of the library with the latest Libraries BOM' 3 | runs: 4 | using: "composite" 5 | steps: 6 | - name: Download Linkage Monitor uber JAR 7 | # scripts/release.sh updates the version part in the URL 8 | run: | 9 | curl --output /tmp/linkage-monitor.jar \ 10 | "https://storage.googleapis.com/cloud-opensource-java-linkage-monitor/linkage-monitor-1.5.16-SNAPSHOT-all-deps.jar" 11 | shell: bash 12 | - run: java -jar /tmp/linkage-monitor.jar com.google.cloud:libraries-bom 13 | shell: bash 14 | -------------------------------------------------------------------------------- /linkage-monitor/kokoro/release_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on any error. 4 | set -e 5 | # Display commands being run. 6 | set -x 7 | 8 | cd github/cloud-opensource-java 9 | 10 | # This generates linkage-monitor/target/linkage-monitor-X.Y.Z-all-deps.jar. The Kokoro build config 11 | # specifies this JAR to upload to GCS. 12 | mvn -V -B clean install 13 | -------------------------------------------------------------------------------- /linkage-monitor/src/main/java/com/google/cloud/tools/dependencies/linkagemonitor/PlaceholderConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.tools.dependencies.linkagemonitor; 18 | 19 | /** 20 | * Constants initialized at compile-time. 21 | */ 22 | class PlaceholderConstants { 23 | 24 | static final String FIRELOG_API_KEY = "@firelog.api.key@"; 25 | } 26 | -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/gax-bom/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.google.api 5 | gax-bom 6 | 1.60.2-SNAPSHOT 7 | pom 8 | GAX (Google Api eXtensions) for Java 9 | GAX BOM version 1.60.2-SNAPSHOT copied for Linkage Monitor test 10 | 11 | 12 | 13 | com.google.api 14 | gax 15 | 1.60.2-SNAPSHOT 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/linkage-monitor-artifacts-invalid-format.txt: -------------------------------------------------------------------------------- 1 | com.google.api:gax:1.0.0 2 | com.google.api:gax-grpc 3 | com.google.api:gax-httpjson:1.0.0 -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/linkage-monitor-artifacts-nonexistent-coordinates.txt: -------------------------------------------------------------------------------- 1 | com.google.api:gax-nonexistent-coordinates 2 | com.google.api:gax-grpc 3 | -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/linkage-monitor-artifacts-with-empty-line.txt: -------------------------------------------------------------------------------- 1 | 2 | com.google.api:gax:1.60.0-SNAPSHOT 3 | 4 | com.google.api:gax-grpc:1.60.0-SNAPSHOT 5 | 6 | com.google.api:gax-httpjson:0.77.0-SNAPSHOT -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/linkage-monitor-artifacts.txt: -------------------------------------------------------------------------------- 1 | com.google.api:gax:1.60.0-SNAPSHOT 2 | com.google.api:gax-grpc:1.60.0-SNAPSHOT 3 | com.google.api:gax-httpjson:0.77.0-SNAPSHOT -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | com.google.cloud.tools 8 | test-project 9 | pom 10 | 0.0.1-SNAPSHOT 11 | 12 | Test Project for LinkageMonitorTest 13 | 14 | 15 | -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/testsubproject/build/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | com.google.cloud.tools 8 | copy-of-test-subproject-in-build 9 | pom 10 | 0.0.1-SNAPSHOT 11 | 12 | Test Sub Project for LinkageMonitorTest 13 | 14 | 15 | -------------------------------------------------------------------------------- /linkage-monitor/src/test/resources/testproject/testsubproject/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | com.google.cloud.tools 8 | test-subproject 9 | pom 10 | 0.0.2-SNAPSHOT 11 | 12 | Test Sub Project for LinkageMonitorTest 13 | 14 | 15 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "ignorePaths": [ 6 | "example-problems/**", 7 | "enforcer-rules/src/it/**", 8 | "boms/convergence-check", 9 | "boms/cloud-lts-bom", 10 | "boms/cloud-oss-bom", 11 | "verboseTree-maven-plugin/src/it/**" 12 | ], 13 | "separateMajorMinor": false, 14 | "semanticCommits": true, 15 | "packageRules": [ 16 | { 17 | "packagePatterns": [ 18 | "^com.google.guava:" 19 | ], 20 | "versionScheme": "docker" 21 | }, 22 | { 23 | "packagePatterns": [ 24 | "^com.google.cloud:google-cloud-" 25 | ], 26 | "ignoreUnstable": false 27 | }, 28 | { 29 | "packagePatterns": [ 30 | "^com.google.cloud:libraries-bom", 31 | "^com.google.cloud.tools:dependencies", 32 | "^com.google.cloud.tools:linkage", 33 | "^com.google.cloud.tools.opensource" 34 | ], 35 | "enabled": false 36 | } 37 | ], 38 | "masterIssue": true, 39 | "masterIssueApproval": true 40 | } 41 | -------------------------------------------------------------------------------- /scripts/cancel_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash - 2 | # Usage: ./cancel_release.sh 3 | 4 | set -e 5 | 6 | EchoRed() { 7 | echo "$(tput setaf 1; tput bold)$1$(tput sgr0)" 8 | } 9 | EchoGreen() { 10 | echo "$(tput setaf 2; tput bold)$1$(tput sgr0)" 11 | } 12 | 13 | Die() { 14 | EchoRed "$1" 15 | exit 1 16 | } 17 | 18 | DieUsage() { 19 | Die "Usage: ./cancel_release.sh ]" 20 | } 21 | 22 | # Usage: CheckVersion 23 | CheckVersion() { 24 | [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z]+)?$ ]] || Die "Version: $1 not in ###.###.###[-XXX] format." 25 | } 26 | 27 | [ $# -ne 1 ] && DieUsage 28 | 29 | EchoGreen 'Cancelling release...' 30 | 31 | VERSION=$1 32 | CheckVersion ${VERSION} 33 | 34 | if [[ $(git status -uno --porcelain) ]]; then 35 | Die 'There are uncommitted changes.' 36 | fi 37 | 38 | git checkout master 39 | git branch -D ${VERSION}-bom 40 | git fetch --tags --force 41 | git tag -d v${VERSION}-bom 42 | git push origin :v${VERSION}-bom 43 | 44 | 45 | -------------------------------------------------------------------------------- /scripts/update_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash - 2 | # Usage: ./update_docs.sh 3 | 4 | set -e 5 | 6 | EchoRed() { 7 | echo "$(tput setaf 1; tput bold)$1$(tput sgr0)" 8 | } 9 | EchoGreen() { 10 | echo "$(tput setaf 2; tput bold)$1$(tput sgr0)" 11 | } 12 | 13 | Die() { 14 | EchoRed "$1" 15 | exit 1 16 | } 17 | 18 | DieUsage() { 19 | Die "Usage: ./release.sh []" 20 | } 21 | 22 | # Usage: CheckVersion 23 | CheckVersion() { 24 | [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z]+)?$ ]] || Die "Version: $1 not in ###.###.###[-XXX] format." 25 | } 26 | 27 | gcertstatus --quiet --check_ssh=false --check_remaining=10m \ 28 | || Die "Run gcert." 29 | 30 | OLDVERSION=$1 31 | CheckVersion ${OLDVERSION} 32 | 33 | NEWVERSION=$2 34 | CheckVersion ${NEWVERSION} 35 | 36 | # CITC client names can't contain periods 37 | citcclient="bom-docs-${NEWVERSION//\./_}" 38 | 39 | p4 g4d -f ${citcclient} 40 | clientdir="$(p4 g4d -- "${citcclient?}")" 41 | 42 | cd "${clientdir}" 43 | 44 | /google/src/head/depot/google3/devtools/scripts/replace_string "<version>${OLDVERSION}</version>" "<version>${NEWVERSION}</version>" 45 | /google/src/head/depot/google3/devtools/scripts/replace_string "<version>${OLDVERSION}</version>" "<version>${NEWVERSION}</version>" 46 | /google/src/head/depot/google3/devtools/scripts/replace_string "<version>${OLDVERSION}</version>" "<version>${NEWVERSION}</version>" 47 | 48 | 49 | -------------------------------------------------------------------------------- /temurin-install-testing/.gitignore: -------------------------------------------------------------------------------- 1 | *.tfstate.backup 2 | *.tfstate 3 | private.auto.tfvars 4 | .terraform/ 5 | .idea/ 6 | .terraform.lock.hcl 7 | .terraform.tfstate.lock.info 8 | -------------------------------------------------------------------------------- /temurin-install-testing/connect.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Copyright 2023 Google LLC 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | set -eo pipefail 19 | 20 | ZONE=$(terraform output -raw zone) 21 | PROJECT=$(terraform output -raw project) 22 | 23 | echo "" 24 | echo "Once connection is complete, to see startup script logs in Linux:" 25 | echo " sudo journalctl -u google-startup-scripts.service" 26 | echo "To rerun startup script in Windows:" 27 | echo ' "C:\Program Files\Google\Compute Engine\metadata_scripts\run_startup_scripts.cmd"' 28 | 29 | gcloud compute ssh --project="$PROJECT" --zone="$ZONE" "$1" 30 | -------------------------------------------------------------------------------- /temurin-install-testing/inputs.auto.tfvars: -------------------------------------------------------------------------------- 1 | # Only enable one test category at a time to avoid hitting default compute quotas. 2 | enable_arm = false 3 | enable_windows = false 4 | enable_linux = false 5 | -------------------------------------------------------------------------------- /temurin-install-testing/outputs.tf: -------------------------------------------------------------------------------- 1 | output "zone" { 2 | value = var.zone 3 | } 4 | output "project" { 5 | value = var.project_id 6 | } 7 | output "bucket_folder" { 8 | value = local.bucket_folder 9 | } 10 | -------------------------------------------------------------------------------- /temurin-install-testing/test-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Copyright 2023 Google LLC 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | set -eo pipefail 19 | 20 | function wait { 21 | echo "$(date +%T) Sleeping 20 min" 22 | sleep 1200 23 | } 24 | 25 | terraform apply -var="enable_arm=true" -auto-approve 26 | wait 27 | BUCKET_FOLDER=$(terraform output --raw bucket_folder) 28 | terraform apply -auto-approve 29 | terraform apply -var="enable_linux=true" -var="bucket_folder=$BUCKET_FOLDER" -auto-approve 30 | # For single invocations: terraform apply -var="enable_linux=true" -auto-approve 31 | wait 32 | terraform apply -auto-approve 33 | terraform apply -var="enable_windows=true" -var="bucket_folder=$BUCKET_FOLDER" -auto-approve 34 | # For single invocations: terraform apply -var="enable_windows=true" -auto-approve 35 | wait 36 | terraform apply -auto-approve 37 | --------------------------------------------------------------------------------