import se.bjurr.gitchangelog.plugin.gradle.GitChangelogTask plugins { id 'java' id 'maven-publish' id 'signing' id "org.javacc.javacc" version "latest.release" id 'jacoco' id 'com.github.kt3k.coveralls' version "latest.release" id "com.github.spotbugs" version "latest.release" id "com.diffplug.spotless" version "latest.release" id 'pmd' id 'checkstyle' // download the RR tools which have no Maven Repository id "de.undercouch.download" version "latest.release" id 'org.hidetake.ssh' version "latest.release" id "se.bjurr.gitchangelog.git-changelog-gradle-plugin" version "latest.release" id "me.champeau.jmh" version "latest.release" id "com.nwalsh.gradle.saxon.saxon-gradle" version "0.9.6" } def getVersion = { boolean considerSnapshot -> Integer major = 0 Integer minor = 0 Integer patch = null Integer build = null def commit = null def snapshot = "" new ByteArrayOutputStream().withStream { os -> exec { args = [ "--no-pager" , "describe" , "--tags" , "--always" , "--dirty=-SNAPSHOT" ] executable "git" standardOutput = os } def versionStr = os.toString().trim() def pattern = /(?\d*)\.(?\d*)(\.(?\d*))?(-(?\d*)-(?[a-zA-Z\d]*))?/ def matcher = versionStr =~ pattern if (matcher.find()) { major = matcher.group('major') as Integer minor = matcher.group('minor') as Integer patch = matcher.group('patch') as Integer build = matcher.group('build') as Integer commit = matcher.group('commit') } if (considerSnapshot && ( versionStr.endsWith('SNAPSHOT') || build!=null) ) { minor++ if (patch!=null) patch = 0 snapshot = "-SNAPSHOT" } } return patch!=null ? "${major}.${minor}.${patch}${snapshot}" : "${major}.${minor}${snapshot}" } // for publishing a release, call Gradle with Environment Variable RELEASE: // RELEASE=true gradle JSQLParser:publish version = getVersion( !System.getenv("RELEASE") ) group = 'com.github.jsqlparser' description = 'JSQLParser library' archivesBaseName = "JSQLParser" repositories { gradlePluginPortal() mavenLocal() mavenCentral() // Sonatype OSSRH maven { url = uri('https://s01.oss.sonatype.org/content/repositories/snapshots/') } } configurations { xmlDoclet } dependencies { testImplementation 'commons-io:commons-io:2.+' testImplementation 'org.apache.commons:commons-text:+' testImplementation 'org.mockito:mockito-core:+' testImplementation 'org.assertj:assertj-core:+' testImplementation 'org.hamcrest:hamcrest-core:+' testImplementation 'org.apache.commons:commons-lang3:+' testImplementation 'com.h2database:h2:+' // for JaCoCo Reports testImplementation 'org.junit.jupiter:junit-jupiter-api:+' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:+' testImplementation 'org.junit.jupiter:junit-jupiter-params:+' // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter testImplementation 'org.mockito:mockito-junit-jupiter:+' // Performance Benchmark testImplementation 'org.openjdk.jmh:jmh-core:+' testImplementation 'org.openjdk.jmh:jmh-generator-annprocess:+' // Java Doc in XML Format xmlDoclet 'com.manticore-projects.tools:xml-doclet:+' // enforce latest version of JavaCC testImplementation 'net.java.dev.javacc:javacc:+' javacc 'net.java.dev.javacc:javacc:+' } compileJavacc { arguments = [grammar_encoding: 'UTF-8', static: 'false', java_template_type: 'modern'] } java { withSourcesJar() withJavadocJar() sourceCompatibility = '11' targetCompatibility = '11' // needed for XML-Doclet to work (since Doclet changed again with Java 13) toolchain { languageVersion.set(JavaLanguageVersion.of(11)) } } compileJava { options.release = 11 } javadoc { include("build/generated/javacc/net/sf/jsqlparser/parser/*.java" ) if(JavaVersion.current().isJava9Compatible()) { options.addBooleanOption('html5', true) } options.addBooleanOption("Xdoclint:none", true) } jar { manifest { attributes ( "Automatic-Module-Name": "net.sf.jsqlparser" ) } } tasks.register('xmldoc', Javadoc) { def outFile = reporting.file( version.endsWith("-SNAPSHOT") ? "xmlDoclet/javadoc_snapshot.xml" : "xmlDoclet/javadoc_stable.xml" ) def rstFile = reporting.file( version.endsWith("-SNAPSHOT") ? "xmlDoclet/javadoc_snapshot.rst" : "xmlDoclet/javadoc_stable.rst" ) source = sourceSets.main.allJava // beware: Gradle deletes this folder automatically and there is no switch-off destinationDir = reporting.file("xmlDoclet") options.docletpath = configurations.xmlDoclet.files as List options.doclet = "com.github.markusbernhardt.xmldoclet.XmlDoclet" title = "API $version" options.addBooleanOption("rst", true) options.addBooleanOption("withFloatingToc", Boolean.parseBoolean(System.getenv().getOrDefault("FLOATING_TOC", "true"))) options.addStringOption("basePackage", "net.sf.jsqlparser") options.addStringOption("filename", outFile.getName()) dependsOn(compileJava) doLast { copy { from rstFile into "${projectDir}/src/site/sphinx/" } } } test { environment = [ 'EXPORT_TEST_TO_FILE': 'True' ] useJUnitPlatform() // set heap size for the test JVM(s) minHeapSize = "128m" maxHeapSize = "1G" } coveralls { jacocoReportPath 'build/reports/jacoco/test/jacocoTestReport.xml' } jacocoTestReport { // Jacoco can't handle the TokenManager class afterEvaluate { classDirectories.setFrom(files(classDirectories.files.collect { fileTree(dir: it, exclude: [ "**CCJSqlParserTokenManager**" ]) })) } dependsOn test // tests are required to run before generating the report reports { xml.required = false csv.required = false html.outputLocation = layout.buildDirectory.dir('reports/jacoco') } } jacocoTestCoverageVerification { // Jacoco can't handle the TokenManager class afterEvaluate { classDirectories.setFrom(files(classDirectories.files.collect { fileTree(dir: it, exclude: [ "**CCJSqlParserTokenManager**" ]) })) } violationRules { rule { //element = 'CLASS' limit { //@todo: temporarily reduced it 80%, we need to bring that back to 84% accepting the Keywords PR minimum = 0.50 } excludes = [ 'net.sf.jsqlparser.util.validation.*', 'net.sf.jsqlparser.**.*Adapter', 'net.sf.jsqlparser.parser.**' ] } rule { //element = 'CLASS' limit { counter = 'LINE' value = 'MISSEDCOUNT' //@todo: temporarily increased to 7000, we need to bring that down to 5500 after accepting the Keywords PR maximum = 20000 } excludes = [ 'net.sf.jsqlparser.util.validation.*', 'net.sf.jsqlparser.**.*Adapter', 'net.sf.jsqlparser.parser.**' ] } // rule { // element = 'CLASS' // limit { // counter = 'LINE' // value = 'MISSEDRATIO' // maximum = 0.3 // } // excludes = [ // 'net.sf.jsqlparser.util.validation.*', // 'net.sf.jsqlparser.**.*Adapter', // 'net.sf.jsqlparser.parser.**' // ] // } } } spotbugsMain { reports { html { enabled = true destination = file("build/reports/spotbugs/main/spotbugs.html") stylesheet = 'fancy-hist.xsl' } } } spotbugs { // fail only on P1 and without the net.sf.jsqlparser.parser.* excludeFilter = file("config/spotbugs/spotBugsExcludeFilter.xml") // do not run over the test, although we should do that eventually spotbugsTest.enabled = false } pmd { consoleOutput = true sourceSets = [sourceSets.main] // clear the ruleset in order to use configured rules only ruleSets = [] //rulesMinimumPriority = 1 ruleSetFiles = files("config/pmd/ruleset.xml") pmdMain { excludes = [ "build/generated/*" ] } } checkstyle { sourceSets = [sourceSets.main, sourceSets.test] configFile = rootProject.file('config/checkstyle/checkstyle.xml') } spotless { // optional: limit format enforcement to just the files changed by this feature branch ratchetFrom 'origin/master' format 'misc', { // define the files to apply `misc` to target '*.rst', '*.md', '.gitignore' // define the steps to apply to those files trimTrailingWhitespace() indentWithSpaces(4) // or spaces. Takes an integer argument if you don't like 4 endWithNewline() } java { indentWithSpaces(4) eclipse().configFile('config/formatter/eclipse-java-google-style.xml') } } tasks.withType(Checkstyle).configureEach { reports { xml.required = false html.required = true } excludes = [ "**/module-info.java" ] } tasks.register('renderRR') { dependsOn(compileJavacc) doLast { // these WAR files have been provided as a courtesy by Gunther Rademacher // and belong to the RR - Railroad Diagram Generator Project // https://github.com/GuntherRademacher/rr // // Hosting at manticore-projects.com is temporary until a better solution is found // Please do not use these files without Gunther's permission download.run { src 'http://manticore-projects.com/download/convert.war' dest "$buildDir/rr/convert.war" overwrite false onlyIfModified true } download.run { src 'http://manticore-projects.com/download/rr.war' dest "$buildDir/rr/rr.war" overwrite false onlyIfModified true tempAndMove true } javaexec { standardOutput = new FileOutputStream("${buildDir}/rr/JSqlParserCC.ebnf") main = "-jar" args = [ "$buildDir/rr/convert.war", "$buildDir/generated/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jj" ] } javaexec { main = "-jar" args = [ "$buildDir/rr/rr.war", "-noepsilon", "-color:#4D88FF", "-offset:0", "-width:800", //"-png", //"-out:${buildDir}/rr/JSqlParserCC.zip", "-out:${buildDir}/rr/JSqlParserCC.xhtml", "${buildDir}/rr/JSqlParserCC.ebnf" ] } } } tasks.register('gitChangelogTask', GitChangelogTask) { fromRepo = file("$projectDir") file = new File("${projectDir}/src/site/sphinx/changelog.rst") fromRef = "4.0" //toRef = "1.1"; // switch off the formatter since the indentation matters for Mark-down // @formatter:off templateContent =""" ************************ Changelog ************************ {{#tags}} {{#ifMatches name "^Unreleased.*"}} Latest Changes since |JSQLPARSER_VERSION| {{/ifMatches}} {{#ifMatches name "^(?!Unreleased).*"}} Version {{name}} {{/ifMatches}} ============================================================= {{#issues}} {{#commits}} {{#ifMatches messageTitle "^(?!Merge).*"}} * **{{{messageTitle}}}** {{authorName}}, {{commitDate}} {{/ifMatches}} {{/commits}} {{/issues}} {{/tags}} """ // @formatter:on } tasks.register('updateKeywords', JavaExec) { group = "Execution" description = "Run the main class with JavaExecTask" classpath = sourceSets.main.runtimeClasspath args = [ file('src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt').absolutePath , file('src/site/sphinx/keywords.rst').absolutePath ] main("net.sf.jsqlparser.parser.ParserKeywordsUtils") dependsOn(compileJava) } xslt { def outFile = version.endsWith("-SNAPSHOT") ? file("src/site/sphinx/syntax_snapshot.rst") : file("src/site/sphinx/syntax_stable.rst") dependsOn(renderRR) stylesheet 'src/main/resources/rr/xhtml2rst.xsl' parameters ( "withFloatingToc": System.getenv().getOrDefault("FLOATING_TOC", "true"), "isSnapshot": Boolean.toString(version.endsWith("-SNAPSHOT")) ) // Transform every .xml file in the "input" directory. input "$buildDir/rr/JSqlParserCC.xhtml" output outFile } tasks.register('sphinx', Exec) { dependsOn(gitChangelogTask, renderRR, xslt, xmldoc) String PROLOG = """ .. |_| unicode:: U+00A0 :trim: .. |JSQLPARSER_EMAIL| replace:: support@manticore-projects.com .. |JSQLPARSER_VERSION| replace:: ${getVersion(false)} .. |JSQLPARSER_SNAPSHOT_VERSION| replace:: ${getVersion(true)} .. |JSQLPARSER_STABLE_VERSION_LINK| raw:: html ${project.name}-${getVersion(false)}.jar .. |JSQLPARSER_SNAPSHOT_VERSION_LINK| raw:: html ${project.name}-${getVersion(true)}.jar """ args = [ "-Dproject=JSQLParser" , "-Dcopyright=Tobias Warneke, 2022" , "-Dauthor=Tobias Warneke" , "-Drelease=${getVersion(false)}" , "-Drst_prolog=$PROLOG" , "${projectDir}/src/site/sphinx" , "${project.buildDir}/sphinx" ] executable "sphinx-build" //store the output instead of printing to the console: standardOutput = new ByteArrayOutputStream() //extension method stopTomcat.output() can be used to obtain the output: ext.output = { return standardOutput.toString() } } publish { dependsOn(check, gitChangelogTask, renderRR, xslt, xmldoc) } publishing { publications { mavenJava(MavenPublication) { artifactId = 'jsqlparser' from components.java versionMapping { usage('java-api') { fromResolutionOf('runtimeClasspath') } usage('java-runtime') { fromResolutionResult() } } pom { name = 'JSQLParser library' description = 'Parse SQL Statements into Abstract Syntax Trees (AST)' url = 'https://github.com/JSQLParser/JSqlParser' licenses { license { name = 'GNU Library or Lesser General Public License (LGPL) V2.1' url = 'http://www.gnu.org/licenses/lgpl-2.1.html' } license { name = 'The Apache Software License, Version 2.0' url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } developers { developer { id = 'twa' name = 'Tobias Warneke' email = 't.warneke@gmx.net' } developer { id = 'are' name = 'Andreas Reichel' email = 'andreas@manticore-projects.com' } } scm { connection = 'scm:git:https://github.com/JSQLParser/JSqlParser.git' developerConnection = 'scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git' url = 'https://github.com/JSQLParser/JSqlParser.git' } } } } repositories { maven { name "ossrh" def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" def snapshotsRepoUrl= "https://oss.sonatype.org/content/repositories/snapshots/" url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl credentials { username = System.getenv("ossrhUsername") password = System.getenv("ossrhPassword") } } } } signing { //def signingKey = findProperty("signingKey") //def signingPassword = findProperty("signingPassword") //useInMemoryPgpKeys(signingKey, signingPassword) // don't sign SNAPSHOTS if (!version.endsWith('SNAPSHOT')) { sign publishing.publications.mavenJava } } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } remotes { webServer { host = findProperty("${project.name}.host") user = findProperty("${project.name}.username") identity = new File("${System.properties['user.home']}/.ssh/id_rsa") } } tasks.register('upload') { doFirst { if (findProperty("${project.name}.host") == null) { println( """ Property \"${project.name}.host\' not found. Please define \"${project.name}.host\" in the Gradle configuration (e. g. \$HOME/.gradle/gradle.properties. """ ) } } doLast { ssh.run { session(remotes.webServer) { def versionStable = getVersion(false) execute "mkdir -p download/${project.name}-${versionStable}" for (File file: fileTree(include:['*.jar'], dir:"${project.buildDir}/libs").collect()) { put from: file, into: "download/${project.name}-${versionStable}" } } } } } check.dependsOn jacocoTestCoverageVerification upload.dependsOn(check, assemble, gitChangelogTask, renderRR, xslt, xmldoc)