diff --git a/build.gradle b/build.gradle index c2f5d3a6..eb16131f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,31 @@ +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.adaptc.gradle:nexus-workflow:0.6' + } +} + +apply plugin: 'nexus-workflow' apply plugin: 'java' apply plugin: 'maven' +apply plugin: 'signing' -group 'org.iot.dsa' -version '0.25.0' +group 'org.iot-dsa' +version '0.27.0' sourceCompatibility = 1.6 targetCompatibility = 1.6 +install { + repositories.mavenInstaller { + pom.project { + artifactId 'dslink-v2' + } + } +} + repositories { mavenLocal() mavenCentral() @@ -16,7 +35,7 @@ repositories { } dependencies { - testCompile 'junit:junit:+' + testCompile 'junit:junit:[4.12,)' } task sourcesJar(group: 'build', type: Jar, dependsOn: classes) { @@ -24,6 +43,12 @@ task sourcesJar(group: 'build', type: Jar, dependsOn: classes) { from sourceSets.main.allJava } +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + artifacts { archives sourcesJar + archives javadocJar } diff --git a/ci/secring.gpg.enc b/ci/secring.gpg.enc new file mode 100644 index 00000000..b6130bd1 Binary files /dev/null and b/ci/secring.gpg.enc differ diff --git a/dslink-core/build.gradle b/dslink-core/build.gradle index dd25f220..8396041e 100644 --- a/dslink-core/build.gradle +++ b/dslink-core/build.gradle @@ -3,3 +3,54 @@ apply from: '../build.gradle' javadoc { exclude("**/com/**") } + +signing { + required { gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives +} + +uploadArchives { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + pom.project { + name = 'DSLink SDK V2' + artifactId = 'dslink-core-v2' + description = 'V2 Java SDK for the IoT DSA protocol' + + packaging = 'jar' + url = 'http://iot-dsa.org' + + scm { + connection = 'scm:git:https://github.com/iot-dsa-v2/sdk-dslink-java-v2.git' + developerConnection = 'scm:git:git@github.com:iot-dsa-v2/sdk-dslink-java-v2.git' + url = 'https://github.com/iot-dsa-v2/sdk-dslink-java-v2' + } + + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + + developers { + developer { + id = 'samrg472' + name = 'Samuel Grenier' + email = 'samrg472@gmail.com' + } + } + } + } + } +} diff --git a/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/protocol/v1/DS1Session.java b/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/protocol/v1/DS1Session.java index 9bc2b335..ea3f6d30 100644 --- a/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/protocol/v1/DS1Session.java +++ b/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/protocol/v1/DS1Session.java @@ -287,11 +287,9 @@ protected void processEnvelope(DSIReader reader) { getConnection().setRequesterAllowed(); } } else if (key.equals("salt")) { - if (reader.next() != Token.STRING) { - throw new IllegalStateException("Salt not a string"); - } - fine(fine() ? "Next salt: " + reader.getString() : null); - getConnection().updateSalt(reader.getString()); + String s = reader.getElement().toString(); + fine(fine() ? "Next salt: " + s : null); + getConnection().updateSalt(s); } next = reader.next(); } while (next != END_MAP); diff --git a/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/sys/cert/SysCertManager.java b/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/sys/cert/SysCertManager.java index d36cd727..29148606 100644 --- a/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/sys/cert/SysCertManager.java +++ b/dslink-core/src/main/java/com/acuity/iot/dsa/dslink/sys/cert/SysCertManager.java @@ -5,7 +5,7 @@ import org.iot.dsa.node.DSInfo; import org.iot.dsa.node.DSNode; import org.iot.dsa.node.DSString; -import org.iot.dsa.security.DSPasswordAes; +import org.iot.dsa.security.DSPasswordAes256; /** * Certificate management for the whole process. This is basically a stub for future @@ -57,11 +57,11 @@ public void declareDefaults() { declareDefault(ALLOW_SERVERS, DSBool.TRUE); declareDefault(CERTFILE, DSString.valueOf("dslink.jks")); declareDefault(CERTFILE_TYPE, DSString.valueOf("JKS")); - declareDefault(CERTFILE_PASS, DSPasswordAes.valueOf("dsarocks")); + declareDefault(CERTFILE_PASS, DSPasswordAes256.valueOf("dsarocks")); } private String getCertFilePass() { - DSPasswordAes pass = (DSPasswordAes) keystorePass.getObject(); + DSPasswordAes256 pass = (DSPasswordAes256) keystorePass.getObject(); return pass.decode(); } diff --git a/dslink-core/src/main/java/org/iot/dsa/dslink/DSLink.java b/dslink-core/src/main/java/org/iot/dsa/dslink/DSLink.java index 57e48bb6..d9df32d5 100644 --- a/dslink-core/src/main/java/org/iot/dsa/dslink/DSLink.java +++ b/dslink-core/src/main/java/org/iot/dsa/dslink/DSLink.java @@ -356,15 +356,16 @@ public void save() { */ public void shutdown() { stop(); - if (runThread == null) { + Thread thread = runThread; + if (thread == null) { return; } - synchronized (runThread) { - try { - runThread.join(); - } catch (Exception x) { - fine(x); + try { + synchronized (thread) { + thread.join(); } + } catch (Exception x) { + fine(x); } } diff --git a/dslink-core/src/main/java/org/iot/dsa/node/DSPath.java b/dslink-core/src/main/java/org/iot/dsa/node/DSPath.java index 6052bcbb..48cc0f3f 100644 --- a/dslink-core/src/main/java/org/iot/dsa/node/DSPath.java +++ b/dslink-core/src/main/java/org/iot/dsa/node/DSPath.java @@ -16,7 +16,7 @@ public class DSPath { /////////////////////////////////////////////////////////////////////////// private static final int caseDiff = ('a' - 'A'); - private static final Charset utf8 = Charset.forName("UTF-8"); + private static final Charset utf8 = DSString.UTF8; /////////////////////////////////////////////////////////////////////////// // Fields @@ -56,15 +56,14 @@ public static StringBuilder concat(String leading, String trailing, StringBuilde } if (leading.charAt(leading.length() - 1) == '/') { if (trailing.charAt(0) == '/') { - bucket.append(trailing.substring(1)); + return bucket.append(trailing.substring(1)); } } else { if (trailing.charAt(0) != '/') { bucket.append('/'); - bucket.append(trailing); } } - return bucket; + return bucket.append(trailing); } /** diff --git a/dslink-core/src/main/java/org/iot/dsa/node/DSString.java b/dslink-core/src/main/java/org/iot/dsa/node/DSString.java index 1ce354bd..5a0baebc 100644 --- a/dslink-core/src/main/java/org/iot/dsa/node/DSString.java +++ b/dslink-core/src/main/java/org/iot/dsa/node/DSString.java @@ -1,8 +1,6 @@ package org.iot.dsa.node; import java.nio.charset.Charset; -import java.util.logging.Level; -import org.iot.dsa.logging.DSLogging; /** * String wrapper. @@ -24,7 +22,7 @@ public class DSString extends DSElement { /** * The standard UTF8 charset, can be used with string.getBytes(Charset). */ - public static final Charset UTF8 = utf8(); + public static final Charset UTF8 = Charset.forName("UTF-8"); // Fields // ------ @@ -84,16 +82,12 @@ public boolean isString() { public boolean toBoolean() { if (value.equalsIgnoreCase("true")) { return true; - } else if (value.equalsIgnoreCase("false")) { - return true; } else if (value.equals("0")) { return false; } else if (value.equals("1")) { return true; } else if (value.equalsIgnoreCase("on")) { return true; - } else if (value.equalsIgnoreCase("off")) { - return false; } return false; } @@ -106,15 +100,6 @@ public String toString() { return value; } - private static Charset utf8() { - try { - return Charset.forName("UTF-8"); - } catch (Exception x) { - DSLogging.getDefaultLogger().log(Level.SEVERE, "UTF-8 unknown", x); - } - return Charset.defaultCharset(); - } - @Override public DSString valueOf(DSElement arg) { return valueOf(arg.toString()); diff --git a/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordAes.java b/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordAes256.java similarity index 85% rename from dslink-core/src/main/java/org/iot/dsa/security/DSPasswordAes.java rename to dslink-core/src/main/java/org/iot/dsa/security/DSPasswordAes256.java index 93755015..053c25ce 100644 --- a/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordAes.java +++ b/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordAes256.java @@ -14,14 +14,14 @@ * * @author Aaron Hansen */ -public class DSPasswordAes extends DSValue implements DSIPassword, DSIStorable { +public class DSPasswordAes256 extends DSValue implements DSIPassword, DSIStorable { // Constants // --------- private static Cipher cipher; private static Key key; - public static final DSPasswordAes NULL = new DSPasswordAes(DSString.NULL); + public static final DSPasswordAes256 NULL = new DSPasswordAes256(DSString.NULL); // Fields // ------ @@ -31,11 +31,11 @@ public class DSPasswordAes extends DSValue implements DSIPassword, DSIStorable { // Constructors // ------------ - private DSPasswordAes(DSString encrypted) { + private DSPasswordAes256(DSString encrypted) { this.value = encrypted; } - private DSPasswordAes(String encrypted) { + private DSPasswordAes256(String encrypted) { this(DSString.valueOf(encrypted)); } @@ -86,7 +86,7 @@ public static String encode(String arg) { @Override public boolean equals(Object obj) { - if (obj instanceof DSPasswordAes) { + if (obj instanceof DSPasswordAes256) { return value.equals(obj.toString()); } return false; @@ -148,11 +148,11 @@ public DSString store() { } @Override - public DSPasswordAes restore(DSElement element) { + public DSPasswordAes256 restore(DSElement element) { if (element.isNull()) { return NULL; } - return new DSPasswordAes(element.toString()); + return new DSPasswordAes256(element.toString()); } /** @@ -178,7 +178,7 @@ public String toString() { * @return Returns the NULL instance if the arg is null, isNull() or the empty string. */ @Override - public DSPasswordAes valueOf(DSElement arg) { + public DSPasswordAes256 valueOf(DSElement arg) { if ((arg == null) || arg.isNull()) { return NULL; } @@ -195,13 +195,13 @@ public DSPasswordAes valueOf(DSElement arg) { * @param arg The text to hash. * @return Returns the NULL instance if the arg is null or the empty string. */ - public static DSPasswordAes valueOf(String arg) { + public static DSPasswordAes256 valueOf(String arg) { if (arg == null) { return NULL; } else if (arg.isEmpty()) { return NULL; } - return new DSPasswordAes(encode(arg)); + return new DSPasswordAes256(encode(arg)); } // Initialization @@ -210,14 +210,14 @@ public static DSPasswordAes valueOf(String arg) { static { try { cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); - byte[] nameBytes = DSPasswordAes.class.getName().getBytes(DSString.UTF8); - byte[] keyBytes = new byte[16]; - System.arraycopy(nameBytes, 0, keyBytes, 0, 16); + byte[] nameBytes = DSPasswordAes256.class.getName().getBytes(DSString.UTF8); + byte[] keyBytes = new byte[32]; + System.arraycopy(nameBytes, 0, keyBytes, 0, 32); key = new SecretKeySpec(keyBytes, "AES"); } catch (Exception x) { Logger.getLogger("security").log(Level.SEVERE, "AES problem", x); } - DSRegistry.registerDecoder(DSPasswordAes.class, NULL); + DSRegistry.registerDecoder(DSPasswordAes256.class, NULL); } } diff --git a/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordSha256.java b/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordSha256.java index 4f3b7433..30200ebe 100644 --- a/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordSha256.java +++ b/dslink-core/src/main/java/org/iot/dsa/security/DSPasswordSha256.java @@ -55,7 +55,7 @@ public static String encode(String arg) { @Override public boolean equals(Object obj) { - if (obj instanceof DSPasswordAes) { + if (obj instanceof DSPasswordAes256) { return value.equals(obj.toString()); } return false; diff --git a/dslink-core/src/test/java/org/iot/dsa/dslink/DSPasswordTests.java b/dslink-core/src/test/java/org/iot/dsa/dslink/DSPasswordTests.java index 37736d27..0b649e3e 100644 --- a/dslink-core/src/test/java/org/iot/dsa/dslink/DSPasswordTests.java +++ b/dslink-core/src/test/java/org/iot/dsa/dslink/DSPasswordTests.java @@ -2,7 +2,7 @@ import org.iot.dsa.node.DSElement; import org.iot.dsa.node.DSString; -import org.iot.dsa.security.DSPasswordAes; +import org.iot.dsa.security.DSPasswordAes256; import org.iot.dsa.security.DSPasswordSha256; import org.junit.Assert; import org.junit.Test; @@ -25,15 +25,15 @@ public class DSPasswordTests { // ------- @Test - public void testAes() throws Exception { - DSPasswordAes pass = DSPasswordAes.valueOf("myPass"); + public void testAes256() throws Exception { + DSPasswordAes256 pass = DSPasswordAes256.valueOf("myPass"); String encrypted = pass.toString(); Assert.assertFalse(pass.toString().equals("myPass")); Assert.assertTrue(pass.decode().equals("myPass")); Assert.assertTrue(pass.isValid(DSString.valueOf("myPass"))); Assert.assertFalse(pass.isValid(DSString.valueOf("asdf"))); DSElement e = pass.store(); - pass = DSPasswordAes.NULL.restore(e); + pass = DSPasswordAes256.NULL.restore(e); Assert.assertFalse(pass.toString().equals("myPass")); Assert.assertTrue(pass.decode().equals("myPass")); Assert.assertTrue(pass.toString().equals(encrypted)); diff --git a/dslink-java-v2-poc/dslink.json b/dslink-java-v2-poc/dslink.json index 95681e4d..bef28535 100644 --- a/dslink-java-v2-poc/dslink.json +++ b/dslink-java-v2-poc/dslink.json @@ -7,12 +7,12 @@ "configs": { "handler_class": { "type": "string", - "value": "org.iot.dsa.dslink.test.MainNode" + "value": "org.iot.dsa.dslink.poc.MainNode" }, "log": { "desc": "all, trace, debug, fine, warn, info, error, admin, fatal, none", "type": "enum", - "value": "info" + "value": "all" }, "token": { "desc": "Authentication token for the broker.", diff --git a/dslink-java-v2-poc/src/main/java/org/iot/dsa/dslink/test/MainNode.java b/dslink-java-v2-poc/src/main/java/org/iot/dsa/dslink/poc/MainNode.java similarity index 98% rename from dslink-java-v2-poc/src/main/java/org/iot/dsa/dslink/test/MainNode.java rename to dslink-java-v2-poc/src/main/java/org/iot/dsa/dslink/poc/MainNode.java index b65a014e..351fa78a 100644 --- a/dslink-java-v2-poc/src/main/java/org/iot/dsa/dslink/test/MainNode.java +++ b/dslink-java-v2-poc/src/main/java/org/iot/dsa/dslink/poc/MainNode.java @@ -1,4 +1,4 @@ -package org.iot.dsa.dslink.test; +package org.iot.dsa.dslink.poc; import org.iot.dsa.DSRuntime; import org.iot.dsa.dslink.DSMainNode; @@ -96,7 +96,8 @@ public void onRemove(String name) { @Override public void onUpdate(String name, DSElement value) { - System.out.println("list update " + name); + System.out.print(name); + System.out.print(": "); System.out.println(String.valueOf(value)); } diff --git a/dslink-websocket-standalone/build.gradle b/dslink-websocket-standalone/build.gradle index 2b8d354f..d61d3d39 100644 --- a/dslink-websocket-standalone/build.gradle +++ b/dslink-websocket-standalone/build.gradle @@ -2,5 +2,56 @@ apply from: '../build.gradle' dependencies { compile project(':dslink-core') - compile 'org.glassfish.tyrus.bundles:tyrus-standalone-client:+' + compile 'org.glassfish.tyrus.bundles:tyrus-standalone-client:[1.12,)' +} + +signing { + required { gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives +} + +uploadArchives { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + pom.project { + name = 'DSLink SDK V2 Websocket Implementation' + artifactId = 'dslink-websocket-standalone-v2' + description = 'V2 Implementation of Websockets for IoT DSA protocol' + + packaging = 'jar' + url = 'http://iot-dsa.org' + + scm { + connection = 'scm:git:https://github.com/iot-dsa-v2/sdk-dslink-java-v2.git' + developerConnection = 'scm:git:git@github.com:iot-dsa-v2/sdk-dslink-java-v2.git' + url = 'https://github.com/iot-dsa-v2/sdk-dslink-java-v2' + } + + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + + developers { + developer { + id = 'samrg472' + name = 'Samuel Grenier' + email = 'samrg472@gmail.com' + } + } + } + } + } } diff --git a/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsBinaryTransport.java b/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsBinaryTransport.java index 916d40b5..82eae3bc 100644 --- a/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsBinaryTransport.java +++ b/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsBinaryTransport.java @@ -5,15 +5,9 @@ import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; -import javax.websocket.ClientEndpoint; -import javax.websocket.CloseReason; -import javax.websocket.EndpointConfig; -import javax.websocket.OnClose; -import javax.websocket.OnError; -import javax.websocket.OnMessage; -import javax.websocket.OnOpen; -import javax.websocket.RemoteEndpoint; -import javax.websocket.Session; +import java.util.List; +import java.util.Map; +import javax.websocket.*; import org.glassfish.tyrus.client.ClientManager; import org.iot.dsa.util.DSException; diff --git a/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsTextTransport.java b/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsTextTransport.java index 842b95a9..1c14e0e2 100644 --- a/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsTextTransport.java +++ b/dslink-websocket-standalone/src/main/java/org/iot/dsa/dslink/websocket/WsTextTransport.java @@ -8,15 +8,9 @@ import java.io.Reader; import java.io.Writer; import java.net.URI; -import javax.websocket.ClientEndpoint; -import javax.websocket.CloseReason; -import javax.websocket.EndpointConfig; -import javax.websocket.OnClose; -import javax.websocket.OnError; -import javax.websocket.OnMessage; -import javax.websocket.OnOpen; -import javax.websocket.RemoteEndpoint; -import javax.websocket.Session; +import java.util.List; +import java.util.Map; +import javax.websocket.*; import org.glassfish.tyrus.client.ClientManager; import org.iot.dsa.util.DSException; diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..3858cc1d --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +ossrhUsername="" +ossrhPassword="" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265ee..f6b961fd 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ea720f98..2d80b69a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip diff --git a/gradlew b/gradlew old mode 100644 new mode 100755