Skip to content

Commit

Permalink
feat: Updated extension with compatibility with TWX 9.5, update gradle
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan-lacatus committed Feb 19, 2024
1 parent 5415de8 commit 88303f4
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 355 deletions.
55 changes: 55 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

# Created by https://www.toptal.com/developers/gitignore/api/java,gradle
# Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle
.idea
### Java ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

### Gradle ###
.gradle
build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Cache of project
.gradletasknamecache

# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties

### Gradle Patch ###
**/build/

# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath

# End of https://www.toptal.com/developers/gitignore/api/java,gradle
12 changes: 6 additions & 6 deletions README → README.MD
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# README #
# SFTP Extension

### What is this repository for? ###
## What is this repository for?

The SFTP Extension allows you to configure Thingworx entities to connect to a remote SFTP (SSH File Transfer Protocol) server for the purposes of managing the file system, like copying, moving or deleting files, as well as file transfer functionalities, like uploading or downloading files. The extension uses SSH for its underlying transport, so it provides secure authentication and transport. Both password, and key based authentication are supported.


### How do I get set up? ###
## How do I get set up?

* To build the importable zip extension run the gradle task **packageExtension**.
* Install the extension archive "zip/sftpExtension.zip" using the Extension import tool from ThingWorx.
* Create Things that inherit the SftpRepositoryTemplate ThingTemplate.
* On the created Things, configure them according to the documentation

### Developing ###
## Developing

You can use the gradle tasks *eclipse* or *idea* to generate projects that you can use in your favourite IDE

This Extension is provided as-is and without warranty or support. It is not part of the PTC product suite. This project is licensed under the terms of the MIT license
Please open an issue or contact placatus@iqnox.com for support.
This Extension is provided as-is and without warranty or support. It is not part of the PTC product suite. This project is licensed under the terms of the MIT license.
188 changes: 139 additions & 49 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,42 +1,52 @@
group 'com.thingworx.extensions'
version '1.0-SNAPSHOT'
apply plugin: 'idea'
apply plugin: 'eclipse'
apply plugin: 'java'
import groovyx.net.http.HTTPBuilder
import org.apache.http.entity.mime.MultipartEntityBuilder
import static groovyx.net.http.Method.POST

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.apache.httpcomponents:httpmime:4.5.2'
classpath 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
}
}

defaultTasks 'clean', 'build-extension'
plugins {
id 'java'
id 'wrapper'
}

group 'com.iqnox'
version '1.0-SNAPSHOT'
defaultTasks 'clean', 'packageExtension'

project.sourceCompatibility = 1.8
project.targetCompatibility = 1.8

// set the properties accordingly
project.ext {
incrementVersionNumber = true
extensionJar = "thingworx-sftp-extension.jar" // name of the jar
baseDir = projectDir
common = 'common'
uiDir = "${baseDir}/ui" // if there are any widgets
localJarDir = "${baseDir}/lib/local" // if you have any jars add them here
srcDir = "${baseDir}/src/main" // where are the sources located
uiDir = "${baseDir}/ui" // if there are any widgets
localJarDir = "${baseDir}/lib/local" // if you have any jars add them here
srcDir = "${baseDir}/src/main" // where are the sources located
buildDir = "${baseDir}/build" // where is the build saved
configDir = "${baseDir}/configfiles" // folder location of the metadata.xml file
entitiesDir = "${baseDir}/configfiles/Entities" // folder location of the metadata.xml file
zipDir = "${baseDir}/zip" // where to store the generated zip
thingworxSdkDir = "${baseDir}/lib/common" // where the thingworx sdk is located
packageVendor = "ThingWorx Customer Service"
thingworxSdkDir = "${baseDir}/lib/twxSdk" // where the thingworx sdk is located
packageVendor = "IQNOX"
packageName = "SftpExtension"
packageTitle = "SftpExtension"
packageVersion = version
thingworxServerRoot = "http://Administrator:Administrator12345@localhost:8016"
}

repositories {
mavenCentral()
jcenter()
maven {
url "${artifactory_contextUrl}/${artifactory_resolve_repokey}"
credentials {
username = "${artifactory_user}"
password = "${artifactory_password}"
}
}

flatDir {
dirs project.ext.thingworxSdkDir
Expand All @@ -60,43 +70,32 @@ clean.doFirst {

configurations {
packageDependencies
compile {
implementation {
extendsFrom packageDependencies
}
thingworxsdk
}

dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
// add all the dependencies for the extension using the packageDependencies configuration. Here only one is added
packageDependencies 'com.jcraft:jsch:0.1.53'
testImplementation group: 'junit', name: 'junit', version: '4.11'

// the zip version
thingworxsdk group: 'com.thingworx', name: 'Thingworx-Extension-SDK', version: '6.5.2-b463', ext: 'zip'
compile fileTree(dir: project.ext.thingworxSdkDir, include: ['*.jar'])
// import the statically defined jar files, and the jars in the thingworx sdk
implementation fileTree(dir: project.ext.thingworxSdkDir, include: ['*.jar'])
packageDependencies fileTree(dir: project.ext.localJarDir, include: ['*.jar'])
}

task extractTwxSdk(type: Copy) {
from {
configurations.thingworxsdk.collect { zipTree(it) }
}
into project.ext.thingworxSdkDir
}
// add all the dependencies for the extension using the packageDependencies configuration.
// use the implementation for jars that always exist at runtime
packageDependencies 'com.jcraft:jsch:0.1.55'

gradle.projectsEvaluated {
compileJava.dependsOn(extractTwxSdk)
}

jar {
archiveName = project.ext.extensionJar
archiveFileName = project.ext.extensionJar
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
)
attributes "Built-By" : project.ext.packageVendor
attributes "Build-Date": new Date().format("yyyy-MM-dd HH:mm:ss")
attributes "Package-Title" : project.ext.packageTitle
attributes "Package-Version": project.ext.packageVersion
attributes "Package-Vendor" : project.ext.packageVendor
}
}

Expand All @@ -109,6 +108,9 @@ def addDependenciesInMetadata() {
[type: "JAR", file: project.ext.extensionJar]
)
for (File f : configurations.packageDependencies) {
if (shouldExcludeFile(f.getName())) {
continue;
}
xml.ExtensionPackages.ExtensionPackage.JarResources[0]?.appendNode(
"FileResource",
[type: "JAR", file: f.getName()]
Expand All @@ -119,14 +121,49 @@ def addDependenciesInMetadata() {
pw.close()
}

private boolean shouldExcludeFile(String fileName) {
fileName.startsWith("commons-codec") ||
fileName.startsWith("commons-io") ||
fileName.startsWith("commons-lang") ||
fileName.startsWith("commons-logging") ||
fileName.startsWith("commons-compress") ||
fileName.startsWith("commons-collections4") ||
fileName.startsWith("bcprov") ||
fileName.startsWith("netty") ||
fileName.startsWith("gson") ||
fileName.startsWith("okhttp") ||
fileName.startsWith("okio") ||
fileName.startsWith("retrofit") ||
fileName.startsWith("jackson") ||
fileName.startsWith("jaxen") ||
fileName.startsWith("jdom") ||
fileName.startsWith("joda") ||
fileName.startsWith("log4j") ||
fileName.startsWith("logback") ||
fileName.startsWith("httpclient") ||
fileName.startsWith("httpcore") ||
fileName.startsWith("slf4j") ||
fileName.startsWith("thingworx") ||
fileName.startsWith("oauth2-oidc-sdk") ||
fileName.startsWith("guava") ||
fileName.startsWith("nimbus-jose-jwt") ||
fileName.startsWith("json-smart") ||
fileName.startsWith("error_prone_annotations") ||
fileName.startsWith("checker-qual")
}

task prepPackage(dependsOn: jar) {
if (project.ext.incrementVersionNumber)
increaseVersionNumber()
doLast {
delete project.ext.zipDir
delete "${buildDir}/zip/"

// add here all the jars from the packageDependencies configuration
copy {
from configurations.packageDependencies
from configurations.packageDependencies {
exclude {FileTreeElement details -> shouldExcludeFile(details.file.name)}
}
into "${buildDir}/zip/lib/common/"
}
// add the configuration
Expand All @@ -143,13 +180,66 @@ task prepPackage(dependsOn: jar) {
// add the ui files
copy {
from uiDir
into "${buildDir}/zip/ui/common/"
into "${buildDir}/zip/ui/"
}
}
}

task packageExtension(type: Zip, dependsOn: prepPackage, overwrite: true) {
archiveName = "${project.name}.zip"
destinationDir = new File(project.ext.zipDir)

tasks.register('packageExtension', Zip) {
dependsOn(prepPackage)
archiveFileName = "${project.name}.zip"
destinationDirectory = new File(project.ext.zipDir)
from "${buildDir}/zip/"
}
}


def increaseVersionNumber() {
def file = "${configDir}/metadata.xml"
def parser = new groovy.util.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")
}
}
}
}

Loading

0 comments on commit 88303f4

Please sign in to comment.