diff --git a/build-support/release/rat_exclude_files.txt b/build-support/release/rat_exclude_files.txt index ea13868be1..298f28ce3d 100644 --- a/build-support/release/rat_exclude_files.txt +++ b/build-support/release/rat_exclude_files.txt @@ -10,6 +10,9 @@ pax_global_header version.txt build-support/release/rat_exclude_files.txt docs/support/doxygen/client_api.footer.in +java/gradlew +java/gradle/gradle-wrapper.jar +java/gradle/gradle-wrapper.properties java/kudu-flume-sink/src/test/avro/testAvroKuduOperationsProducer.avsc java/kudu-client/src/main/java/com/google/protobuf/ZeroCopyLiteralByteString.java java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduClient.java diff --git a/java/.gitignore b/java/.gitignore index fd62d76571..b418b4cf60 100644 --- a/java/.gitignore +++ b/java/.gitignore @@ -16,6 +16,7 @@ # under the License. # Eclipse files +.metadata/ .classpath .project .settings/ @@ -24,8 +25,13 @@ target/ dependency-reduced-pom.xml +# Gradle build artifacts +.gradle +build + # IntelliJ *.ipr *.iws *.iml .idea/ +classes diff --git a/java/README.md b/java/README.md index 8bd8b85e38..3b65f27726 100644 --- a/java/README.md +++ b/java/README.md @@ -25,7 +25,7 @@ Building the Client $ mvn package -DskipTests -The client jar will can then be found at kudu-client/target. +The client jar can then be found at kudu-client/target. Running the Tests ------------------------------------------------------------ @@ -135,3 +135,56 @@ likely a bug in maven-protoc-plugin. There's a simple workaround: delete the errant folder within Eclipse and refresh the kudu-client project. + +Building with Gradle +-------------------- + +As an experiment a Gradle build definition also exists. +In order to run the Gradle build you must install [Gradle|https://gradle.org/]. +If you would rather not install Gradle locally, you can use the +[Gradle Wrapper|https://docs.gradle.org/current/userguide/gradle_wrapper.html] +by replacing all references to gradle with gradlew. + +## Running a full build + +This will build all modules and run all "checks". + +$ gradle buildAll + +## Building the Client +$ gradle :kudu-client:assemble + +The client jar can then be found at kudu-client/build/libs. + +## Running the Tests +$ gradle test + +Integration tests, including tests which cover Hadoop integration, +may be run with: + +$ gradle integrationTest + +*Note:* Integration tests may depend on built Kudu binaries. + +## Building the Kudu-Spark integration + +Builds with Spark 2.x with Scala 2.11 (the default) or +Spark 1.x with Scala 2.10. + +$ gradle :kudu-spark:assemble +$ gradle :kudu-spark:assemble -PscalaVersions=2.10.6 + +## Installing to local maven repo + +$ gradle install + +## Clearing cached build state + +$ gradle clean + +## Discovering other tasks + +$ gradle tasks + + + diff --git a/java/build.gradle b/java/build.gradle new file mode 100755 index 0000000000..6bd21fc7c9 --- /dev/null +++ b/java/build.gradle @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file is the entry-point for the gradle build and contains +// common logic for the various subprojects in the build. + +// Load the buildscript file to apply dependencies needed for the gradle build itself. +buildscript { apply from: file("gradle/buildscript.gradle"), to: buildscript } + +// Plugins and scripts applied at the root level only, instead of per module. +apply plugin: "idea" +apply plugin: "eclipse" +apply from: "$rootDir/gradle/properties.gradle" +apply from: "$rootDir/gradle/dependencies.gradle" +apply from: "$rootDir/gradle/wrapper.gradle" + +subprojects { + // Plugins and scripts are applied in the natural "build order" + // they are used to ensure there are no dependency issues. + // These are common to all subprojects. However, subprojects may + // include their own plugins and scripts as well. + apply plugin: "java" + apply from: "$rootDir/gradle/scopes.gradle" + apply from: "$rootDir/gradle/compile.gradle" + apply from: "$rootDir/gradle/tests.gradle" + apply from: "$rootDir/gradle/quality.gradle" + apply from: "$rootDir/gradle/artifacts.gradle" + apply from: "$rootDir/gradle/publishing.gradle" + + repositories { + mavenCentral() + mavenLocal() + } +} \ No newline at end of file diff --git a/java/gradle.properties b/java/gradle.properties new file mode 100755 index 0000000000..2ad95e77d2 --- /dev/null +++ b/java/gradle.properties @@ -0,0 +1,41 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# This file contains project properties. +# More about how to use the gradle.properties file can be read here: +# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties + +group = org.apache.kudu +version = 1.5.0-SNAPSHOT +url = https://kudu.apache.org/ +scmUrl = git://git.apache.org/kudu.git +issueTrackerUrl = https://issues.apache.org/jira/projects/KUDU + +javaSourceCompatibility = 1.7 +encoding = UTF-8 + +# Maximum parallel forks to use while unit testing. +maxParallelForks = 1 + +# Flags to speed up the gradle build. +# https://docs.gradle.org/current/userguide/build_environment.html +org.gradle.daemon=true +# The below configurations are experimental but a nice performance boost. +# org.gradle.caching=true +# org.gradle.configureondemand=true +# org.gradle.parallel=true +# org.gradle.workers.max=4 \ No newline at end of file diff --git a/java/gradle/artifacts.gradle b/java/gradle/artifacts.gradle new file mode 100755 index 0000000000..69a74ab713 --- /dev/null +++ b/java/gradle/artifacts.gradle @@ -0,0 +1,57 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains common tasks and configuration for artifact generation. + +// Create a configuration so that the test jar can be referenced in other modules. +configurations.create("test") + +task testJar(type: Jar, dependsOn: testClasses, group: "Build") { + description = "Assembles a jar archive containing the test classes." + from sourceSets.test.output + classifier = "tests" + extension "jar" +} + +task sourcesJar(type: Jar, dependsOn: classes, group: "Build") { + description = "Assembles a jar archive containing the main source." + from sourceSets.main.allSource + classifier "sources" + extension "jar" +} + +task testSourcesJar(type: Jar, dependsOn: testJar, group: "Build") { + description = "Assembles a jar archive containing the test source." + from sourceSets.test.allSource + classifier "test-sources" + extension "jar" +} + +task javadocJar(type: Jar, dependsOn: javadoc, group: "Build") { + description = "Assembles a jar archive containing the javadoc." + from javadoc.destinationDir + classifier "javadoc" + extension "jar" +} + +artifacts { + test testJar + archives testJar + archives sourcesJar + archives testSourcesJar + archives javadocJar +} \ No newline at end of file diff --git a/java/gradle/buildscript.gradle b/java/gradle/buildscript.gradle new file mode 100644 index 0000000000..6f062f8e11 --- /dev/null +++ b/java/gradle/buildscript.gradle @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains the dependencies required for the gradle build itself. + +repositories { + mavenCentral() + jcenter() + maven { url "http://clojars.org/repo" } // Only used for the clojure plugin below. + maven { url "http://repo.spring.io/plugins-release" } // Only used for the propdeps plugin below. + maven { url "https://plugins.gradle.org/m2/" } +} + +// Manage plugin dependencies since the plugin block can't be used in included build scripts yet. +// For more details see: https://docs.gradle.org/current/userguide/plugins.html#plugins_dsl_limitations +dependencies { + classpath "com.commercehub.gradle.plugin:gradle-avro-plugin:0.9.0" + classpath "com.github.ben-manes:gradle-versions-plugin:0.15.0" + classpath "com.github.jengelman.gradle.plugins:shadow:2.0.1" + classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.1" + classpath "com.netflix.nebula:nebula-clojure-plugin:4.1.0" + classpath "io.spring.gradle:propdeps-plugin:0.0.9.RELEASE" +} \ No newline at end of file diff --git a/java/gradle/compile.gradle b/java/gradle/compile.gradle new file mode 100644 index 0000000000..823775af35 --- /dev/null +++ b/java/gradle/compile.gradle @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains common compiler configurations. + +// Java Configuration +tasks.withType(JavaCompile) { + sourceCompatibility = javaSourceCompatibility + options.encoding = encoding // make sure the encoding is defined by the project and not the system default. + options.incremental = true // enable incremental compilation. +} + +// Scala configuration +tasks.withType(ScalaCompile) { + sourceCompatibility = javaSourceCompatibility + scalaCompileOptions.encoding = encoding // make sure the encoding is defined by the project and not the system default. + scalaCompileOptions.additionalParameters = [ + // Emit warning and location for usages of features that should be imported explicitly. + "-feature", + // Emit various static analysis warnings. + "-Xlint" + ] +} \ No newline at end of file diff --git a/java/gradle/dependencies.gradle b/java/gradle/dependencies.gradle new file mode 100755 index 0000000000..f62015cc1e --- /dev/null +++ b/java/gradle/dependencies.gradle @@ -0,0 +1,105 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains all of the dependencies required for the build. +// Centrally locating all of the dependencies ensures each subproject +// uses the same dependency version for all dependencies used. + +ext { + versions = [:] + libs = [:] + // All supported scala versions. + scalaVersions = propertyWithDefault("scalaVersions", "2.11.8,2.10.6").split(",") +} + +versions += [ + async : "1.4.1", + avro : "1.8.1", + clojure : "1.8.0", + clojureToolsCli: "0.3.5", + commonsIo : "2.5", + findbugs : "3.0.1", + flume : "1.6.0", + gradle : "4.0.2", + guava : "20.0", + hadoop : "2.8.1", + hamcrest : "1.3", + jepsen : "0.1.3", + jsr305 : "3.0.2", + junit : "4.12", + log4j : "1.2.17", + mockito : "2.8.47", + murmur : "1.0.0", + netty : "3.10.6.Final", + pmd : "5.8.1", + protobuf : "3.3.0", + scalatest : "3.0.3", + slf4j : "1.7.25", + yetus : "0.5.0" +] + +// Log the Gradle version used vs defined. +if (gradle.gradleVersion != versions.gradle) { + println "Using gradle version $gradle.gradleVersion (Build defines $versions.gradle)" +} + +// Set the Scala version. +// The first Scala version in the scalaVersions list is the default. +versions["scala"] = scalaVersions.first() +// Add base Scala version +versions["scalaBase"] = versions.scala.substring(0, versions.scala.lastIndexOf(".")) + +// Set the Spark version based on the Scala version. +def spark1Version = "1.6.3" +def spark2Version = "2.1.1" +if ("$versions.scalaBase" == "2.10") { + versions["spark"] = spark1Version +} else { + versions["spark"] = spark2Version +} +versions["sparkBase"] = versions.spark.substring(0, versions.spark.indexOf(".")) +// Log for debugging +logger.info("Configuring Scala version: $versions.scala with Spark version: $versions.spark") + +libs += [ + async : "com.stumbleupon:async:$versions.async", + avro : "org.apache.avro:avro:$versions.avro", + clojure : "org.clojure:clojure:$versions.clojure", + clojureToolsCli : "org.clojure:tools.cli:$versions.clojureToolsCli", + commonsIo : "commons-io:commons-io:$versions.commonsIo", + flumeConfiguration: "org.apache.flume:flume-ng-configuration:$versions.flume", + flumeCore : "org.apache.flume:flume-ng-core:$versions.flume", + guava : "com.google.guava:guava:$versions.guava", + hadoopClient : "org.apache.hadoop:hadoop-client:$versions.hadoop", + hamcrestCore : "org.hamcrest:hamcrest-core:$versions.hamcrest", + jepsen : "jepsen:jepsen:$versions.jepsen", + jsr305 : "com.google.code.findbugs:jsr305:$versions.jsr305", + junit : "junit:junit:$versions.junit", + log4j : "log4j:log4j:$versions.log4j", + mockitoCore : "org.mockito:mockito-core:$versions.mockito", + murmur : "com.sangupta:murmur:$versions.murmur", + netty : "io.netty:netty:$versions.netty", + protobufJava : "com.google.protobuf:protobuf-java:$versions.protobuf", + protoc : "com.google.protobuf:protoc:$versions.protobuf", + scalaLibrary : "org.scala-lang:scala-library:$versions.scala", + scalatest : "org.scalatest:scalatest_$versions.scalaBase:$versions.scalatest", + slf4jApi : "org.slf4j:slf4j-api:$versions.slf4j", + slf4jLog4j12 : "org.slf4j:slf4j-log4j12:$versions.slf4j", + sparkCore : "org.apache.spark:spark-core_$versions.scalaBase:$versions.spark", + sparkSql : "org.apache.spark:spark-sql_$versions.scalaBase:$versions.spark", + yetusAnnotations : "org.apache.yetus:audience-annotations:$versions.yetus" +] \ No newline at end of file diff --git a/java/gradle/properties.gradle b/java/gradle/properties.gradle new file mode 100644 index 0000000000..1c89214f8b --- /dev/null +++ b/java/gradle/properties.gradle @@ -0,0 +1,53 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains methods to be used in the build to load and +// set build properties consistently. + +// ext makes these methods callable project wide +ext { + // A common method to handle loading gradle properties with a default when + // no definition is found. The property value is determined by the following + // priority order (top is highest priority): + // - gradle property (-Pproperty=value) + // - system property (-Dproperty=value) + // - default value + // See more details on gradle property handling here: + // https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties + propertyWithDefault = { property, defaultValue -> + def value = defaultValue + def systemValue = System.getProperty(property) + if (systemValue != null) { + value = systemValue + } + def projectValue = project.hasProperty(property) ? project.getProperty(property) : null + if (projectValue != null) { + value = projectValue + } + logger.info("Resolved property $property with final value $value " + + "[defaultValue=$defaultValue, systemValue=$systemValue, projectValue=$projectValue]") + return value + } + + // Returns true if the property has been set, otherwise false. + propertyExists = { property -> + if (System.getProperty(property) != null || project.hasProperty(property)) { + return true + } + return false + } +} \ No newline at end of file diff --git a/java/gradle/protobuf.gradle b/java/gradle/protobuf.gradle new file mode 100644 index 0000000000..f3d84bcfcc --- /dev/null +++ b/java/gradle/protobuf.gradle @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains the common protobuf plugin configuration. + +apply plugin: "com.google.protobuf" + +// Use the maven protoc artifact instead of local. +protobuf { + protoc { + artifact = libs.protoc + } +} + +// Configure Intellij to see the generated classes. +idea { + module { + generatedSourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java") + } +} \ No newline at end of file diff --git a/java/gradle/publishing.gradle b/java/gradle/publishing.gradle new file mode 100644 index 0000000000..5b3ba2e8ad --- /dev/null +++ b/java/gradle/publishing.gradle @@ -0,0 +1,62 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains common tasks and configuration for artifact publishing. + +apply plugin: "maven" +apply plugin: "signing" + +// Only sign artifacts if skipSigning is false, +// the version is not a snapshot, and we are uploading them to maven. +// This allows simplified builds and local maven installs. +def skipSigning = propertyExists("skipSigning") +def shouldSign = !skipSigning && !version.endsWith("SNAPSHOT") && project.gradle.startParameter.taskNames.any { it.contains("upload") } +def mavenUrl = propertyWithDefault("mavenUrl", "") +def mavenUsername = propertyWithDefault("mavenUsername", "") +def mavenPassword = propertyWithDefault("mavenPassword", "") + +uploadArchives { + repositories { + signing { + required { shouldSign } + sign configurations.archives + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + repository(url: "${mavenUrl}") { + authentication(userName: "${mavenUsername}", password: "${mavenPassword}") + } + } + } + } +} + +// Add the install task to the "Upload" group so it's visible in the tasks output. +install.group = "Upload" + +// Sort the generated maven dependencies to make pom comparisons easier. +tasks.withType(Upload) { + def installer = install.repositories.mavenInstaller + def deployer = uploadArchives.repositories.mavenDeployer + + [installer, deployer]*.pom*.whenConfigured { pom -> + pom.dependencies = pom.dependencies.sort { dep -> + "$dep.scope:$dep.optional:$dep.groupId:$dep.artifactId" + } + } +} + + diff --git a/java/gradle/quality.gradle b/java/gradle/quality.gradle new file mode 100644 index 0000000000..1f0759709c --- /dev/null +++ b/java/gradle/quality.gradle @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains common tasks and configuration for checking the quality of the code. + +apply plugin: "checkstyle" // Ensures Java code follows the defined coding style. +apply plugin: "findbugs" // Performs static code analysis to look for bugs in Java code. +apply plugin: "pmd" // Performs static code analysis to look for common code smells in Java code. +apply plugin: "com.github.ben-manes.versions" // Provides a task to determine which dependencies have updates. + +checkstyle { + configFile = file("$rootDir/kudu_style.xml") + configProperties = [ + "checkstyle.suppressions.file" : "$rootDir/checkstyle_suppressions.xml" + ] + ignoreFailures = true + showViolations = true +} + +// Create an aggregate checkstyle task. +// This simplifies running checkstyle on all the code by only needing one task instead of multiple in your command. +task checkstyle(dependsOn: [checkstyleMain, checkstyleTest, checkstyleIntegrationTest], group: "Verification") { + description = "Run Checkstyle analysis." +} + +findbugs { + toolVersion = versions.findbugs + ignoreFailures = true + effort = "max" +} + +tasks.withType(FindBugs) { + reports { + xml.enabled false + html.enabled true + } +} + +// Create an aggregate findbugs task. +// This simplifies running findbugs on all the code by only needing one task instead of multiple in your command. +task findbugs(dependsOn: [findbugsMain, findbugsTest, findbugsIntegrationTest], group: "Verification") { + description = "Run FindBugs analysis." +} + +pmd { + toolVersion = versions.pmd + ignoreFailures = true +} + +// Create an aggregate pmd task. +// This simplifies running pmd on all the code by only needing one task instead of multiple in your command. +task pmd(dependsOn: [pmdMain, pmdTest, pmdIntegrationTest], group: "Verification") { + description = "Run PMD analysis." +} + +// Configure the versions plugin to only show dependency updates for released versions. +dependencyUpdates { + revision = "release" + resolutionStrategy = { + componentSelection { rules -> + rules.all { ComponentSelection selection -> + boolean rejected = ["snap", "alpha", "beta", "rc", "cr", "m"].any { qualifier -> + selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/ + } + if (rejected) { + selection.reject("Release candidate") + } + } + } + } +} \ No newline at end of file diff --git a/java/gradle/scopes.gradle b/java/gradle/scopes.gradle new file mode 100644 index 0000000000..10bede3a3c --- /dev/null +++ b/java/gradle/scopes.gradle @@ -0,0 +1,23 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file adds provided scope and optional maven support. + +apply plugin: "propdeps" +apply plugin: "propdeps-eclipse" +apply plugin: "propdeps-idea" +apply plugin: "propdeps-maven" diff --git a/java/gradle/shadow.gradle b/java/gradle/shadow.gradle new file mode 100644 index 0000000000..3663cc7d3f --- /dev/null +++ b/java/gradle/shadow.gradle @@ -0,0 +1,110 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains tasks and configuration to support shading dependencies +// consistently when a subproject requires shaded artifacts. + +import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact + +apply plugin: "com.github.johnrengelman.shadow" + +tasks.remove(knows) // Remove "easter egg" knows task. +shadowJar.group = "" // Hide shadowJar task since it's used by the default build. + +// Configure a shaded jar to replace the default jar +shadowJar.classifier = null // Configure shadow jar to have the default classifier. +jar.finalizedBy(shadowJar) // Generate the shaded jar anytime the jar task is run. +jar.classifier = "unshaded" // Add an unshaded classifier to the default jar. + +// Add the shadowJar to the published artifacts. +artifacts { + archives shadowJar +} + +// Remove the unshaded jar from the published artifacts. +configurations.archives.artifacts.removeAll { + it instanceof ArchivePublishArtifact && it.archiveTask == jar +} + +// Ensure we always relocate these shaded dependencies to the same +// location across all modules. +shadowJar { + relocate "com.google.common", "org.apache.kudu.shaded.com.google.common" + relocate "com.google.protobuf", "org.apache.kudu.shaded.com.google.protobuf" + relocate "com.google.thirdparty", "org.apache.kudu.shaded.com.google.thirdparty" + relocate "com.sangupta", "org.apache.kudu.shaded.com.sangupta" + relocate "org.jboss.netty", "org.apache.kudu.shaded.org.jboss.netty" +} + +// ------------------------------------------------------------------ +// Everything below is a "hack" to support partial shading and +// accurate pom generation. At some point this logic should exist +// in the shadow plugin itself. +// ------------------------------------------------------------------ + +// Add a configuration to support unshaded compile dependencies. +// By default shadow assumes all dependencies are shaded. +configurations.create("compileUnshaded") +configurations.shadow.extendsFrom(configurations.compileUnshaded) +configurations.compile.extendsFrom(configurations.compileUnshaded) + +// Remove the shaded dependencies from the generated pom. +// This hack allows the project to support partially shaded jars, +// where the shadow plugin by default would remove all compile and runtime dependencies. +tasks.withType(Upload) { + def installer = install.repositories.mavenInstaller + def deployer = uploadArchives.repositories.mavenDeployer + + // Handle install and deploy in the same way. + [installer, deployer]*.pom*.whenConfigured { pom -> + def filter = shadowJar.getDependencyFilter() + def configs = shadowJar.getConfigurations() + + def shadowDependencies = configs.collectMany { + // Find all dependencies included in the shadow configuration. + it.resolvedConfiguration.firstLevelModuleDependencies.findAll { + filter.isIncluded(it) + } + } + + // Remove the shadow dependencies from the pom. + shadowDependencies.each { shaded -> + pom.dependencies.removeAll { dep -> + dep.groupId == shaded.getModuleGroup() && + dep.artifactId == shaded.getModuleName() && + dep.version == shaded.getModuleVersion() + } + } + + // Add the explicitly unshaded dependencies from the pom. + def unshadedDependencies = project.configurations.compileUnshaded.resolvedConfiguration.firstLevelModuleDependencies + unshadedDependencies.each { unshaded -> + // to avoid class loading problems + def dependency = pom.model.class.classLoader.loadClass("org.apache.maven.model.Dependency").newInstance() + dependency.setGroupId(unshaded.getModuleGroup()) + dependency.setArtifactId(unshaded.getModuleName()) + dependency.setVersion(unshaded.getModuleVersion()) + dependency.setScope("compile") + pom.dependencies.add(dependency) + } + + // Re-sort the generated maven dependencies to make pom comparisons easier. + pom.dependencies = pom.dependencies.sort { dep -> + "$dep.scope:$dep.optional:$dep.groupId:$dep.artifactId" + } + } +} \ No newline at end of file diff --git a/java/gradle/tests.gradle b/java/gradle/tests.gradle new file mode 100644 index 0000000000..01e3c0d6fb --- /dev/null +++ b/java/gradle/tests.gradle @@ -0,0 +1,80 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains common tasks and configuration for unit and integration tests. + +// Support parallel unit test execution. +test { + maxParallelForks = propertyWithDefault("maxParallelForks", "1").toInteger() +} + +// Log all test events. +tasks.withType(Test) { + testLogging { + events "passed", "skipped", "failed" + exceptionFormat = "full" + } +} + +// Adds pattern based integration test support. +// All test files matching the pattern "**/*IT*.java" will be run after the the other tests. +sourceSets { + test { + java { + exclude "**/*IT*.java" + } + } + integrationTest { + java { + srcDirs = ["src/test/java"] + include "**/*IT*.java" + } + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + } +} +plugins.withType(ScalaPlugin) { + sourceSets { + test { + scala { + exclude "**/*IT*.scala" + } + } + integrationTest { + scala { + srcDirs = ["src/test/scala"] + include "**/*IT*.scala" + } + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + } + } +} + +configurations { + integrationTestCompile.extendsFrom testCompile + integrationTestRuntime.extendsFrom testRuntime +} + +task integrationTest(type: Test, group: "Verification") { + description = "Runs the integration tests." + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath + maxParallelForks = 1 + mustRunAfter test +} +check.dependsOn(integrationTest) \ No newline at end of file diff --git a/java/gradle/wrapper.gradle b/java/gradle/wrapper.gradle new file mode 100644 index 0000000000..4efab86ef3 --- /dev/null +++ b/java/gradle/wrapper.gradle @@ -0,0 +1,64 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains tasks for the gradle wrapper generation. + +// Ensure the wrapper script is generated based on the version defined in the project +// and not the version installed on the machine running the task. +// Read more about the wrapper here: https://docs.gradle.org/current/userguide/gradle_wrapper.html +task wrapper(type: Wrapper) { + gradleVersion = versions.gradle +} + +// Custom task to inject support for downloading the gradle wrapper jar if it doesn't exist. +// This allows us to avoid checking in the jar to our repository. +task bootstrapWrapper() { + // In the doLast block so this runs when the task is called and not during project configuration. + doLast { + def wrapperJarPath = "\$APP_HOME/gradle/wrapper/gradle-wrapper.jar" + // Leverages the wrapper jar checked into the gradle project on github because the jar isn't available elsewhere. + def wrapperJarUrl = "https://raw.githubusercontent.com/gradle/gradle/v${versions.gradle}/gradle/wrapper/gradle-wrapper.jar" + + + def boostrapString = """ + if [[ ! -e $wrapperJarPath ]]; then + curl -o $wrapperJarPath $wrapperJarUrl + fi + """.stripIndent() + + def wrapperScript = file("$rootDir/gradlew") + def wrapperLines = wrapperScript.readLines() + wrapperScript.withPrintWriter { out -> + def bootstrapWritten = false + wrapperLines.each { line -> + // Print the wrapper bootstrap before the first usage of the wrapper jar. + if (!bootstrapWritten && line.contains("gradle-wrapper.jar")) { + out.println(boostrapString) + bootstrapWritten = true + } + out.println(line) + } + } + } +} +wrapper.finalizedBy bootstrapWrapper + +// Remove the generated batch file since we don't test building in the Windows environment. +task removeWindowScript(type: Delete) { + delete "$rootDir/gradlew.bat" +} +wrapper.finalizedBy removeWindowScript \ No newline at end of file diff --git a/java/gradle/wrapper/gradle-wrapper.properties b/java/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..fc47300fde --- /dev/null +++ b/java/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Aug 02 23:12:26 CDT 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-all.zip diff --git a/java/gradlew b/java/gradlew new file mode 100755 index 0000000000..93678fd1d6 --- /dev/null +++ b/java/gradlew @@ -0,0 +1,177 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + + +if [[ ! -e $APP_HOME/gradle/wrapper/gradle-wrapper.jar ]]; then + curl -o $APP_HOME/gradle/wrapper/gradle-wrapper.jar https://raw.githubusercontent.com/gradle/gradle/v4.0.2/gradle/wrapper/gradle-wrapper.jar +fi + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/java/kudu-client-tools/build.gradle b/java/kudu-client-tools/build.gradle new file mode 100644 index 0000000000..d8627c3928 --- /dev/null +++ b/java/kudu-client-tools/build.gradle @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +apply from: "$rootDir/gradle/shadow.gradle" + +dependencies { + compile project(":kudu-mapreduce") + compile libs.yetusAnnotations + compile libs.slf4jApi + + provided libs.hadoopClient + + testCompile project(path: ":kudu-client", configuration: "shadowTest") + testCompile project(path: ":kudu-mapreduce", configuration: "test") + testCompile libs.junit + testCompile libs.log4j + testCompile libs.slf4jLog4j12 +} \ No newline at end of file diff --git a/java/kudu-client/build.gradle b/java/kudu-client/build.gradle new file mode 100644 index 0000000000..b266073478 --- /dev/null +++ b/java/kudu-client/build.gradle @@ -0,0 +1,70 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +apply from: "$rootDir/gradle/protobuf.gradle" +apply from: "$rootDir/gradle/shadow.gradle" + +dependencies { + // Not shaded in the client JAR because it's part of the public API. + compileUnshaded(libs.async) { + // async uses versions ranges for slf4j making builds non-deterministic. + // Remove this once the following is merged: https://github.com/OpenTSDB/async/pull/8 + exclude group: "org.slf4j", module: "slf4j-api" + } + compileUnshaded libs.slf4jApi + compileUnshaded libs.yetusAnnotations + + compile libs.guava + compile libs.murmur + compile libs.netty + compile libs.protobufJava + + optional libs.jsr305 + + testCompile libs.commonsIo + testCompile libs.hamcrestCore + testCompile libs.junit + testCompile libs.log4j + testCompile libs.mockitoCore + testCompile libs.slf4jLog4j12 +} + +// Add protobuf files to the proto source set. +sourceSets { + main { + proto { + srcDir "${project.rootDir}/../src" + // Excluded any test proto files + exclude "**/*test*.proto" + } + } +} + +// Configure a shaded test jar for use in the other modules. +// We only do this for kudu-client because it has common test utilities. +task shadowTestJar(type: ShadowJar) { + classifier = "tests-shaded" + from sourceSets.test.output + configurations = [project.configurations.testRuntime] +} +// Create a configuration so that the shaded test jar can be referenced in other modules. +configurations.create("shadowTest") +artifacts { + shadowTest shadowTestJar +} \ No newline at end of file diff --git a/java/kudu-flume-sink/build.gradle b/java/kudu-flume-sink/build.gradle new file mode 100644 index 0000000000..79df593c76 --- /dev/null +++ b/java/kudu-flume-sink/build.gradle @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// Add the Avro plugin to support code generation from schema files. +apply plugin: "com.commercehub.gradle.plugin.avro" + +dependencies { + compile project(path: ":kudu-client", configuration: "shadow") + compile libs.slf4jApi + compile libs.yetusAnnotations + + provided libs.avro + provided libs.flumeConfiguration + provided libs.flumeCore + provided libs.hadoopClient + + testCompile project(path: ":kudu-client", configuration: "shadowTest") + testCompile libs.junit +} \ No newline at end of file diff --git a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/AvroKuduOperationsProducer.java b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/AvroKuduOperationsProducer.java index ac87e295b6..b6241bb70f 100644 --- a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/AvroKuduOperationsProducer.java +++ b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/AvroKuduOperationsProducer.java @@ -59,7 +59,7 @@ * body as an Avro record and mapping its fields to columns in a Kudu table. * *

Avro Kudu Operations Producer configuration parameters - * + *
* * * diff --git a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/KuduSink.java b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/KuduSink.java index 17706f716f..42f05423fb 100644 --- a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/KuduSink.java +++ b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/KuduSink.java @@ -57,7 +57,7 @@ * *

Flume Kudu Sink configuration parameters * - *

Property NameDefaultRequired?
+ *
* * * diff --git a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKeyedKuduOperationsProducer.java b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKeyedKuduOperationsProducer.java index c216f99f01..b4217716be 100644 --- a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKeyedKuduOperationsProducer.java +++ b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKeyedKuduOperationsProducer.java @@ -43,7 +43,7 @@ * *

Simple Keyed Kudu Operations Producer configuration parameters * - *

Property NameDefaultRequired?Description
channelYesThe name of the Flume channel to read.
typeYes
+ *
* * * diff --git a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKuduOperationsProducer.java b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKuduOperationsProducer.java index 4fa8bd8bb0..acd74e11ff 100644 --- a/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKuduOperationsProducer.java +++ b/java/kudu-flume-sink/src/main/java/org/apache/kudu/flume/sink/SimpleKuduOperationsProducer.java @@ -39,7 +39,7 @@ * *

Simple Kudu Event Producer configuration parameters * - *

Property NameDefault
+ *
* * * diff --git a/java/kudu-jepsen/build.gradle b/java/kudu-jepsen/build.gradle new file mode 100644 index 0000000000..fe55c21008 --- /dev/null +++ b/java/kudu-jepsen/build.gradle @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +apply plugin: "nebula.clojure" + +// Skip kudu-jepsen module tasks unless "Jepsen" property is passed. +if (!project.hasProperty("jepsen")) { + gradle.taskGraph.whenReady { + gradle.taskGraph.allTasks.each { + it.onlyIf { it.project != project } + } + } +} + +repositories { + maven { url "http://clojars.org/repo/" } +} + +dependencies { + compile project(path: ":kudu-client", configuration: "shadow") + compile project(path: ":kudu-client", configuration: "shadowTest") + compile libs.clojure + compile libs.clojureToolsCli + compile libs.jepsen + compile libs.yetusAnnotations +} + +compileClojure { + aotCompile = true +} +// Jepsen tests require specific infrastructure and do not run as part of the regular tests. +clojureTest.enabled = false + +// Run the Jepsen tests. +task runJepsen(type: JavaExec) { + def masterNodes = propertyWithDefault("masterNodes", "m0") + def tserverNodes = propertyWithDefault("tserverNodes", "t0,t1,t2,t3,t4") + def sshKeyPath = propertyWithDefault("sshKeyPath", "") + def iterNum = propertyWithDefault("iterNum", "1") + classpath sourceSets.main.clojure.srcDirs, + sourceSets.test.clojure.srcDirs, + sourceSets.test.runtimeClasspath, + sourceSets.main.runtimeClasspath, + main = "clojure.main" + args = [ + "$projectDir/src/utils/kudu_test_runner.clj", + "--masters=${masterNodes}", + "--tservers=${tserverNodes}", + "--ssh-key-path=${sshKeyPath}", + "--iter-num=${iterNum}" + ] +} \ No newline at end of file diff --git a/java/kudu-mapreduce/build.gradle b/java/kudu-mapreduce/build.gradle new file mode 100644 index 0000000000..cfeb26b999 --- /dev/null +++ b/java/kudu-mapreduce/build.gradle @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +dependencies { + compile project(path: ":kudu-client", configuration: "shadow") + compile(libs.async) { + // async uses versions ranges for slf4j making builds non-deterministic. + // Remove this once the following is merged: https://github.com/OpenTSDB/async/pull/8 + exclude group: "org.slf4j", module: "slf4j-api" + } + compile libs.slf4jApi + compile libs.yetusAnnotations + + provided libs.hadoopClient + + testCompile project(path: ":kudu-client", configuration: "shadowTest") + testCompile libs.junit + testCompile libs.log4j + testCompile libs.slf4jLog4j12 +} \ No newline at end of file diff --git a/java/kudu-spark-tools/build.gradle b/java/kudu-spark-tools/build.gradle new file mode 100644 index 0000000000..adf94b7b76 --- /dev/null +++ b/java/kudu-spark-tools/build.gradle @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +apply plugin: "scala" +apply from: "$rootDir/gradle/shadow.gradle" + +dependencies { + compile project(path: ":kudu-client", configuration: "shadow") + compile project(path: ":kudu-client-tools", configuration: "shadow") + compile project(path: ":kudu-spark", configuration: "shadow") + compile libs.slf4jApi + + provided libs.scalaLibrary + provided libs.sparkCore + provided libs.sparkSql + + testCompile project(path: ":kudu-client", configuration: "shadowTest") + testCompile project(path: ":kudu-spark", configuration: "test") + testCompile libs.junit + testCompile libs.log4j + testCompile libs.scalatest + testCompile libs.slf4jLog4j12 +} \ No newline at end of file diff --git a/java/kudu-spark-tools/pom.xml b/java/kudu-spark-tools/pom.xml index e0aa13b21a..c2eb57fe36 100644 --- a/java/kudu-spark-tools/pom.xml +++ b/java/kudu-spark-tools/pom.xml @@ -132,6 +132,12 @@ ${project.build.sourceEncoding} ${scala-2.11.version} + + + -feature + + -Xlint + diff --git a/java/kudu-spark-tools/src/test/scala/org/apache/kudu/spark/tools/IntegrationTestBigLinkedListTest.scala b/java/kudu-spark-tools/src/test/scala/org/apache/kudu/spark/tools/ITBigLinkedListTest.scala similarity index 97% rename from java/kudu-spark-tools/src/test/scala/org/apache/kudu/spark/tools/IntegrationTestBigLinkedListTest.scala rename to java/kudu-spark-tools/src/test/scala/org/apache/kudu/spark/tools/ITBigLinkedListTest.scala index 9d1faa57d9..6b34a5a44e 100644 --- a/java/kudu-spark-tools/src/test/scala/org/apache/kudu/spark/tools/IntegrationTestBigLinkedListTest.scala +++ b/java/kudu-spark-tools/src/test/scala/org/apache/kudu/spark/tools/ITBigLinkedListTest.scala @@ -28,7 +28,7 @@ import org.scalatest.{FunSuite, Matchers} import scala.collection.JavaConverters._ @RunWith(classOf[JUnitRunner]) -class IntegrationTestBigLinkedListTest extends FunSuite with TestContext with Matchers { +class ITBigLinkedListTest extends FunSuite with TestContext with Matchers { test("Spark ITBLL") { Generator.testMain(Array("--tasks=2", diff --git a/java/kudu-spark/build.gradle b/java/kudu-spark/build.gradle new file mode 100644 index 0000000000..0ce65acc73 --- /dev/null +++ b/java/kudu-spark/build.gradle @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +apply plugin: "scala" +apply from: "$rootDir/gradle/shadow.gradle" + +dependencies { + compile project(path: ":kudu-client", configuration: "shadow") + compile libs.yetusAnnotations + + provided libs.scalaLibrary + provided libs.sparkCore + provided libs.sparkSql + + testCompile project(path: ":kudu-client", configuration: "shadowTest") + testCompile libs.junit + testCompile libs.scalatest +} + +// Add compatibility sources based on the spark version used. +sourceSets { + main { + scala { + if (versions.sparkBase == "1") { + srcDir "src/main/spark1" + } else if (versions.sparkBase == "2") { + srcDir "src/main/spark2" + } else { + throw new GradleException("No compatibility sources exist for spark base version ${versions.sparkBase}") + } + } + } +} + +// Adjust the artifact name to match the maven build. +if (versions.sparkBase == "1") { + archivesBaseName = "kudu-spark_${versions.scalaBase}" +} else { + archivesBaseName = "kudu-spark${versions.sparkBase}_${versions.scalaBase}" +} \ No newline at end of file diff --git a/java/kudu-spark/pom.xml b/java/kudu-spark/pom.xml index 703ff5a43f..7585940e84 100644 --- a/java/kudu-spark/pom.xml +++ b/java/kudu-spark/pom.xml @@ -101,6 +101,12 @@ ${project.build.sourceEncoding} ${scala.version} + + + -feature + + -Xlint + diff --git a/java/settings.gradle b/java/settings.gradle new file mode 100644 index 0000000000..430e884bdc --- /dev/null +++ b/java/settings.gradle @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// This file contains the configuration of the project hierarchy. +// Mainly we just define what subprojects are in the build. + +rootProject.name = "kudu-parent" +include "kudu-client" +include "kudu-client-tools" +include "kudu-flume-sink" +include "kudu-jepsen" +include "kudu-mapreduce" +include "kudu-spark" +include "kudu-spark-tools"
Property NameDefault