diff --git a/gradle/swt.gradle b/scripts/gradle/swt.gradle
similarity index 63%
rename from gradle/swt.gradle
rename to scripts/gradle/swt.gradle
index a41839b..d3a1d0d 100644
--- a/gradle/swt.gradle
+++ b/scripts/gradle/swt.gradle
@@ -1,4 +1,13 @@
String getSWTWindowingLibrary() {
+ if (ext.has('swt')) {
+ switch (ext.swt) {
+ case ~/.*linux.*/: return 'gtk'
+ case ~/.*mac.*/: return 'cocoa'
+ case ~/.*win.*/: return 'win32'
+ default: return null
+ }
+ }
+
String platform = System.properties['os.name']
switch (platform.replaceAll(' ', '').toLowerCase()) {
@@ -13,6 +22,10 @@ String getSWTWindowingLibrary() {
String getSWTArch() {
String arch = System.properties['os.arch']
+ if (ext.has('swt')) {
+ arch = ext.swt
+ }
+
switch (arch) {
case ~/.*64.*/: return 'x86_64'
default: return 'x86'
@@ -20,6 +33,15 @@ String getSWTArch() {
}
String getSWTPlatform() {
+ if (ext.has('swt')) {
+ switch (ext.swt) {
+ case ~/.*linux.*/: return 'linux'
+ case ~/.*mac.*/: return 'macosx'
+ case ~/.*win.*/: return 'win32'
+ default: return null
+ }
+ }
+
String platform = System.properties['os.name']
switch (platform.replaceAll(' ', '').toLowerCase()) {
@@ -31,6 +53,9 @@ String getSWTPlatform() {
}
}
+// optionally let us specify which SWT to use. options are win32/mac32/linux32 and win64/mac64/linux64
+// include this in your build.gradle file, before dependencies are determined. ext.swt = 'win64'
+
ext {
// because the eclipse release of SWT is abandoned on maven, this MAVEN repo has newer version of SWT,
// https://github.com/maven-eclipse/maven-eclipse.github.io (for the website about it)
diff --git a/src/dorkbox/util/Base64Fast.java b/src/dorkbox/util/Base64Fast.java
index faba23e..34f3dc7 100644
--- a/src/dorkbox/util/Base64Fast.java
+++ b/src/dorkbox/util/Base64Fast.java
@@ -15,8 +15,11 @@
*/
package dorkbox.util;
+import java.io.IOException;
import java.util.Arrays;
+import javax.xml.bind.DatatypeConverter;
+
/** A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance
* with RFC 2045.
* On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is about 10 times faster
@@ -25,7 +28,7 @@ import java.util.Arrays;
*
* On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and
* about 50% faster for decoding large arrays. This implementation is about twice as fast on very small
- * arrays (< 30 bytes). If source/destination is a String
this
+ * arrays (< 30 bytes). If source/destination is a String
this
* version is about three times as fast due to the fact that the Commons Codec result has to be recoded
* to a String
from byte[]
, which is very expensive.
*
@@ -97,6 +100,50 @@ public class Base64Fast
IA['='] = 0;
}
+ /**
+ * Formats data into a nicely formatted base64 encoded String
+ *
+ * @param s A string containing the base64 encoded data
+ * @param lineLength The number of characters per line
+ * @param prefix A string prefixing the characters on each line
+ * @param addClose Whether to add a close parenthesis or not
+ *
+ * @return A String representing the formatted output
+ */
+ public static
+ String formatString(String s, int lineLength, String prefix, boolean addClose) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < s.length(); i += lineLength) {
+ sb.append(prefix);
+ if (i + lineLength >= s.length()) {
+ sb.append(s.substring(i));
+ if (addClose) {
+ sb.append(" )");
+ }
+ }
+ else {
+ sb.append(s.substring(i, i + lineLength));
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ public static
+ String encode2(byte[] data) {
+ // will skip/ignore invalid chars!
+ return DatatypeConverter.printBase64Binary(data);
+ }
+
+ public static
+ byte[] decode2(String base64) throws IOException {
+ // this is the fastest way to do string->byte conversion
+ // http://java-performance.info/base64-encoding-and-decoding-performance/
+ // will skip/ignore invalid chars!
+ return DatatypeConverter.parseBase64Binary(base64);
+ }
+
+
// ****************************************************************************************
// * char[] version
// ****************************************************************************************
diff --git a/src/dorkbox/util/Version.java b/src/dorkbox/util/Version.java
deleted file mode 100644
index c14123d..0000000
--- a/src/dorkbox/util/Version.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright 2017 dorkbox, llc
- *
- * Licensed 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.
- */
-package dorkbox.util;
-
-import java.util.Locale;
-
-/**
- * Version a = new Version("1.1");
- * Version b = new Version("1.1.1");
- * a.compareTo(b) // return -1 (a
- * Version a = new Version("2.0");
- * Version b = new Version("1.9.9");
- * a.compareTo(b) // return 1 (a>b)
- * a.equals(b) // return false
- *
- * Version a = new Version("1.0");
- * Version b = new Version("1");
- * a.compareTo(b) // return 0 (a=b)
- * a.equals(b) // return true
- *
- * Version a = new Version("1");
- * Version b = null;
- * a.compareTo(b) // return 1 (a>b)
- * a.equals(b) // return false
- *
- * List versions = new ArrayList();
- * versions.add(new Version("2"));
- * versions.add(new Version("1.0.5"));
- * versions.add(new Version("1.01.0"));
- * versions.add(new Version("1.00.1"));
- * Collections.min(versions).get() // return min version
- * Collections.max(versions).get() // return max version
- *
- * // WARNING
- * Version a = new Version("2.06");
- * Version b = new Version("2.060");
- * a.equals(b) // return false
- *
- *
- * If the numbers are the same, then
- * BETA+BUILD < BETA < STABLE+BUILD < STABLE.
- *
- * Stable is a version that is exclusively numbers. Builds are always equal, even if a different build commit hash/etc.
- */
-@SuppressWarnings({"unused", "SimplifiableIfStatement", "WeakerAccess"})
-public
-class Version implements Comparable {
- private static final int[] PRIME = {2, 3, 5};
-
- // protected scope to permit overriding functionality
-
- protected String version;
- protected int[] internalVersion;
-
- protected boolean isBeta;
- protected String build;
-
- protected
- Version() {
- // no-arg for serialization
- }
-
- /**
- * Creates a comparable version based on only numbers
- *
- * @param version must consist of just numbers with a maximum of 1 decimal point
- */
- public
- Version(double version) {
- this(Double.toString(version), false, null);
- }
-
- /**
- * Creates a comparable version from a string
- *
- * @param version The version part must consist of just numbers with a maximum of 3 groups separated by a '.' and BETA or BUILD info
- */
- public
- Version(String version) {
- this(Version.fromString(version));
- }
-
- /**
- * Creates a comparable version based on an existing version
- */
- public
- Version(final Version version) {
- this.version = version.version;
- this.internalVersion = version.internalVersion;
- this.isBeta = version.isBeta;
- this.build = version.build;
- }
-
- /**
- * Creates a comparable version based on numbers, BETA status, and BUILD
- *
- * @param version must consist of only numbers with a maximum of 3 groups separated by a '.' Leading '0' will be removed
- * @param isBeta true if this is a beta build
- * @param build custom build info, such as the commit sha hash
- */
- public
- Version(String version, boolean isBeta, String build) {
- if (version == null) {
- throw new IllegalArgumentException("Version can not be null");
- }
- if (!version.matches("[0-9]+(\\.[0-9]+){0,3}")) {
- throw new IllegalArgumentException("Invalid version format");
- }
-
- if (build != null) {
- this.build = build.toLowerCase(Locale.US);
- }
- else {
- this.build = null;
- }
-
- this.isBeta = isBeta;
- this.version = version;
-
- String[] parts = this.version.split("\\.");
- internalVersion = new int[parts.length];
-
- for (int i = 0; i < parts.length; i++) {
- final String s = parts[i];
- internalVersion[i] = Integer.parseInt(s);
- }
- }
-
- /**
- * Creates a comparable version based on only numbers
- */
- public
- Version(String... version) {
- if (version == null) {
- throw new IllegalArgumentException("Version can not be null");
- }
-
- int length = version.length;
- if (length > 3) {
- throw new IllegalArgumentException("Invalid version format");
- }
-
- this.build = null;
- this.isBeta = false;
-
- StringBuilder builder = new StringBuilder(length + 3);
- internalVersion = new int[length];
- for (int i = 0; i < length; i++) {
- final String s = version[i];
- // must be a number
- internalVersion[i] = Integer.parseInt(s);
- builder.append(s)
- .append('.');
- }
-
- this.version = builder.toString();
- }
-
- /**
- * Creates a comparable version based on only numbers
- */
- public
- Version(int... version) {
- if (version == null) {
- throw new IllegalArgumentException("Version can not be null");
- }
-
- if (version.length > 3) {
- throw new IllegalArgumentException("Invalid version format");
- }
-
- this.build = null;
- this.isBeta = false;
-
- StringBuilder builder = new StringBuilder(version.length + 3);
- internalVersion = new int[version.length];
- for (int i = 0; i < version.length; i++) {
- internalVersion[i] = version[i];
- builder.append(i)
- .append('.');
- }
-
- this.version = builder.toString();
- }
-
- /**
- * Converts a version into a "beta" version, without any additional build information
- *
- * BETA+BUILD < BETA < STABLE+BUILD < STABLE.
- * Stable is a version that is exclusively numbers. Builds are always equal, even if a different build commit hash/etc.
- */
- public
- Version beta() {
- this.isBeta = true;
- return this;
- }
-
- /**
- * Creates a version with specific build information (such as sha commit hash, etc)
- *
- * BETA+BUILD < BETA < STABLE+BUILD < STABLE.
- * Stable is a version that is exclusively numbers. Builds are always equal, even if a different build commit hash/etc.
- */
- public
- Version build(String build) {
- this.build = build;
- return this;
- }
-
- /**
- * @return the version information, as an array.
- */
- public
- int[] getVersion() {
- return internalVersion;
- }
-
- /**
- * @return true if this version is a beta or not
- */
- public
- boolean isBeta() {
- return isBeta;
- }
-
- /**
- * @return the build information, if any
- */
- public
- String getBuild() {
- return build;
- }
-
- public
- boolean isGreater(Object that) {
- if (this == that) {
- return false;
- }
- if (that == null) {
- return true;
- }
- if (this.getClass() != that.getClass()) {
- return false;
- }
-
- return this.compareTo((Version) that) > 0;
- }
-
- public
- boolean isGreaterOrEquals(Object that) {
- if (this == that) {
- return true;
- }
- if (that == null) {
- return true;
- }
- if (this.getClass() != that.getClass()) {
- return false;
- }
-
- return this.compareTo((Version) that) >= 0;
- }
-
- public
- boolean isLess(Object that) {
- if (this == that) {
- return false;
- }
- if (that == null) {
- return false;
- }
- if (this.getClass() != that.getClass()) {
- return false;
- }
-
- return this.compareTo((Version) that) < 0;
- }
-
- public
- boolean isLessOrEquals(Object that) {
- if (this == that) {
- return true;
- }
- if (that == null) {
- return false;
- }
- if (this.getClass() != that.getClass()) {
- return false;
- }
-
- return this.compareTo((Version) that) <= 0;
- }
-
- public
- boolean isEquals(Object that) {
- return equals(that);
- }
-
- @Override
- public
- boolean equals(Object that) {
- if (this == that) {
- return true;
- }
-
- if (that == null) {
- return false;
- }
- if (this.getClass() != that.getClass()) {
- return false;
- }
-
- return this.compareTo((Version) that) == 0;
- }
-
- @Override
- public
- int compareTo(Version that) {
- if (that == null) {
- return 1;
- }
-
- int[] thisParts = this.internalVersion;
- int[] thatParts = that.internalVersion;
-
- int maxLength = Math.max(thisParts.length, thatParts.length);
-
- for (int i = 0; i < maxLength; i++) {
- int thisPart;
- if (i < thisParts.length) {
- thisPart = thisParts[i];
- }
- else {
- thisPart = 0;
- }
-
- int thatPart;
- if (i < thatParts.length) {
- thatPart = thatParts[i];
- }
- else {
- thatPart = 0;
- }
-
- if (thisPart < thatPart) {
- return -1;
- }
- if (thisPart > thatPart) {
- return 1;
- }
- }
-
- // our numbers are all equal, now determine equality based on BETA/BUILD info
-
- // BETA+BUILD < BETA < STABLE+BUILD < STABLE.
- // Stable is a version that is exclusively numbers. Builds are always equal, even if a different build commit hash/etc.
-
- if (this.isBeta) {
- if (this.build != null) {
- if (that.isBeta) {
- if (that.build != null) {
- // BETA+BUILD == BETA+BUILD
- return 0;
- }
- // BETA+BUILD < BETA
- return -1;
- }
- // BETA+BUILD < STABLE+BUILD < STABLE
- return -1;
- }
- else {
- if (that.isBeta) {
- if (that.build != null) {
- // BETA > BETA+BUILD
- return 1;
- }
- // BETA == BETA
- return 0;
- }
- // BETA < STABLE+BUILD < STABLE
- return -1;
- }
- }
-
- // else this is STABLE or STABLE+BUILD
-
- if (this.build != null) {
- if (that.isBeta) {
- // STABLE+BUILD > BETA > BETA+BUILD
- return 1;
- }
- if (that.build != null) {
- // STABLE+BUILD == STABLE+BUILD
- return 0;
- }
- // STABLE+BUILD < STABLE
- return -1;
- }
- else {
- if (that.isBeta) {
- // STABLE > BETA > BETA+BUILD
- return 1;
- }
- if (that.build != null) {
- // STABLE > STABLE+BUILD
- return 1;
- }
- // STABLE == STABLE
- return 0;
- }
- }
-
-
- @Override
- public final
- int hashCode() {
- // better hashing than just using .toString().hashCode()
- int hashCode = 0;
- for (int i = 0; i < internalVersion.length; i++) {
- final int part = internalVersion[i];
- if (part > 0) {
- hashCode += PRIME[i] ^ part;
- }
- }
-
- if (build != null) {
- hashCode += build.hashCode();
- }
-
- return hashCode;
- }
-
- /**
- * Converts version information from a string
- *
- * @param string The version string, as received by {@link Version#toString()}
- */
- public static
- Version fromString(String string) {
- int betaIndex = string.indexOf("-BETA");
- int buildIndex = string.indexOf("+");
- int lastIndex = string.length();
-
-
- boolean isBeta = betaIndex > 0;
- String build = null;
- if (buildIndex > 0) {
- build = string.substring(buildIndex + 1, lastIndex);
- lastIndex = buildIndex;
- }
-
- if (isBeta) {
- lastIndex = betaIndex;
- }
-
- String version = string.substring(0, lastIndex);
-
- return new Version(version, isBeta, build);
- }
-
- @Override
- public
- String toString() {
- if (isBeta) {
- if (build != null) {
- return version + "-BETA+" + build;
- }
- return version + "-BETA";
- }
- if (build != null) {
- return version + "+" + build;
- }
- return version;
- }
-}
diff --git a/src/dorkbox/util/userManagement/Group.java b/src/dorkbox/util/userManagement/Group.java
new file mode 100644
index 0000000..4902f8f
--- /dev/null
+++ b/src/dorkbox/util/userManagement/Group.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2018 dorkbox, llc
+ *
+ * Licensed 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.
+ */
+package dorkbox.util.userManagement;
+
+import java.io.Serializable;
+import java.util.*;
+
+// TODO: this class needs to save itself to the database on changes
+/**
+ * Plugable group object for user management
+ */
+public final
+class Group implements Serializable {
+
+ private final UUID uuid;
+ private String name;
+
+ private Set users = new HashSet();
+
+ public
+ Group(final String name) {
+ this(name, UserManagement.UUID_GENERATOR.generate());
+ }
+
+ Group(final String name, final UUID uuid) {
+ this.name = name;
+ this.uuid = uuid;
+ }
+
+ public
+ UUID getUuid() {
+ return uuid;
+ }
+
+ public
+ String getName() {
+ return name;
+ }
+
+ public synchronized
+ void addUser(UUID user) {
+ users.add(user);
+ }
+
+ public synchronized
+ void removeUser(UUID user) {
+ users.remove(user);
+ }
+
+ public synchronized
+ Collection getUsers() {
+ return Collections.unmodifiableCollection(users);
+ }
+
+ public synchronized
+ boolean isEmpty() {
+ return users.isEmpty();
+ }
+
+ public synchronized
+ void remove() {
+ // UserManagement.Groups.remove(this);
+
+ // for (User user : users) {
+ // user.removeGroup(this);
+ // }
+
+ users.clear();
+ }
+
+ @Override
+ public
+ String toString() {
+ return "Group '" + name + '\'';
+ }
+
+ @Override
+ public
+ boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final Group group = (Group) o;
+
+ return uuid != null ? uuid.equals(group.uuid) : group.uuid == null;
+ }
+
+ @Override
+ public
+ int hashCode() {
+ return uuid != null ? uuid.hashCode() : 0;
+ }
+}
diff --git a/src/dorkbox/util/userManagement/User.java b/src/dorkbox/util/userManagement/User.java
new file mode 100644
index 0000000..aea78ee
--- /dev/null
+++ b/src/dorkbox/util/userManagement/User.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2018 dorkbox, llc
+ *
+ * Licensed 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.
+ */
+package dorkbox.util.userManagement;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+// TODO: this class needs to save itself to the database on changes
+
+
+public
+class User implements Serializable {
+ /** Global, unique ID for this user. This is the only thing used to determine equality */
+ private final UUID uuid;
+
+ /** Random, per-user salt that is used for secure password hashing */
+ private final byte[] salt = new byte[256];
+
+ /** user name assigned. Equality is determined by the UUID, so depending on use, the name does not have to be unique. */
+ protected String name;
+
+ /** This is the groups that this user is a member of */
+ private final Set groups = new HashSet();
+
+ public
+ User() {
+ uuid = UserManagement.UUID_GENERATOR.generate();
+ UserManagement.RANDOM.nextBytes(salt);
+ }
+
+ User(final UUID uuid, final byte[] salt) {
+ this.uuid = uuid;
+
+ // set the salt
+ for (int i = 0, saltLength = salt.length; i < saltLength; i++) {
+ this.salt[i] = salt[i];
+ }
+ }
+
+ /**
+ * @return the global, unique ID for this user. This is the only thing used to determine equality
+ */
+ public final
+ UUID getUUID() {
+ return uuid;
+ }
+
+ /**
+ * @return a random, per-user salt that is used for secure password hashing
+ */
+ public final
+ byte[] getSalt() {
+ return salt;
+ }
+
+ /**
+ * @return an unmodifiable set of groups this user is a member of
+ */
+ public final
+ Set getGroups() {
+ return Collections.unmodifiableSet(groups);
+ }
+
+
+ /**
+ * @return the user name assigned. Equality is determined by the UUID, so depending on use, the name does not have to be unique.
+ */
+ public final
+ String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the user name to be assigned. Equality is determined by the UUID, so depending on use, the name does not have to be unique.
+ */
+ public final
+ void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public final
+ boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final User user = (User) o;
+
+ return uuid.equals(user.uuid);
+ }
+
+ @Override
+ public final
+ int hashCode() {
+ return uuid.hashCode();
+ }
+
+ @Override
+ public final
+ String toString() {
+ return "User {" + uuid + ", '" + name + '\'' + '}';
+ }
+}
diff --git a/src/dorkbox/util/userManagement/UserManagement.java b/src/dorkbox/util/userManagement/UserManagement.java
new file mode 100644
index 0000000..0e53ef3
--- /dev/null
+++ b/src/dorkbox/util/userManagement/UserManagement.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright 2018 dorkbox, llc
+ *
+ * Licensed 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.
+ */
+package dorkbox.util.userManagement;
+
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
+import com.fasterxml.uuid.impl.UUIDUtil;
+
+/**
+ * todo: this class should load/save itself to the database
+ */
+public final
+class UserManagement {
+ private static final Logger logger = LoggerFactory.getLogger(UserManagement.class.getSimpleName());
+
+ static final RandomBasedGenerator UUID_GENERATOR = Generators.randomBasedGenerator();
+ static final SecureRandom RANDOM = new SecureRandom();
+
+ public final Group ADMIN;
+
+ private Map users = new HashMap();
+ private Map groups = new HashMap();
+
+ public
+ UserManagement() {
+ // the "system/admin/root" group MUST always be all "0"
+ final byte[] buffer = new byte[16];
+ for (int i = 0, bufferLength = buffer.length; i < bufferLength; i++) {
+ buffer[i] = 0;
+ }
+
+ UUID uuid = UUIDUtil.uuid(buffer);
+ ADMIN = new Group("System", uuid);
+
+ // the "system/root" group MUST always be all "0"
+ groups.put(uuid, ADMIN);
+ }
+
+ public
+ User authenticate(String user) {
+ return null;
+ }
+
+
+ // public
+ // byte[] generateUserNameHash(String username) {
+ // return HashUtil.getSha256WithSalt(username, getSalt());
+ // }
+
+
+
+
+ /////////////////
+ /// user/group create/add/remove/get actions
+ /////////////////
+
+ public
+ User createUser() {
+ User user = new User();
+ addUser(user);
+ return user;
+ }
+
+ private
+ void addUser(User user) {
+ // users.add(user);
+ }
+
+ private
+ void removeUser(User user) {
+ users.remove(user);
+ }
+
+ public
+ Map getUsers() {
+ return Collections.unmodifiableMap(users);
+ }
+
+ public
+ User getUser(final UUID uuid) {
+ return users.get(uuid);
+ }
+
+ public
+ Group createGroup(String groupName) {
+ Group group = new Group(groupName);
+ addGroup(group);
+ return group;
+ }
+
+ public
+ void addGroup(final Group group) {
+ // groups.add(group);
+ }
+
+ public
+ void removeGroup(final Group group) {
+ if (group != ADMIN) {
+ groups.remove(group);
+ }
+ }
+
+ // public
+ // Collection getGroups() {
+ // return Collections.unmodifiableCollection(groups);
+ // }
+ //
+ // /**
+ // * @param user the user to check
+ // * @return true if this user is in the admin group
+ // */
+ // public
+ // boolean isAdminGroup(final User user) {
+ // return ADMIN.getUsers()
+ // .contains(user.getUUID());
+ // }
+ //
+ //
+ // /**
+ // * check if a user is the admin user
+ // *
+ // * @return false if not admin, or NOT called from the console
+ // */
+ // public synchronized
+ // boolean isAdminUser(final byte[] userNameHash) {
+ // if (userNameHash == null || userNameHash.length == 0) {
+ // return false;
+ // }
+ //
+ // if (!checkAccessNoExit(SystemLoginImpl.class, AdminActions.class, ConsoleServer.class)) {
+ // return false;
+ // }
+ //
+ //
+ // if (adminUserHash == null) {
+ // Exit.FailedConfiguration("Unable to read admin user from the database. FORCED SHUTDOWN.");
+ // return false;
+ // }
+ // else {
+ // if (Arrays.equals(adminUserHash, userNameHash)) {
+ // return true;
+ // }
+ // else {
+ // AdminActions.this.logger.info("User is not the admin user");
+ // return false; // user not the same
+ // }
+ // }
+ // }
+ //
+ // /**
+ // * Set's the admin user for this server. This user should already exist!
+ // *
+ // * @return errormessage, if there are errors, null otherwise
+ // */
+ // public synchronized
+ // String setAdminUser(final byte[] userNameHash, final byte[] currentAdminPasswordHash) {
+ // try {
+ // checkAccess(AdminActions.class, ConsoleServer.class);
+ // } catch (SecurityException e) {
+ // Exit.FailedSecurity(e);
+ // }
+ //
+ // // only check the password if we have an admin user!
+ // if (adminUserHash != null) {
+ // final ByteArrayWrapper adminUserHashWrap = ByteArrayWrapper.wrap(adminUserHash);
+ // DB_User user = users.get(adminUserHashWrap);
+ // if (user != null) {
+ // if (!Arrays.equals(user.getPasswordHash(), currentAdminPasswordHash)) {
+ // String mesg = "Incorrect admin password.";
+ // AdminActions.this.logger.info(mesg);
+ // return mesg;
+ // }
+ // }
+ // else {
+ // String mesg = "Invalid user!";
+ // AdminActions.this.logger.info(mesg);
+ // return mesg;
+ // }
+ // }
+ //
+ // final ByteArrayWrapper userHashWrap = ByteArrayWrapper.wrap(userNameHash);
+ // DB_User user = users.get(userHashWrap);
+ // if (user == null) {
+ // String mesg = "User doesn't exist.";
+ // AdminActions.this.logger.info(mesg);
+ // return mesg;
+ // }
+ //
+ // adminUserHash = userNameHash;
+ //
+ // // have to always specify what we are saving
+ // storage.put(DatabaseStorage.ADMIN_HASH, adminUserHash);
+ //
+ // return null;
+ // }
+ //
+ // /**
+ // * Adds a user to the system. beware userName != usernamehash
+ // *
+ // * @return the error message, null if successful.
+ // */
+ // public synchronized
+ // String addUser(final String userName, final byte[] userNameHash, final byte[] passwordHash) {
+ // try {
+ // checkAccess(AdminActions.class, ConsoleServer.class);
+ // } catch (SecurityException e) {
+ // Exit.FailedSecurity(e);
+ // }
+ //
+ // String validateLogin = Validation.userName(userName);
+ // Logger logger2 = this.logger;
+ // if (validateLogin != null) {
+ // String mesg = "Unable to create user account ( " + userName + " ). Reason: " + validateLogin;
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info("{} Reason: {}", mesg, validateLogin);
+ // }
+ // return mesg;
+ // }
+ //
+ // final ByteArrayWrapper userNameHashWrap = ByteArrayWrapper.wrap(userNameHash);
+ //
+ // // only once, to save memory
+ // DB_User user = users.get(userNameHashWrap);
+ //
+ // if (user != null) {
+ // String mesg = "Unable to create user account ( " + userName + " ). Reason: User already exists";
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info(mesg);
+ // }
+ // return mesg;
+ // }
+ // else {
+ // user = new DB_User();
+ // user.setName(userName);
+ // user.setNameHash(userNameHash);
+ // user.setPasswordHash(passwordHash);
+ //
+ // users.put(userNameHashWrap, user);
+ // // have to always specify what we are saving
+ // storage.put(DatabaseStorage.USERS, users);
+ //
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info("Added user ({})", userName);
+ // }
+ // return null; // success!
+ // }
+ // }
+ //
+ // /**
+ // * remove a user + userName hash.
+ // *
+ // * @return true if removed, false if the user could not be removed.
+ // */
+ // public synchronized
+ // boolean removeUser(final byte[] userNameHash) {
+ // final ByteArrayWrapper userNameHashWrap = ByteArrayWrapper.wrap(userNameHash);
+ // DB_User user = users.get(userNameHashWrap);
+ //
+ // Logger logger2 = this.logger;
+ // if (user != null) {
+ // byte[] userNameCheck = user.getNameHash();
+ // if (Arrays.equals(userNameHash, userNameCheck) && !isAdminUser(userNameHash)) {
+ //
+ // DB_User removedUser = users.remove(userNameHashWrap);
+ // String name = user.getName();
+ //
+ // if (removedUser != null) {
+ // // have to always specify what we are saving
+ // storage.put(DatabaseStorage.USERS, users);
+ // return true;
+ // }
+ // else {
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info("Problem removing the user ({}). Does not exist.", name);
+ // }
+ // return false; // problem removing the user
+ // }
+ // }
+ // }
+ //
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info("Problem removing unknown user");
+ // }
+ // return false; // problem removing the user
+ // }
+ //
+ // /**
+ // * Force set the password for a user in the system.
+ // *
+ // * @return the error message, null if successful.
+ // */
+ // public synchronized
+ // String setPasswordUser(final byte[] userNameHash, final byte[] passwordHash, final byte[] adminPasswordHash) {
+ // try {
+ // checkAccess(ConsoleServer.class);
+ // } catch (SecurityException e) {
+ // Exit.FailedSecurity(e);
+ // }
+ //
+ // final ByteArrayWrapper adminUserHashWrap = ByteArrayWrapper.wrap(adminPasswordHash);
+ // DB_User adminUser = users.get(adminUserHashWrap);
+ //
+ // Logger logger2 = this.logger;
+ // if (adminUser == null || !Arrays.equals(adminUser.getPasswordHash(), adminPasswordHash)) {
+ // String mesg = "Unable to authenticate admin password.";
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info(mesg);
+ // }
+ // return mesg;
+ // }
+ //
+ // final ByteArrayWrapper userNameHashWrap = ByteArrayWrapper.wrap(userNameHash);
+ // DB_User user = users.get(userNameHashWrap);
+ // if (user != null) {
+ // user.setPasswordHash(passwordHash);
+ // // have to always specify what we are saving
+ // storage.put(DatabaseStorage.USERS, users);
+ //
+ // String name = user.getName();
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info("Reset password for user ({})", name);
+ // }
+ // return null; // success!
+ // }
+ // else {
+ // String mesg = "Unable to change the password for non-existant user.";
+ // if (logger2.isInfoEnabled()) {
+ // logger2.info(mesg);
+ // }
+ // return mesg;
+ // }
+ // }
+ //
+ // /**
+ // * faster check that userExists(), as it only check the hash
+ // */
+ // public synchronized
+ // User getUser(final byte[] usernameHash) {
+ // if (usernameHash == null) {
+ // return null;
+ // }
+ //
+ // try {
+ // checkAccess(SystemLoginImpl.class, AdminActions.class, ConsoleServer.class);
+ // } catch (SecurityException e) {
+ // Exit.FailedSecurity(e);
+ // }
+ //
+ // return users.get(ByteArrayWrapper.wrap(usernameHash));
+ // }
+ //
+ // /**
+ // * gets the user password given the userName hash
+ // *
+ // * @return NON NULL VALUE
+ // */
+ // public synchronized
+ // byte[] getPasswordHash(final byte[] userNameHash) {
+ // if (userNameHash == null || userNameHash.length == 0) {
+ // return new byte[0];
+ // }
+ //
+ // try {
+ // checkAccess(AdminActions.class);
+ // } catch (SecurityException e) {
+ // Exit.FailedSecurity(e);
+ // }
+ //
+ //
+ // DB_User user = users.get(ByteArrayWrapper.wrap(userNameHash));
+ // if (user != null) {
+ // return user.getPasswordHash();
+ // }
+ //
+ // return new byte[0];
+ // }
+ //
+ // public
+ // Group getGroup(final UUID uuid) {
+ // return groups.();
+ // }
+
+
+
+ // public synchronized final boolean isValidUser(String userName, char[] password) {
+// String storedToken = properties.get(AdminActions.USER_PREFIX + userName, String.class);
+// String storedPasswd = properties.get(AdminActions.USER_PWD_PREFIX + userName, String.class);
+//
+// if (storedToken == null || storedToken.isEmpty()) {
+// return false;
+// } else {
+// ifObject (!token.equals(storedToken)) {
+// return false;
+// }
+// }
+//
+// return false;
+// // check to see if the password matches
+//// return SCrypt.check(password, storedPasswd);
+// }
+
+}