import org.apache.http.entity.mime.MultipartEntityBuilder
import static groovyx.net.http.Method.POST
group 'com.iqnox.twx.extensions'
version '1.0-SNAPSHOT'
apply plugin: 'idea'
apply plugin: 'eclipse'
apply plugin: 'java'
apply plugin: 'wrapper'
defaultTasks 'clean', 'packageExtension'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.apache.httpcomponents:httpmime:4.5.2'
classpath 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
}
}
//project.sourceCompatibility = 1.9
//project.targetCompatibility = 11
// set the properties accordingly
project.ext {
incrementVersionNumber = true
extensionJar = "ContentLoaderExtended_Extension"
baseDir = projectDir
println 'Project.ext: baseDir value: ' + projectDir
common = 'common'
uiDir = "${baseDir}/ui" // if there are any widgets
localJarDir = "${baseDir}/lib/local" // if you have any jars add them here
println 'Project.ext: localJarDir value: ' + localJarDir
srcDir = "${baseDir}/src/main/java" // where are the sources located
println 'Project.ext: srcDir value: ' + srcDir
//buildDir = "${baseDir}/build" // where is the build saved
configDir = "${baseDir}/configfiles" // folder location of the metadata.xml file
entitiesDir = "${baseDir}/configfiles/Entities" // folder additional Entities file that you want to be included in the extension
zipDir = "${baseDir}/zip" // where to store the generated zip
println 'Project.ext: zipDir value: ' + zipDir
thingworxSdkDir = "${baseDir}/lib/common" // where the thingworx sdk is located
packageVendor = "IQNOX" // MANIFEST.MF information
packageName = "ContentLoaderExtension" // MANIFEST.MF information
packageTitle = "ContentLoaderExtension" // MANIFEST.MF information
packageVersion = version
thingworxServerRoot = "http://Administrator:Administrator12345@localhost:8015" // When calling the Upload task, what is the target server
}
repositories {
mavenCentral()
//jcenter()
flatDir {
dirs project.ext.thingworxSdkDir
}
flatDir {
dirs project.ext.localJarDir
}
}
sourceSets {
main {
java {
srcDir project.ext.srcDir
}
}
}
clean.doFirst {
delete project.ext.zipDir
}
configurations {
packageDependencies
compile {
extendsFrom packageDependencies
}
}
dependencies {
testImplementation group: 'junit', name: 'junit', version: '4.12'
// compile dependencies are dependencies that you know that already exist in Tomcat
implementation group: 'commons-io', name: 'commons-io', version: '2.5'
implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
implementation group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.6'
// we depend on the thingworx sdk that should be in the thingorxSdkDir
implementation fileTree(dir: project.ext.thingworxSdkDir, include: ['*.jar'])
// package dependencies are external dependences that are also written in the metadata.xml under JarResoruces
// include all local jar, and other jars using manven
packageDependencies fileTree(dir: project.ext.localJarDir, include: ['**/*.jar'])
}
jar {
println 'Starting task Jar. Value of extensionJar is: '+project.ext.extensionJar
archiveBaseName = project.ext.extensionJar
version = ''
manifest {
attributes(["Built-By" : project.ext.packageVendor,
"Build-Date": new Date().format("yyyy-MM-dd HH:mm:ss")])
attributes(["Package-Title" : project.ext.packageTitle,
"Package-Version": project.ext.packageVersion,
"Package-Vendor" : project.ext.packageVendor], project.ext.packageName
)
}
println 'Finished task Jar'
}
def addDependenciesInMetadata() {
def file = "${buildDir}/zip/metadata.xml"
def parser = new groovy.xml.XmlParser(false, true)
def xml = parser.parse(file)
xml.ExtensionPackages.ExtensionPackage.JarResources[0]?.appendNode(
"FileResource",
[type: "JAR", file: project.ext.extensionJar+".jar"]
)
for (File f : configurations.packageDependencies) {
if (f.getName().startsWith("commons-codec") ||
f.getName().startsWith("commons-io") ||
f.getName().startsWith("commons-logging") ||
f.getName().startsWith("netty") ||
f.getName().startsWith("log4j") ||
f.getName().startsWith("httpclient") ||
f.getName().startsWith("httpcore") ||
f.getName().startsWith("slf4j")
) {
continue
}
xml.ExtensionPackages.ExtensionPackage.JarResources[0]?.appendNode(
"FileResource",
[type: "JAR", file: f.getName()]
)
}
PrintWriter pw = new PrintWriter(new File(file))
pw.write(groovy.xml.XmlUtil.serialize(xml))
pw.close()
}
tasks.register("prepPackage") {
dependsOn(tasks.named("jar"))
// this block runs during configuration (same as your original)
println 'Starting task prepPackage.'
println 'Increment version value: '+project.ext.incrementVersionNumber
if (project.ext.incrementVersionNumber) {
increaseVersionNumber()
}
doLast {
println 'Starting to delete all files from: ' + project.ext.zipDir+" and from: " + "${buildDir}/zip/"
delete project.ext.zipDir
delete "${buildDir}/zip/"
println 'Finished deleting files'
// add here all the jars from the packageDependencies configuration
copy {
from configurations.packageDependencies
into "${buildDir}/zip/lib/common/"
}
// add the configuration
copy {
from "${project.ext.configDir}"
into "${buildDir}/zip/"
}
addDependenciesInMetadata()
// add the extension jar itself
copy {
from "${buildDir}/libs/${project.ext.extensionJar}.jar"
println 'Starting to copy the JAR file from: '+"${buildDir}/libs/${project.ext.extensionJar}"+" to: " +"${buildDir}/zip/lib/common/"
into "${buildDir}/zip/lib/common/"
}
// add the ui files
copy {
from uiDir
into "${buildDir}/zip/ui/"
}
copy {
from entitiesDir
into "${buildDir}/zip/Entities/"
}
}
}
tasks.register("packageExtension", Zip) {
println 'Starting task packageExtension.'
dependsOn(tasks.named("prepPackage"))
archiveFileName.set("${project.name}.zip")
println 'PackageExtension archiveFileName value:'+"${project.name}.zip"
destinationDirectory.set(file(project.ext.zipDir))
println 'PackageExtension destinationDirectory value:'+file(project.ext.zipDir)
from(layout.buildDirectory.dir("zip"))
println 'PackageExtension from value:'+layout.buildDirectory.dir("zip")
println 'Finished task packageExtension.'
}
def increaseVersionNumber() {
def file = "${configDir}/metadata.xml"
def parser = new groovy.xml.XmlParser(false, true)
def xml = parser.parse(file)
def currentVersion = xml.ExtensionPackages.ExtensionPackage.@packageVersion[0]
def versionComponents = currentVersion.split('\\.')
def minorVersion = ++Integer.parseInt(versionComponents[versionComponents.length - 1])
versionComponents[versionComponents.length - 1] = String.valueOf(minorVersion)
xml.ExtensionPackages.ExtensionPackage.@packageVersion = String.join('.', versionComponents)
// xml.ExtensionPackages.ExtensionPackage.get(0).attributes().put('packageVersion', String.join(',', versionComponents));
println 'Updated to version ' + String.join('.', versionComponents)
println xml.ExtensionPackages.ExtensionPackage.@packageVersion[0]
PrintWriter pw = new PrintWriter(new File(file))
pw.write(groovy.xml.XmlUtil.serialize(xml))
pw.close()
}
task upload(dependsOn: packageExtension) {
doLast {
def http = new HTTPBuilder("${project.ext.thingworxServerRoot}/Thingworx/")
def extZip = file("${project.ext.zipDir}/${project.name}.zip")
http.request(POST) { req ->
uri.path = 'ExtensionPackageUploader'
uri.query = ['purpose': 'import']
headers."X-XSRF-TOKEN" = "TWX-XSRF-TOKEN-VALUE"
requestContentType = 'multipart/form-data'
MultipartEntityBuilder entity = MultipartEntityBuilder.create().setLaxMode()
entity.addBinaryBody('file', extZip)
req.setEntity(entity.build())
response.success = { resp ->
println("Upload successful!")
}
response.failure = { resp ->
println(resp.statusLine)
throw new StopExecutionException("Thingworx upload failed! See server response above")
}
}
}
}
We (me and @twobby) tried building this project by command line, using the latest gradle version (9.3.1) for ThingWorx 10.0
We encountered various errors, and modified the existing project file with this version.
We are not sure if the modifications are safe enough to be included in a PR, but we're adding what worked for us, so that others can use it in case they have issues.