Merge the matrix-java-sdk due to it no longer maintained. Remove thirdparty repositories.

This commit is contained in:
Anatoly Sablin
2019-07-07 23:13:59 +03:00
parent 136563c61a
commit c3262a9f25
126 changed files with 9058 additions and 8 deletions

View File

@@ -82,8 +82,6 @@ buildscript {
repositories { repositories {
jcenter() jcenter()
maven { url "https://kamax.io/maven/releases/" }
maven { url "https://kamax.io/maven/snapshots/" }
} }
dependencies { dependencies {
@@ -96,14 +94,16 @@ dependencies {
// Config management // Config management
compile 'org.yaml:snakeyaml:1.23' compile 'org.yaml:snakeyaml:1.23'
// Matrix Java SDK // Dependencies from old Matrix-java-sdk
compile 'io.kamax:matrix-java-sdk:0.0.14-8-g0e57ec6' compile 'org.apache.commons:commons-lang3:3.8.1'
compile 'com.squareup.okhttp3:okhttp:3.12.0'
compile 'commons-codec:commons-codec:1.11'
// ORMLite // ORMLite
compile 'com.j256.ormlite:ormlite-jdbc:5.0' compile 'com.j256.ormlite:ormlite-jdbc:5.0'
// ed25519 handling // ed25519 handling
compile 'net.i2p.crypto:eddsa:0.1.0' compile 'net.i2p.crypto:eddsa:0.3.0'
// LDAP connector // LDAP connector
compile 'org.apache.directory.api:api-all:1.0.0' compile 'org.apache.directory.api:api-all:1.0.0'

View File

@@ -1,5 +1,6 @@
#Thu Jul 04 22:47:59 MSK 2019
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View File

@@ -0,0 +1,33 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class MalformedEventException extends MatrixException {
public MalformedEventException(String s) {
super("M_NOT_JSON", s);
}
public static MalformedEventException forId(String id) {
return new MalformedEventException("Event " + id + " is malformed");
}
}

View File

@@ -0,0 +1,44 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class MatrixErrorInfo {
private String errcode;
private String error;
public MatrixErrorInfo(String errcode) {
this.errcode = errcode;
}
public MatrixErrorInfo(Throwable t) {
this.errcode = "AS_INTERNAL_SERVER_ERROR";
}
public String getErrcode() {
return errcode;
}
public String getError() {
return error;
}
}

View File

@@ -0,0 +1,48 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class MatrixException extends RuntimeException {
private String errorCode;
private String error;
public MatrixException(String errorCode, String error) {
super(errorCode + ": " + error);
this.errorCode = errorCode;
this.error = error;
}
public MatrixException(String errorCode, String error, Throwable t) {
super(errorCode + ": " + error, t);
this.errorCode = errorCode;
this.error = error;
}
public String getErrorCode() {
return errorCode;
}
public String getError() {
return error;
}
}

View File

@@ -0,0 +1,170 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatrixID implements _MatrixID {
public static class Builder {
private MatrixID mxId;
public Builder(String id) {
mxId = MatrixID.parse(id);
}
public MatrixID valid() {
if (!mxId.isValid()) {
throw new IllegalArgumentException(mxId + " is not a valid Matrix ID");
}
return mxId;
}
public MatrixID acceptable() {
if (!mxId.isAcceptable()) {
throw new IllegalArgumentException(mxId + " is not an acceptable Matrix ID");
}
return mxId;
}
}
public static final String ALLOWED_CHARS = "0-9a-z-.=_/";
public static final Pattern LAX_PATTERN = Pattern.compile("@(.*?):(.+)");
public static final Pattern STRICT_PATTERN = Pattern.compile("@([" + ALLOWED_CHARS + "]+):(.+)");
private String id;
private String localpart;
private String domain;
private static String buildRaw(String localpart, String domain) {
return "@" + localpart + ":" + domain;
}
private static MatrixID parse(String id) {
Matcher m = LAX_PATTERN.matcher(id);
if (!m.matches()) {
throw new IllegalArgumentException(id + " is not a Matrix ID");
}
MatrixID mxId = new MatrixID();
mxId.id = id;
mxId.localpart = m.group(1);
mxId.domain = m.group(2);
return mxId;
}
public static Builder from(String id) {
return new Builder(id);
}
public static Builder from(String local, String domain) {
return from(buildRaw(local, domain));
}
public static MatrixID asValid(String id) {
return new Builder(id).valid();
}
public static MatrixID asAcceptable(String local, String domain) {
return from(local, domain).acceptable();
}
public static MatrixID asAcceptable(String id) {
return from(id).acceptable();
}
private MatrixID() {
// not for public consumption
}
private MatrixID(MatrixID mxId) {
this.id = mxId.id;
this.localpart = mxId.localpart;
this.domain = mxId.domain;
}
@Deprecated
public MatrixID(String mxId) {
this(parse(mxId));
}
@Deprecated
public MatrixID(String localpart, String domain) {
this(parse(buildRaw(localpart, domain)));
}
@Override
public String getId() {
return id;
}
@Override
public String getLocalPart() {
return localpart;
}
@Override
public String getDomain() {
return domain;
}
@Override
public MatrixID canonicalize() {
return parse(getId().toLowerCase());
}
@Override
public boolean isValid() {
return isAcceptable() && STRICT_PATTERN.matcher(id).matches();
}
@Override
public boolean isAcceptable() {
// TODO properly implement
return id.length() <= 255;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MatrixID)) return false;
MatrixID matrixID = (MatrixID) o;
return id.equals(matrixID.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public String toString() {
return getId();
}
}

View File

@@ -0,0 +1,93 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.kamax.matrix.MatrixID.ALLOWED_CHARS;
public class MatrixIdCodec {
public static final String DELIMITER = "=";
public static final String ENCODE_REGEX = "[^" + ALLOWED_CHARS + "]+";
public static final Pattern ENCODE_PATTERN = Pattern.compile(ENCODE_REGEX);
public static final Pattern DECODE_PATTERN = Pattern.compile("(=[0-9a-f]{2})+");
private MatrixIdCodec() {
// not for public consumption
}
public static String encode(String decoded) {
decoded = decoded.toLowerCase();
StringBuilder builder = new StringBuilder();
for (Character c : decoded.toCharArray()) {
String s = c.toString();
Matcher lp = ENCODE_PATTERN.matcher(s);
if (!lp.find()) {
builder.append(s);
} else {
for (byte b : c.toString().getBytes(StandardCharsets.UTF_8)) {
builder.append(DELIMITER);
builder.append(Hex.encodeHexString(new byte[] { b }));
}
}
}
return builder.toString();
}
public static String decode(String encoded) {
StringBuilder builder = new StringBuilder();
Matcher m = DECODE_PATTERN.matcher(encoded);
int prevEnd = 0;
while (m.find()) {
try {
int start = m.start();
int end = m.end();
String sub = encoded.substring(start, end).replaceAll(DELIMITER, "");
String decoded = new String(Hex.decodeHex(sub.toCharArray()), StandardCharsets.UTF_8);
builder.append(encoded, prevEnd, start);
builder.append(decoded);
prevEnd = end - 1;
} catch (DecoderException e) {
e.printStackTrace();
}
}
prevEnd++;
if (prevEnd < encoded.length()) {
builder.append(encoded, prevEnd, encoded.length());
}
if (builder.length() == 0) {
return encoded;
} else {
return builder.toString();
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class MatrixPath {
public static String encode(String element) {
try {
return URLEncoder.encode(element, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
// This would be madness if it happened, but we need to handle it still
throw new RuntimeException(e);
}
}
private static MatrixPath with(String base) {
return new MatrixPath().add(base);
}
public static MatrixPath root() {
return with("");
}
public static MatrixPath base() {
return root().add("_matrix");
}
public static MatrixPath client() {
return base().add("client");
}
public static MatrixPath clientR0() {
return client().add("r0");
}
private StringBuilder path = new StringBuilder();
/**
* Add the raw element to this path
*
* @param element
* The raw element to be added as is to the path, without encoding or path separator
* @return The MatrixPath
*/
public MatrixPath put(String element) {
path.append(element);
return this;
}
/**
* URL encode and add a new path element
*
* This method handle path separators
*
* @param element
* The element to be encoded and added.
* @return The MatrixPath
*/
public MatrixPath add(String element) {
// We add a path separator if this is the first character or if the last character is not a path separator
// already
if (path.length() == 0 || path.lastIndexOf("/", 0) < path.length() - 1) {
put("/");
}
put(encode(element));
return this;
}
public String get() {
return path.toString();
}
public String toString() {
return get();
}
public URI toURI() {
return URI.create(toString());
}
}

View File

@@ -0,0 +1,61 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class ThreePid implements _ThreePid {
private String medium;
private String address;
public ThreePid(String medium, String address) {
this.medium = medium;
this.address = address;
}
@Override
public String getMedium() {
return medium;
}
@Override
public String getAddress() {
return address;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreePid threePid = (ThreePid) o;
if (!medium.equals(threePid.medium)) return false;
return address.equals(threePid.address);
}
@Override
public int hashCode() {
int result = medium.hashCode();
result = 31 * result + address.hashCode();
return result;
}
}

View File

@@ -0,0 +1,61 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class ThreePidMapping implements _ThreePidMapping {
private _ThreePid threePid;
private _MatrixID mxId;
public ThreePidMapping(_ThreePid threePid, _MatrixID mxId) {
this.threePid = threePid;
this.mxId = mxId;
}
@Override
public _ThreePid getThreePid() {
return threePid;
}
@Override
public _MatrixID getMatrixId() {
return mxId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreePidMapping that = (ThreePidMapping) o;
if (!threePid.equals(that.threePid)) return false;
return mxId.equals(that.mxId);
}
@Override
public int hashCode() {
int result = threePid.hashCode();
result = 31 * result + mxId.hashCode();
return result;
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public enum ThreePidMedium {
Email("email"),
PhoneNumber("msisdn");
private String id;
ThreePidMedium(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String toString() {
return getId();
}
public boolean is(String s) {
return getId().contentEquals(s);
}
}

View File

@@ -0,0 +1,41 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.net.URI;
import java.net.URL;
import java.util.Optional;
public interface _MatrixContent {
URI getAddress();
URL getPermaLink();
boolean isValid();
Optional<String> getType();
byte[] getData();
Optional<String> getFilename();
}

View File

@@ -0,0 +1,55 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public interface _MatrixID {
String getId();
String getLocalPart();
String getDomain();
/**
* Render this Matrix ID strictly valid. In technical term, transform this ID so
* <code>isValid()</code> returns true.
*
* @return A canonical Matrix ID
*/
_MatrixID canonicalize();
/**
* If the Matrix ID is strictly valid in the protocol as per
* http://matrix.org/docs/spec/intro.html#user-identifiers
*
* @return true if strictly valid, false if not
*/
boolean isValid();
/**
* If the Matrix ID is acceptable in the protocol as per
* http://matrix.org/docs/spec/intro.html#historical-user-ids
*
* @return
*/
boolean isAcceptable();
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import io.kamax.matrix.client._Presence;
import java.util.Optional;
public interface _MatrixUser extends _MatrixUserProfile {
Optional<_Presence> getPresence();
}

View File

@@ -0,0 +1,42 @@
/*
* matrix-java-sdk - Matrix SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.net.URI;
import java.util.Optional;
public interface _MatrixUserProfile {
_MatrixID getId();
Optional<String> getName();
void setName(String name);
Optional<String> getAvatarUrl();
void setAvatar(String avatarRef);
void setAvatar(URI avatarUri);
Optional<_MatrixContent> getAvatar();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public interface _ThreePid {
String getMedium();
String getAddress();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public interface _ThreePidMapping {
_ThreePid getThreePid();
_MatrixID getMatrixId();
}

View File

@@ -0,0 +1,409 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import io.kamax.matrix.MatrixErrorInfo;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.hs._MatrixHomeserver;
import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.Objects;
import java.util.Optional;
import okhttp3.*;
public abstract class AMatrixHttpClient implements _MatrixClientRaw {
private Logger log = LoggerFactory.getLogger(AMatrixHttpClient.class);
protected MatrixClientContext context;
protected Gson gson = GsonUtil.get();
protected JsonParser jsonParser = new JsonParser();
private OkHttpClient client;
public AMatrixHttpClient(String domain) {
this(new MatrixClientContext().setDomain(domain));
}
public AMatrixHttpClient(URL hsBaseUrl) {
this(new MatrixClientContext().setHsBaseUrl(hsBaseUrl));
}
protected AMatrixHttpClient(MatrixClientContext context) {
this(context, new OkHttpClient.Builder(), new MatrixClientDefaults());
}
protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client) {
this(context, client, new MatrixClientDefaults());
}
protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client,
MatrixClientDefaults defaults) {
this(context, client.connectTimeout(defaults.getConnectTimeout(), TimeUnit.MILLISECONDS)
.readTimeout(5, TimeUnit.MINUTES).followRedirects(false).build());
}
protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient client) {
this.context = context;
this.client = client;
}
@Override
public Optional<_AutoDiscoverySettings> discoverSettings() {
if (StringUtils.isBlank(context.getDomain())) {
throw new IllegalStateException("A non-empty Matrix domain must be set to discover the client settings");
}
String hostname = context.getDomain().split(":")[0];
log.info("Performing .well-known auto-discovery for {}", hostname);
URL url = new HttpUrl.Builder().scheme("https").host(hostname).addPathSegments(".well-known/matrix/client")
.build().url();
String body = execute(new MatrixHttpRequest(new Request.Builder().get().url(url)).addIgnoredErrorCode(404));
if (StringUtils.isBlank(body)) {
if (Objects.isNull(context.getHsBaseUrl())) {
throw new IllegalStateException("No valid Homeserver base URL was found");
}
// No .well-known data found
// FIXME improve SDK so we can differentiate between not found and empty.
// not found = skip
// empty = failure
return Optional.empty();
}
log.info("Found body: {}", body);
WellKnownAutoDiscoverySettings settings = new WellKnownAutoDiscoverySettings(body);
log.info("Found .well-known data");
// TODO reconsider if and where we should check for an already present HS url in the context
if (settings.getHsBaseUrls().isEmpty()) {
throw new IllegalStateException("No valid Homeserver base URL was found");
}
for (URL baseUrlCandidate : settings.getHsBaseUrls()) {
context.setHsBaseUrl(baseUrlCandidate);
try {
if (!getHomeApiVersions().isEmpty()) {
log.info("Found a valid HS at {}", getContext().getHsBaseUrl().toString());
break;
}
} catch (MatrixClientRequestException e) {
log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage());
}
}
for (URL baseUrlCandidate : settings.getIsBaseUrls()) {
context.setIsBaseUrl(baseUrlCandidate);
try {
if (validateIsBaseUrl()) {
log.info("Found a valid IS at {}", getContext().getIsBaseUrl().toString());
break;
}
} catch (MatrixClientRequestException e) {
log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage());
}
}
return Optional.of(settings);
}
@Override
public MatrixClientContext getContext() {
return context;
}
@Override
public _MatrixHomeserver getHomeserver() {
return context.getHomeserver();
}
@Override
public Optional<String> getAccessToken() {
return Optional.ofNullable(context.getToken());
}
public String getAccessTokenOrThrow() {
return getAccessToken()
.orElseThrow(() -> new IllegalStateException("This method can only be used with a valid token."));
}
@Override
public List<String> getHomeApiVersions() {
String body = execute(new Request.Builder().get().url(getPath("client", "", "versions")));
return GsonUtil.asList(GsonUtil.parseObj(body), "versions", String.class);
}
@Override
public boolean validateIsBaseUrl() {
String body = execute(new Request.Builder().get().url(getIdentityPath("identity", "api", "v1")));
return "{}".equals(body);
}
protected String getUserId() {
return getUser().orElseThrow(IllegalStateException::new).getId();
}
@Override
public Optional<_MatrixID> getUser() {
return context.getUser();
}
protected Request.Builder addAuthHeader(Request.Builder builder, String token) {
builder.addHeader("Authorization", "Bearer " + token);
return builder;
}
protected Request.Builder addAuthHeader(Request.Builder builder) {
return addAuthHeader(builder, getAccessTokenOrThrow());
}
protected String executeAuthenticated(Request.Builder builder, String token) {
return execute(addAuthHeader(builder, token));
}
protected String executeAuthenticated(Request.Builder builder) {
return execute(addAuthHeader(builder));
}
protected String executeAuthenticated(MatrixHttpRequest matrixRequest) {
addAuthHeader(matrixRequest.getHttpRequest());
return execute(matrixRequest);
}
protected String execute(Request.Builder builder) {
return execute(new MatrixHttpRequest(builder));
}
protected String execute(MatrixHttpRequest matrixRequest) {
log(matrixRequest.getHttpRequest());
try (Response response = client.newCall(matrixRequest.getHttpRequest().build()).execute()) {
String body = response.body().string();
int responseStatus = response.code();
if (responseStatus == 200) {
log.debug("Request successfully executed.");
} else if (matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) {
log.debug("Error code ignored: " + responseStatus);
return "";
} else {
MatrixErrorInfo info = createErrorInfo(body, responseStatus);
body = handleError(matrixRequest, responseStatus, info);
}
return body;
} catch (IOException e) {
throw new MatrixClientRequestException(e);
}
}
protected MatrixHttpContentResult executeContentRequest(MatrixHttpRequest matrixRequest) {
log(matrixRequest.getHttpRequest());
try (Response response = client.newCall(matrixRequest.getHttpRequest().build()).execute()) {
int responseStatus = response.code();
MatrixHttpContentResult result;
if (responseStatus == 200 || matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) {
log.debug("Request successfully executed.");
result = new MatrixHttpContentResult(response);
} else {
String body = response.body().string();
MatrixErrorInfo info = createErrorInfo(body, responseStatus);
result = handleErrorContentRequest(matrixRequest, responseStatus, info);
}
return result;
} catch (IOException e) {
throw new MatrixClientRequestException(e);
}
}
/**
* Default handling of errors. Can be overwritten by a custom implementation in inherited classes.
*
* @param matrixRequest
* @param responseStatus
* @param info
* @return body of the response of a repeated call of the request, else this methods throws a
* MatrixClientRequestException
*/
protected String handleError(MatrixHttpRequest matrixRequest, int responseStatus, MatrixErrorInfo info) {
String message = String.format("Request failed: %s", responseStatus);
if (Objects.nonNull(info)) {
message = String.format("%s - %s - %s", message, info.getErrcode(), info.getError());
}
if (responseStatus == 429) {
return handleRateLimited(matrixRequest, info);
}
throw new MatrixClientRequestException(info, message);
}
/**
* Default handling of rate limited calls. Can be overwritten by a custom implementation in inherited classes.
*
* @param matrixRequest
* @param info
* @return body of the response of a repeated call of the request, else this methods throws a
* MatrixClientRequestException
*/
protected String handleRateLimited(MatrixHttpRequest matrixRequest, MatrixErrorInfo info) {
throw new MatrixClientRequestException(info, "Request was rate limited.");
// TODO Add default handling of rate limited call, i.e. repeated call after given time interval.
// 1. Wait for timeout
// 2. return execute(request)
}
protected MatrixHttpContentResult handleErrorContentRequest(MatrixHttpRequest matrixRequest, int responseStatus,
MatrixErrorInfo info) {
String message = String.format("Request failed with status code: %s", responseStatus);
if (responseStatus == 429) {
return handleRateLimitedContentRequest(matrixRequest, info);
}
throw new MatrixClientRequestException(info, message);
}
protected MatrixHttpContentResult handleRateLimitedContentRequest(MatrixHttpRequest matrixRequest,
MatrixErrorInfo info) {
throw new MatrixClientRequestRateLimitedException(info, "Request was rate limited.");
// TODO Add default handling of rate limited call, i.e. repeated call after given time interval.
// 1. Wait for timeout
// 2. return execute(request)
}
protected Optional<String> extractAsStringFromBody(String body, String jsonObjectName) {
if (StringUtils.isEmpty(body)) {
return Optional.empty();
}
return GsonUtil.findString(jsonParser.parse(body).getAsJsonObject(), jsonObjectName);
}
private MatrixErrorInfo createErrorInfo(String body, int responseStatus) {
MatrixErrorInfo info = null;
try {
info = gson.fromJson(body, MatrixErrorInfo.class);
if (Objects.nonNull(info)) {
log.debug("Request returned with an error. Status code: {}, errcode: {}, error: {}", responseStatus,
info.getErrcode(), info.getError());
}
} catch (JsonSyntaxException e) {
log.debug("Unable to parse Matrix error info. Content was:\n{}", body);
}
return info;
}
private void log(Request.Builder req) {
log.debug("Doing {} {}", req, req.toString());
}
protected HttpUrl.Builder getHsBaseUrl() {
return HttpUrl.get(context.getHsBaseUrl()).newBuilder();
}
protected HttpUrl.Builder getIsBaseUrl() {
return HttpUrl.get(context.getIsBaseUrl()).newBuilder();
}
protected HttpUrl.Builder getPathBuilder(HttpUrl.Builder base, String... segments) {
base.addPathSegment("_matrix");
for (String segment : segments) {
base.addPathSegment(segment);
}
if (context.isVirtual()) {
context.getUser().ifPresent(user -> base.addQueryParameter("user_id", user.getId()));
}
return base;
}
protected HttpUrl.Builder getPathBuilder(String... segments) {
return getPathBuilder(getHsBaseUrl(), segments);
}
protected HttpUrl.Builder getIdentityPathBuilder(String... segments) {
return getPathBuilder(getIsBaseUrl(), segments);
}
protected URL getPath(String... segments) {
return getPathBuilder(segments).build().url();
}
protected URL getIdentityPath(String... segments) {
return getIdentityPathBuilder(segments).build().url();
}
protected HttpUrl.Builder getClientPathBuilder(String... segments) {
String[] base = { "client", "r0" };
segments = ArrayUtils.addAll(base, segments);
return getPathBuilder(segments);
}
protected HttpUrl.Builder getMediaPathBuilder(String... segments) {
String[] base = { "media", "r0" };
segments = ArrayUtils.addAll(base, segments);
return getPathBuilder(segments);
}
protected URL getClientPath(String... segments) {
return getClientPathBuilder(segments).build().url();
}
protected URL getMediaPath(String... segments) {
return getMediaPathBuilder(segments).build().url();
}
protected RequestBody getJsonBody(Object o) {
return RequestBody.create(MediaType.parse("application/json"), GsonUtil.get().toJson(o));
}
protected Request.Builder request(URL url) {
return new Request.Builder().url(url);
}
protected Request.Builder getRequest(URL url) {
return request(url).get();
}
}

View File

@@ -0,0 +1,154 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.hs.MatrixHomeserver;
import io.kamax.matrix.hs._MatrixHomeserver;
import java.net.URL;
import java.util.Objects;
import java.util.Optional;
public class MatrixClientContext {
private String domain;
private URL hsBaseUrl;
private URL isBaseUrl;
private _MatrixID user;
private String token;
private boolean isVirtual;
private String deviceId;
private String initialDeviceName;
public MatrixClientContext() {
// stub
}
public MatrixClientContext(MatrixClientContext other) {
this.domain = other.domain;
this.hsBaseUrl = other.hsBaseUrl;
this.isBaseUrl = other.isBaseUrl;
this.user = other.user;
this.token = other.token;
this.isVirtual = other.isVirtual;
this.deviceId = other.deviceId;
this.initialDeviceName = other.initialDeviceName;
}
public MatrixClientContext(_MatrixHomeserver hs) {
setDomain(hs.getDomain());
setHsBaseUrl(hs.getBaseEndpoint());
}
public MatrixClientContext(_MatrixHomeserver hs, _MatrixID user, String token) {
this(hs);
setUser(user);
setToken(token);
}
public _MatrixHomeserver getHomeserver() {
if (Objects.isNull(hsBaseUrl)) {
throw new IllegalStateException("Homeserver Base URL is not set");
}
return new MatrixHomeserver(domain, hsBaseUrl.toString());
}
public String getDomain() {
return domain;
}
public MatrixClientContext setDomain(String domain) {
this.domain = domain;
return this;
}
public URL getHsBaseUrl() {
return hsBaseUrl;
}
public MatrixClientContext setHsBaseUrl(URL hsBaseUrl) {
this.hsBaseUrl = hsBaseUrl;
return this;
}
public URL getIsBaseUrl() {
return isBaseUrl;
}
public MatrixClientContext setIsBaseUrl(URL isBaseUrl) {
this.isBaseUrl = isBaseUrl;
return this;
}
public Optional<_MatrixID> getUser() {
return Optional.ofNullable(user);
}
public MatrixClientContext setUser(_MatrixID user) {
this.user = user;
return this;
}
public MatrixClientContext setUserWithLocalpart(String localpart) {
setUser(MatrixID.asAcceptable(localpart, getDomain()));
return this;
}
public String getToken() {
return token;
}
public MatrixClientContext setToken(String token) {
this.token = token;
return this;
}
public boolean isVirtual() {
return isVirtual;
}
public MatrixClientContext setVirtual(boolean virtual) {
isVirtual = virtual;
return this;
}
public String getDeviceId() {
return deviceId;
}
public MatrixClientContext setDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
public String getInitialDeviceName() {
return initialDeviceName;
}
public MatrixClientContext setInitialDeviceName(String initialDeviceName) {
this.initialDeviceName = initialDeviceName;
return this;
}
}

View File

@@ -0,0 +1,59 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
public class MatrixClientDefaults {
private int connectTimeout = 30 * 1000; // 30 sec
private int requestTimeout = 5 * 60 * 1000; // 5 min
private int socketTimeout = requestTimeout;
public int getConnectTimeout() {
return connectTimeout;
}
public MatrixClientDefaults setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}
public int getRequestTimeout() {
return requestTimeout;
}
public MatrixClientDefaults setRequestTimeout(int requestTimeout) {
this.requestTimeout = requestTimeout;
return this;
}
public int getSocketTimeout() {
return socketTimeout;
}
public MatrixClientDefaults setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
return this;
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix.MatrixErrorInfo;
import java.io.IOException;
import java.util.Optional;
public class MatrixClientRequestException extends RuntimeException {
private MatrixErrorInfo errorInfo;
public MatrixClientRequestException(IOException e) {
super(e);
}
public MatrixClientRequestException(MatrixErrorInfo errorInfo, String message) {
super(message);
this.errorInfo = errorInfo;
}
public Optional<MatrixErrorInfo> getError() {
return Optional.ofNullable(errorInfo);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix.MatrixErrorInfo;
public class MatrixClientRequestRateLimitedException extends MatrixClientRequestException {
public MatrixClientRequestRateLimitedException(MatrixErrorInfo errorInfo, String message) {
super(errorInfo, message);
}
}

View File

@@ -0,0 +1,133 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix._MatrixContent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Optional;
import okhttp3.Request;
public class MatrixHttpContent extends AMatrixHttpClient implements _MatrixContent {
private Logger log = LoggerFactory.getLogger(MatrixHttpContent.class);
private final Pattern filenamePattern = Pattern.compile("filename=\"?([^\";]+)");
private URI address;
private MatrixHttpContentResult result;
private boolean loaded = false;
private boolean valid = false;
public MatrixHttpContent(MatrixClientContext context, URI address) {
super(context);
this.address = address;
}
// TODO switch a HTTP HEAD to fetch initial data, instead of loading in memory directly
private synchronized void load() {
if (loaded) {
return;
}
try {
if (!StringUtils.equalsIgnoreCase("mxc", address.getScheme())) {
log.debug("{} is not a supported protocol for avatars, ignoring", address.getScheme());
} else {
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().url(getPermaLink()));
result = executeContentRequest(request);
valid = result.isValid();
}
} catch (MatrixClientRequestException e) {
valid = false;
}
loaded = true;
}
@Override
public URI getAddress() {
return address;
}
@Override
public URL getPermaLink() {
return getMediaPathBuilder("download", address.getHost()).addEncodedPathSegments(address.getPath().substring(1))
.build().url();
}
@Override
public boolean isValid() {
load();
return valid;
}
@Override
public Optional<String> getType() {
load();
if (!isValid()) {
throw new IllegalStateException("This method should only be called, if valid is true.");
}
return result.getContentType();
}
@Override
public byte[] getData() {
load();
if (!isValid()) {
throw new IllegalStateException("This method should only be called, if valid is true.");
}
return result.getData();
}
@Override
public Optional<String> getFilename() {
load();
if (!isValid()) {
throw new IllegalStateException("This method should only be called, if valid is true.");
}
return result.getHeader("Content-Disposition").filter(l -> !l.isEmpty()).flatMap(l -> {
for (String v : l) {
Matcher m = filenamePattern.matcher(v);
if (m.find()) {
return Optional.of(m.group(1));
}
}
return Optional.empty();
});
}
}

View File

@@ -0,0 +1,71 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import java.io.IOException;
import java.util.*;
import java.util.Optional;
import okhttp3.MediaType;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class MatrixHttpContentResult {
private final boolean valid;
private final Map<String, List<String>> headers;
private final Optional<String> contentType;
private final byte[] data;
public MatrixHttpContentResult(Response response) throws IOException {
try (ResponseBody body = response.body()) {
boolean hasBody = Objects.nonNull(body);
valid = hasBody && response.code() == 200;
headers = response.headers().toMultimap();
if (hasBody) {
contentType = Optional.ofNullable(body.contentType()).map(MediaType::toString);
data = body.bytes();
} else {
contentType = Optional.empty();
data = new byte[0];
}
}
}
public boolean isValid() {
return valid;
}
public Optional<List<String>> getHeader(String name) {
return Optional.ofNullable(headers.get(name));
}
public Optional<String> getContentType() {
return contentType;
}
public byte[] getData() {
return data;
}
}

View File

@@ -0,0 +1,93 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang3.ArrayUtils;
import java.net.URL;
import java.util.List;
import javax.swing.*;
public class MatrixHttpPushRule extends AMatrixHttpClient implements _PushRule {
private static final String ActionKey = "actions";
private static final String EnabledKey = "enabled";
private final String[] baseSegments;
public MatrixHttpPushRule(MatrixClientContext context, String scope, String kind, String id) {
super(context);
baseSegments = new String[] { "pushrules", scope, kind, id };
}
private URL makeUrl() {
return getClientPath(baseSegments);
}
private URL makeUrl(String... segments) {
return getClientPath(ArrayUtils.addAll(baseSegments, segments));
}
@Override
public JsonObject getJson() {
return GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl())));
}
@Override
public void set(JsonObject data) {
executeAuthenticated(request(makeUrl()).put(getJsonBody(data)));
}
@Override
public void delete() {
executeAuthenticated(request(makeUrl()).delete());
}
@Override
public boolean isEnabled() {
JsonObject response = GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl(EnabledKey))));
return GsonUtil.getPrimitive(response, EnabledKey).getAsBoolean();
}
@Override
public void setEnabled(boolean enabled) {
executeAuthenticated(request(makeUrl(EnabledKey)).put(getJsonBody(GsonUtil.makeObj(EnabledKey, enabled))));
}
@Override
public List<String> getActions() {
JsonObject response = GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl(ActionKey))));
return GsonUtil.asList(GsonUtil.findArray(response, ActionKey).orElseGet(JsonArray::new), String.class);
}
@Override
public void setActions(List<String> data) {
executeAuthenticated(
request(makeUrl(ActionKey)).put(getJsonBody(GsonUtil.makeObj(ActionKey, GsonUtil.asArray(data)))));
}
}

View File

@@ -0,0 +1,50 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Request;
public class MatrixHttpRequest {
private final Request.Builder httpRequest;
private List<Integer> ignoredErrorCodes = new ArrayList<>();
public MatrixHttpRequest(Request.Builder request) {
this.httpRequest = request;
}
public MatrixHttpRequest addIgnoredErrorCode(int errcode) {
ignoredErrorCodes.add(errcode);
return this;
}
public Request.Builder getHttpRequest() {
return httpRequest;
}
public List<Integer> getIgnoredErrorCodes() {
return ignoredErrorCodes;
}
}

View File

@@ -0,0 +1,440 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixErrorInfo;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUserProfile;
import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.RoomMessageChunkResponseJson;
import io.kamax.matrix.json.RoomMessageFormattedTextPutBody;
import io.kamax.matrix.json.RoomMessageTextPutBody;
import io.kamax.matrix.json.RoomTagSetBody;
import io.kamax.matrix.json.event.MatrixJsonPersistentEvent;
import io.kamax.matrix.room.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import okhttp3.HttpUrl;
import okhttp3.Request;
public class MatrixHttpRoom extends AMatrixHttpClient implements _MatrixRoom {
private Logger log = LoggerFactory.getLogger(MatrixHttpRoom.class);
private String roomId;
public MatrixHttpRoom(MatrixClientContext context, String roomId) {
super(context);
this.roomId = roomId;
}
@Override
public String getAddress() {
return roomId;
}
@Override
public Optional<String> getName() {
return getState("m.room.name").flatMap(obj -> GsonUtil.findString(obj, "name"));
}
@Override
public Optional<String> getTopic() {
return getState("m.room.topic").flatMap(obj -> GsonUtil.findString(obj, "topic"));
}
@Override
public Optional<String> getAvatarUrl() {
return getState("m.room.avatar").flatMap(obj -> GsonUtil.findString(obj, "url"));
}
@Override
public Optional<_MatrixContent> getAvatar() {
return getAvatarUrl().flatMap(url -> {
try {
return Optional.of(new MatrixHttpContent(context, new URI(url)));
} catch (URISyntaxException e) {
log.debug("{} is not a valid URI for avatar, returning empty", url);
return Optional.empty();
}
});
}
@Override
public String getId() {
return roomId;
}
@Override
public Optional<JsonObject> getState(String type) {
URL path = getClientPath("rooms", getAddress(), "state", type);
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
if (StringUtils.isBlank(body)) {
return Optional.empty();
}
return Optional.of(GsonUtil.parseObj(body));
}
@Override
public Optional<JsonObject> getState(String type, String key) {
URL path = getClientPath("rooms", roomId, "state", type, key);
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
if (StringUtils.isBlank(body)) {
return Optional.empty();
}
return Optional.of(GsonUtil.parseObj(body));
}
@Override
public void join() {
join(Collections.emptyList());
}
@Override
public void join(List<String> servers) {
HttpUrl.Builder b = getClientPathBuilder("rooms", roomId, "join");
servers.forEach(server -> b.addQueryParameter("server_name", server));
executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(b.build()));
}
@Override
public Optional<MatrixErrorInfo> tryJoin() {
return tryJoin(Collections.emptyList());
}
@Override
public Optional<MatrixErrorInfo> tryJoin(List<String> servers) {
try {
join(servers);
return Optional.empty();
} catch (MatrixClientRequestException e) {
return e.getError();
}
}
@Override
public void leave() {
URL path = getClientPath("rooms", roomId, "leave");
MatrixHttpRequest request = new MatrixHttpRequest(
new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
// TODO Find a better way to handle room objects for unknown rooms
// Maybe throw exception?
// TODO implement method to check room existence - isValid() ?
// if (res.getStatusLine().getStatusCode() == 404) {
// log.warn("Room {} is not joined, ignoring call", roomId);
// return;
// }
request.addIgnoredErrorCode(404);
executeAuthenticated(request);
}
@Override
public Optional<MatrixErrorInfo> tryLeave() {
try {
leave();
return Optional.empty();
} catch (MatrixClientRequestException e) {
return e.getError();
}
}
@Override
public void kick(_MatrixID user) {
kick(user, null);
}
@Override
public void kick(_MatrixID user, String reason) {
JsonObject body = new JsonObject();
body.addProperty("user_id", user.getId());
body.addProperty("reason", reason);
URL path = getClientPath("rooms", roomId, "kick");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().post(getJsonBody(body)).url(path));
executeAuthenticated(request);
}
@Override
public Optional<MatrixErrorInfo> tryKick(_MatrixID user) {
return tryKick(user, null);
}
@Override
public Optional<MatrixErrorInfo> tryKick(_MatrixID user, String reason) {
try {
kick(user, reason);
return Optional.empty();
} catch (MatrixClientRequestException e) {
return e.getError();
}
}
@Override
public String sendEvent(String type, JsonObject content) {
// FIXME URL encoding
URL path = getClientPath("rooms", roomId, "send", type, Long.toString(System.currentTimeMillis()));
String body = executeAuthenticated(new Request.Builder().put(getJsonBody(content)).url(path));
return GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "event_id");
}
private String sendMessage(RoomMessageTextPutBody content) {
return sendEvent("m.room.message", GsonUtil.makeObj(content));
}
@Override
public String sendText(String message) {
return sendMessage(new RoomMessageTextPutBody(message));
}
@Override
public String sendFormattedText(String formatted, String rawFallback) {
// TODO sanitize input
return sendMessage(new RoomMessageFormattedTextPutBody(rawFallback, formatted));
}
@Override
public String sendNotice(String message) {
return sendMessage(new RoomMessageTextPutBody("m.notice", message));
}
@Override
public String sendNotice(String formatted, String plain) {
// TODO sanitize input
return sendMessage(new RoomMessageFormattedTextPutBody("m.notice", plain, formatted));
}
@Override
public void sendReceipt(String type, String eventId) {
URL path = getClientPath("rooms", roomId, "receipt", type, eventId);
executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
}
@Override
public void sendReceipt(ReceiptType type, String eventId) {
sendReceipt(type.getId(), eventId);
}
@Override
public void sendReadReceipt(String eventId) {
sendReceipt(ReceiptType.Read, eventId);
}
@Override
public void invite(_MatrixID mxId) {
URL path = getClientPath("rooms", roomId, "invite");
executeAuthenticated(
new Request.Builder().post(getJsonBody(GsonUtil.makeObj("user_id", mxId.getId()))).url(path));
}
@Override
public List<_MatrixUserProfile> getJoinedUsers() {
URL path = getClientPath("rooms", roomId, "joined_members");
String body = executeAuthenticated(new Request.Builder().get().url(path));
List<_MatrixUserProfile> ids = new ArrayList<>();
if (StringUtils.isNotEmpty(body)) {
JsonObject joinedUsers = jsonParser.parse(body).getAsJsonObject().get("joined").getAsJsonObject();
ids = joinedUsers.entrySet().stream().filter(e -> e.getValue().isJsonObject()).map(entry -> {
JsonObject obj = entry.getValue().getAsJsonObject();
return new MatrixHttpUser(getContext(), MatrixID.asAcceptable(entry.getKey())) {
@Override
public Optional<String> getName() {
return GsonUtil.findString(obj, "display_name");
}
@Override
public Optional<_MatrixContent> getAvatar() {
return GsonUtil.findString(obj, "avatar_url").flatMap(s -> {
try {
return Optional.of(new URI(s));
} catch (URISyntaxException e) {
return Optional.empty();
}
}).map(uri -> new MatrixHttpContent(getContext(), uri));
}
};
}).collect(Collectors.toList());
}
return ids;
}
@Override
public _MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options) {
HttpUrl.Builder builder = getClientPathBuilder("rooms", roomId, "messages");
builder.addQueryParameter("from", options.getFromToken());
builder.addQueryParameter("dir", options.getDirection());
options.getToToken().ifPresent(token -> builder.addQueryParameter("to", token));
options.getLimit().ifPresent(limit -> builder.addQueryParameter("limit", limit.toString()));
String bodyRaw = executeAuthenticated(new Request.Builder().get().url(builder.build().url()));
RoomMessageChunkResponseJson body = GsonUtil.get().fromJson(bodyRaw, RoomMessageChunkResponseJson.class);
return new MatrixRoomMessageChunk(body.getStart(), body.getEnd(),
body.getChunk().stream().map(MatrixJsonPersistentEvent::new).collect(Collectors.toList()));
}
@Override
public List<Tag> getUserTags() {
return getAllTags().stream().filter(tag -> "u".equals(tag.getNamespace()))
.collect(Collectors.toList());
}
@Override
public List<Tag> getAllTags() {
URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags");
String body = executeAuthenticated(new Request.Builder().get().url(path));
JsonObject jsonTags = GsonUtil.parseObj(body).getAsJsonObject("tags").getAsJsonObject();
List<Tag> tags = jsonTags.entrySet().stream().map(entry -> {
String completeName = entry.getKey();
String name = "";
String namespace = "";
if (completeName.startsWith("m.")) {
name = completeName.substring(2);
namespace = "m";
} else if (completeName.startsWith("u.")) {
name = completeName.substring(2);
namespace = "u";
} else {
name = completeName;
}
JsonElement jsonOrder = entry.getValue().getAsJsonObject().get("order");
Double order = null;
if (jsonOrder != null) {
order = jsonOrder.getAsDouble();
}
return new Tag(namespace, name, order);
}).collect(Collectors.toList());
return tags;
}
@Override
public void addUserTag(String tag) {
addTag("u." + tag, null);
}
@Override
public void addUserTag(String tag, double order) {
addTag("u." + tag, order);
}
@Override
public void deleteUserTag(String tag) {
deleteTag("u." + tag);
}
@Override
public void addFavouriteTag() {
addTag("m.favourite", null);
}
@Override
public void addFavouriteTag(double order) {
addTag("m.favourite", order);
}
@Override
public Optional<Tag> getFavouriteTag() {
return getAllTags().stream()
.filter(tag -> "m".equals(tag.getNamespace()) && "favourite".equals(tag.getName())).findFirst();
}
@Override
public void deleteFavouriteTag() {
deleteTag("m.favourite");
}
@Override
public void addLowpriorityTag() {
addTag("m.lowpriority", null);
}
@Override
public void addLowpriorityTag(double order) {
addTag("m.lowpriority", order);
}
@Override
public Optional<Tag> getLowpriorityTag() {
return getAllTags().stream()
.filter(tag -> "m".equals(tag.getNamespace()) && "lowpriority".equals(tag.getName())).findFirst();
}
@Override
public void deleteLowpriorityTag() {
deleteTag("m.lowpriority");
}
private void addTag(String tag, Double order) {
// TODO check name size
if (order != null && (order < 0 || order > 1)) {
throw new IllegalArgumentException("Order out of range!");
}
URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags", tag);
Request.Builder request = new Request.Builder().url(path);
if (order != null) {
request.put(getJsonBody(new RoomTagSetBody(order)));
} else {
request.put(getJsonBody(new JsonObject()));
}
executeAuthenticated(request);
}
private void deleteTag(String tag) {
URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags", tag);
executeAuthenticated(new Request.Builder().url(path).delete());
}
}

View File

@@ -0,0 +1,125 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUser;
import io.kamax.matrix.client.regular.Presence;
import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Optional;
import okhttp3.Request;
public class MatrixHttpUser extends AMatrixHttpClient implements _MatrixUser {
private Logger log = LoggerFactory.getLogger(MatrixHttpUser.class);
private _MatrixID mxId;
public MatrixHttpUser(MatrixClientContext context, _MatrixID mxId) {
super(context);
this.mxId = mxId;
}
@Override
public _MatrixID getId() {
return mxId;
}
@Override
public Optional<String> getName() {
URL path = getClientPath("profile", mxId.getId(), "displayname");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
return extractAsStringFromBody(body, "displayname");
}
@Override
public void setName(String name) {
URL path = getClientPath("profile", mxId.getId(), "displayname");
JsonObject body = GsonUtil.makeObj("displayname", name);
executeAuthenticated(new Request.Builder().put(getJsonBody(body)).url(path));
}
@Override
public Optional<String> getAvatarUrl() {
URL path = getClientPath("profile", mxId.getId(), "avatar_url");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
return extractAsStringFromBody(body, "avatar_url");
}
@Override
public void setAvatar(String avatarRef) {
URL path = getClientPath("profile", mxId.getId(), "avatar_url");
JsonObject body = GsonUtil.makeObj("avatar_url", avatarRef);
executeAuthenticated(new Request.Builder().put(getJsonBody(body)).url(path));
}
@Override
public void setAvatar(URI avatarUri) {
setAvatar(avatarUri.toString());
}
@Override
public Optional<_MatrixContent> getAvatar() {
return getAvatarUrl().flatMap(uri -> {
try {
return Optional.of(new MatrixHttpContent(getContext(), new URI(uri)));
} catch (URISyntaxException e) {
log.debug("{} is not a valid URI for avatar, returning empty", uri);
return Optional.empty();
}
});
}
@Override
public Optional<_Presence> getPresence() {
URL path = getClientPath("presence", mxId.getId(), "status");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = execute(request);
if (StringUtils.isBlank(body)) {
return Optional.empty();
}
return Optional.of(new Presence(GsonUtil.parseObj(body)));
}
}

View File

@@ -0,0 +1,39 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
public class MatrixPasswordCredentials {
private final String localPart;
private final String password;
public MatrixPasswordCredentials(String localPart, String password) {
this.localPart = localPart;
this.password = password;
}
public String getLocalPart() {
return localPart;
}
public String getPassword() {
return password;
}
}

View File

@@ -0,0 +1,45 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import org.apache.commons.lang3.StringUtils;
public enum PresenceStatus {
Online("online"),
Offline("offline"),
Unavailable("unavailable");
private String id;
PresenceStatus(String id) {
this.id = id;
}
public String getId() {
return id;
}
public boolean is(String status) {
return StringUtils.equals(id, status);
}
}

View File

@@ -0,0 +1,138 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.InvalidJsonException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class WellKnownAutoDiscoverySettings implements _AutoDiscoverySettings {
private final Logger log = LoggerFactory.getLogger(WellKnownAutoDiscoverySettings.class);
private JsonObject raw;
private List<URL> hsBaseUrls = new ArrayList<>();
private List<URL> isBaseUrls = new ArrayList<>();
/**
* Build .well-known auto-discovery settings from a .well-known source.
*
* @param raw
* The raw JSON data
* @throws IllegalArgumentException
* if the data is invalid and couldn't be parsed.
*/
public WellKnownAutoDiscoverySettings(String raw) {
try {
setRaw(GsonUtil.parseObj(raw));
} catch (JsonParseException | InvalidJsonException e) {
throw new IllegalArgumentException("Invalid JSON data for .well-known string");
}
}
private void setRaw(JsonObject raw) {
this.raw = raw;
process();
}
private Optional<URL> getUrl(String url) {
try {
return Optional.of(new URL(url));
} catch (MalformedURLException e) {
log.warn("Ignoring invalid Base URL entry in well-known: {} - {}", url, e.getMessage());
return Optional.empty();
}
}
private List<URL> getUrls(JsonArray array) {
List<URL> urls = new ArrayList<>();
array.forEach(el -> {
if (!el.isJsonPrimitive()) {
log.warn("Ignoring invalid Base URL entry in well-known: {} - Not a string", GsonUtil.get().toJson(el));
return;
}
getUrl(el.getAsString()).ifPresent(urls::add);
});
return urls;
}
private List<URL> processUrls(JsonObject base, String key) {
List<URL> urls = new ArrayList<>();
GsonUtil.findObj(base, key).ifPresent(cfg -> {
log.info("Found data");
GsonUtil.findArray(cfg, "base_urls").ifPresent(arr -> {
log.info("Found base URL(s)");
urls.addAll(getUrls(arr));
});
if (urls.isEmpty()) {
GsonUtil.findString(cfg, "base_url").flatMap(this::getUrl).ifPresent(urls::add);
}
});
return urls;
}
private void process() {
log.info("Processing Homeserver Base URLs");
hsBaseUrls = processUrls(raw, "m.homeserver");
log.info("Found {} valid URL(s)", hsBaseUrls.size());
log.info("Processing Identity server Base URLs");
isBaseUrls = processUrls(raw, "m.identity_server");
log.info("Found {} valid URL(s)", isBaseUrls.size());
}
@Override
public JsonObject getRaw() {
return raw;
}
@Override
public List<URL> getHsBaseUrls() {
return Collections.unmodifiableList(hsBaseUrls);
}
@Override
public List<URL> getIsBaseUrls() {
return Collections.unmodifiableList(isBaseUrls);
}
}

View File

@@ -0,0 +1,36 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import java.net.URL;
import java.util.List;
public interface _AutoDiscoverySettings {
JsonObject getRaw();
List<URL> getHsBaseUrls();
List<URL> getIsBaseUrls();
}

View File

@@ -0,0 +1,39 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import java.util.List;
public interface _GlobalPushRulesSet {
List<JsonObject> getContent();
List<JsonObject> getOverride();
List<JsonObject> getRoom();
List<JsonObject> getSender();
List<JsonObject> getUnderride();
}

View File

@@ -0,0 +1,158 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUser;
import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.matrix.room.RoomAlias;
import io.kamax.matrix.room._RoomAliasLookup;
import io.kamax.matrix.room._RoomCreationOptions;
import java.io.File;
import java.net.URI;
import java.util.List;
import java.util.Optional;
public interface _MatrixClient extends _MatrixClientRaw {
_MatrixID getWhoAmI();
void setDisplayName(String name);
_RoomAliasLookup lookup(RoomAlias alias);
_MatrixRoom createRoom(_RoomCreationOptions options);
_MatrixRoom getRoom(String roomId);
List<_MatrixRoom> getJoinedRooms();
_MatrixRoom joinRoom(String roomIdOrAlias);
_MatrixUser getUser(_MatrixID mxId);
Optional<String> getDeviceId();
/* Custom endpoint! */
// TODO refactor into custom synapse class?
void register(MatrixPasswordCredentials credentials, String sharedSecret, boolean admin);
/***
* Set the access token to use for any authenticated API calls.
*
* @param accessToken
* The access token provided by the server which must be valid
* @throws MatrixClientRequestException
* If an error occurred while checking for the identity behind the access token
*/
void setAccessToken(String accessToken) throws MatrixClientRequestException;
void login(MatrixPasswordCredentials credentials);
void logout();
_SyncData sync(_SyncOptions options);
/**
* Download content from the media repository
*
* @param mxUri
* The MXC URI for the content to download
* @return The content
* @throws IllegalArgumentException
* if the parameter is not a valid MXC URI
*/
_MatrixContent getMedia(String mxUri) throws IllegalArgumentException;
/**
* Download content from the media repository
*
* @param mxUri
* The MXC URI for the content to download
* @return The content
* @throws IllegalArgumentException
* if the parameter is not a valid MXC URI
*/
_MatrixContent getMedia(URI mxUri) throws IllegalArgumentException;
/**
* Upload content to the media repository
*
* @param data
* The data to send
* @param type
* The mime-type of the content upload
* @return The MXC URI for the uploaded content
*/
String putMedia(byte[] data, String type);
/**
* Upload content to the media repository
*
* @param data
* The data to send
* @param type
* The mime-type of the content upload
* @param filename
* A suggested filename for the content
* @return The MXC URI for the uploaded content
*/
String putMedia(byte[] data, String type, String filename);
/**
* Upload content to the media repository
*
* @param data
* The file to read the data from
* @param type
* The mime-type of the content upload
* @return The MXC URI for the uploaded content
*/
String putMedia(File data, String type);
/**
* Upload content to the media repository
*
* @param data
* The data to send
* @param type
* The mime-type of the content upload
* @param filename
* A suggested filename for the content
* @return The MXC URI for the uploaded content
*/
String putMedia(File data, String type, String filename);
List<JsonObject> getPushers();
void setPusher(JsonObject pusher);
void deletePusher(String pushKey);
_GlobalPushRulesSet getPushRules();
_PushRule getPushRule(String scope, String kind, String id);
}

View File

@@ -0,0 +1,51 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.hs._MatrixHomeserver;
import java.util.List;
import java.util.Optional;
public interface _MatrixClientRaw {
MatrixClientContext getContext();
_MatrixHomeserver getHomeserver();
Optional<String> getAccessToken();
Optional<_MatrixID> getUser();
Optional<_AutoDiscoverySettings> discoverSettings();
// FIXME
// we should maybe have a dedicated object for HS related items and be merged into getHomeserver() which is only
// holding state at this point and is not functional
List<String> getHomeApiVersions();
// FIXME
// we should maybe have a dedicated object for IS related items. Will reconsider when implementing
// other part of the IS API
boolean validateIsBaseUrl();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
public interface _Presence {
String getStatus();
Long getLastActive();
}

View File

@@ -0,0 +1,43 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import java.util.List;
public interface _PushRule {
JsonObject getJson();
void set(JsonObject data);
void delete();
boolean isEnabled();
void setEnabled(boolean enabled);
List<String> getActions();
void setActions(List<String> data);
}

View File

@@ -0,0 +1,253 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import io.kamax.matrix.event._MatrixAccountDataEvent;
import io.kamax.matrix.event._MatrixEphemeralEvent;
import io.kamax.matrix.event._MatrixPersistentEvent;
import io.kamax.matrix.event._MatrixStateEvent;
import java.util.List;
import java.util.Set;
/**
* Representation of the data when performing a sync call on the Matrix Client API.
*/
public interface _SyncData {
interface State {
/**
* The state of the room.
*
* @return a list of state events.
*/
List<_MatrixStateEvent> getEvents();
}
interface Timeline {
/**
* Events that happened in the sync window.
*
* @return List of events.
*/
List<_MatrixPersistentEvent> getEvents();
/**
* If the number of events returned was limited by the sync filter.
*
* @return true if the number of events was limited, false if not.
*/
boolean isLimited();
/**
* Token that can be supplied to fetch previous events for the associated room.
*
* @return the token.
*/
String getPreviousBatchToken();
}
interface Ephemeral {
/**
* Events that happened in the sync window.
*
* @return List of events.
*/
List<_MatrixEphemeralEvent> getEvents();
}
interface AccountData {
/**
* Events that happened in the sync window.
*
* @return List of events.
*/
List<_MatrixAccountDataEvent> getEvents();
}
interface InvitedRoom {
/**
* The ID of the room the user was invited to.
*
* @return the room ID.
*/
String getId();
/**
* The state of the room at the invite event.
*
* @return a list of state events.
*/
State getState();
}
interface UnreadNotifications {
/**
* The number of unread notifications with the highlight flag set.
*
* @return the count.
*/
long getHighlightCount();
/**
* The total number of unread notifications.
*
* @return the count.
*/
long getNotificationCount();
}
interface JoinedRoom {
/**
* The ID of the room the user is joined to.
*
* @return the room id.
*/
String getId();
/**
* State changes prior the start of the timeline.
*
* @return a list of state events.
*/
State getState();
/**
* The room timeline for this sync batch.
*
* @return the timeline.
*/
Timeline getTimeline();
/**
* Ephemeral events of the room.
*
* @return a list of ephemeral events.
*/
Ephemeral getEphemeral();
/**
* Account events of the room.
*
* @return a list of account data events.
*/
AccountData getAccountData();
/**
* The Counts of unread notifications.
*
* @return unread notifications.
*/
UnreadNotifications getUnreadNotifications();
}
interface LeftRoom {
/**
* The ID of the room the user is joined to.
*
* @return the room id.
*/
String getId();
/**
* State changes prior the start of the timeline.
*
* @return a list of state events.
*/
State getState();
/**
* The room timeline up to the leave event.
*
* @return the timeline.
*/
Timeline getTimeline();
}
interface Rooms {
/**
* Rooms the user was invited to within this sync window.
*
* @return Set of InvitedRoom objects.
*/
Set<InvitedRoom> getInvited();
/**
* Rooms the user was joined in within this sync window.
*
* @return Set of JoinedRoom objects.
*/
Set<JoinedRoom> getJoined();
/**
* Rooms the user left from within this sync window.
*
* @return Set of LeftRoom objects.
*/
Set<LeftRoom> getLeft();
}
/**
* The batch token to supply in the next sync call.
*
* @return the batch token.
*/
String nextBatchToken();
/**
* The global private data created by this user.
*
* @return the account data.
*/
AccountData getAccountData();
/**
* Update to the rooms.
*
* @return rooms object.
*/
Rooms getRooms();
/**
* The raw JSON data for this object.
*
* @return the JSON data.
*/
JsonObject getJson();
}

View File

@@ -0,0 +1,65 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import java.util.Optional;
/**
* Possible options that can be passed to the sync call.
*/
public interface _SyncOptions {
/**
* The point of time to continue the sync from.
*
* @return A token that was provided in a previous sync call, if set.
*/
Optional<String> getSince();
/**
* The filter to use for the sync.
*
* @return The ID or raw JSON filter, if set.
*/
Optional<String> getFilter();
/**
* If the full state should be included in the sync.
*
* @return The full state option, if set.
*/
Optional<Boolean> withFullState();
/**
* If the client should automatically be marked as online.
*
* @return The set presence option, if set.
*/
Optional<String> getSetPresence();
/**
* The maximum time to wait, in milliseconds, before ending the sync call.
*
* @return The timeout option, if set.
*/
Optional<Long> getTimeout();
}

View File

@@ -0,0 +1,87 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.as;
import io.kamax.matrix.client.MatrixClientContext;
import io.kamax.matrix.client.MatrixClientDefaults;
import io.kamax.matrix.client._MatrixClient;
import io.kamax.matrix.client.regular.MatrixHttpClient;
import io.kamax.matrix.json.VirtualUserRegistrationBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URL;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class MatrixApplicationServiceClient extends MatrixHttpClient implements _MatrixApplicationServiceClient {
private Logger log = LoggerFactory.getLogger(MatrixApplicationServiceClient.class);
public MatrixApplicationServiceClient(String domain) {
super(domain);
}
public MatrixApplicationServiceClient(URL hsBaseUrl) {
super(hsBaseUrl);
}
public MatrixApplicationServiceClient(MatrixClientContext context) {
super(context);
}
public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient.Builder client) {
super(context, client);
}
public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient.Builder client,
MatrixClientDefaults defaults) {
super(context, client, defaults);
}
public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient client) {
super(context, client);
}
private MatrixHttpClient createClient(String localpart) {
MatrixClientContext context = new MatrixClientContext(getContext()).setUserWithLocalpart(localpart)
.setVirtual(true);
return new MatrixHttpClient(context);
}
@Override
public _MatrixClient createUser(String localpart) {
log.debug("Creating new user {}", localpart);
URL path = getClientPath("register");
executeAuthenticated(
new Request.Builder().post(getJsonBody(new VirtualUserRegistrationBody(localpart))).url(path));
return createClient(localpart);
}
@Override
public _MatrixClient getUser(String localpart) {
return createClient(localpart);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.as;
import io.kamax.matrix.client._MatrixClient;
public interface _MatrixApplicationServiceClient extends _MatrixClient {
_MatrixClient createUser(String localpart);
_MatrixClient getUser(String localpart);
}

View File

@@ -0,0 +1,68 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.kamax.matrix.client._GlobalPushRulesSet;
import io.kamax.matrix.json.GsonUtil;
import java.util.List;
public class GlobalPushRulesSet implements _GlobalPushRulesSet {
private JsonObject data;
public GlobalPushRulesSet(JsonObject data) {
this.data = data;
}
private List<JsonObject> getForKey(String key) {
return GsonUtil.asList(GsonUtil.findArray(data, key).orElseGet(JsonArray::new), JsonObject.class);
}
@Override
public List<JsonObject> getContent() {
return getForKey("content");
}
@Override
public List<JsonObject> getOverride() {
return getForKey("override");
}
@Override
public List<JsonObject> getRoom() {
return getForKey("room");
}
@Override
public List<JsonObject> getSender() {
return getForKey("sender");
}
@Override
public List<JsonObject> getUnderride() {
return getForKey("underride");
}
}

View File

@@ -0,0 +1,292 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUser;
import io.kamax.matrix.client.*;
import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.matrix.json.*;
import io.kamax.matrix.room.RoomAlias;
import io.kamax.matrix.room.RoomAliasLookup;
import io.kamax.matrix.room._RoomAliasLookup;
import io.kamax.matrix.room._RoomCreationOptions;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import okhttp3.*;
public class MatrixHttpClient extends AMatrixHttpClient implements _MatrixClient {
private Logger log = LoggerFactory.getLogger(MatrixHttpClient.class);
public MatrixHttpClient(String domain) {
super(domain);
}
public MatrixHttpClient(URL hsBaseUrl) {
super(hsBaseUrl);
}
public MatrixHttpClient(MatrixClientContext context) {
super(context);
}
public MatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client) {
super(context, client);
}
public MatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client, MatrixClientDefaults defaults) {
super(context, client, defaults);
}
public MatrixHttpClient(MatrixClientContext context, OkHttpClient client) {
super(context, client);
}
protected _MatrixID getIdentity(String token) {
URL path = getClientPath("account", "whoami");
String body = executeAuthenticated(new Request.Builder().get().url(path), token);
return MatrixID.from(GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "user_id")).acceptable();
}
@Override
public _MatrixID getWhoAmI() {
URL path = getClientPath("account", "whoami");
String body = executeAuthenticated(new Request.Builder().get().url(path));
return MatrixID.from(GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "user_id")).acceptable();
}
@Override
public void setDisplayName(String name) {
URL path = getClientPath("profile", getUserId(), "displayname");
execute(new Request.Builder().put(getJsonBody(new UserDisplaynameSetBody(name))).url(path));
}
@Override
public _RoomAliasLookup lookup(RoomAlias alias) {
URL path = getClientPath("directory", "room", alias.getId());
String resBody = execute(new Request.Builder().get().url(path));
RoomAliasLookupJson lookup = GsonUtil.get().fromJson(resBody, RoomAliasLookupJson.class);
return new RoomAliasLookup(lookup.getRoomId(), alias.getId(), lookup.getServers());
}
@Override
public _MatrixRoom createRoom(_RoomCreationOptions options) {
URL path = getClientPath("createRoom");
String resBody = executeAuthenticated(
new Request.Builder().post(getJsonBody(new RoomCreationRequestJson(options))).url(path));
String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId();
return getRoom(roomId);
}
@Override
public _MatrixRoom getRoom(String roomId) {
return new MatrixHttpRoom(getContext(), roomId);
}
@Override
public List<_MatrixRoom> getJoinedRooms() {
URL path = getClientPath("joined_rooms");
JsonObject resBody = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().get().url(path)));
return GsonUtil.asList(resBody, "joined_rooms", String.class).stream().map(this::getRoom)
.collect(Collectors.toList());
}
@Override
public _MatrixRoom joinRoom(String roomIdOrAlias) {
URL path = getClientPath("join", roomIdOrAlias);
String resBody = executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId();
return getRoom(roomId);
}
@Override
public _MatrixUser getUser(_MatrixID mxId) {
return new MatrixHttpUser(getContext(), mxId);
}
@Override
public Optional<String> getDeviceId() {
return Optional.ofNullable(context.getDeviceId());
}
protected void updateContext(String resBody) {
LoginResponse response = gson.fromJson(resBody, LoginResponse.class);
context.setToken(response.getAccessToken());
context.setDeviceId(response.getDeviceId());
context.setUser(MatrixID.asAcceptable(response.getUserId()));
}
@Override
public void register(MatrixPasswordCredentials credentials, String sharedSecret, boolean admin) {
// As per synapse registration script:
// https://github.com/matrix-org/synapse/blob/master/scripts/register_new_matrix_user#L28
String value = credentials.getLocalPart() + "\0" + credentials.getPassword() + "\0"
+ (admin ? "admin" : "notadmin");
String mac = new HmacUtils(HmacAlgorithms.HMAC_SHA_1, sharedSecret).hmacHex(value);
JsonObject body = new JsonObject();
body.addProperty("user", credentials.getLocalPart());
body.addProperty("password", credentials.getPassword());
body.addProperty("mac", mac);
body.addProperty("type", "org.matrix.login.shared_secret");
body.addProperty("admin", false);
URL url = getPath("client", "api", "v1", "register");
updateContext(execute(new Request.Builder().post(getJsonBody(body)).url(url)));
}
@Override
public void setAccessToken(String accessToken) {
context.setUser(getIdentity(accessToken));
context.setToken(accessToken);
}
@Override
public void login(MatrixPasswordCredentials credentials) {
URL url = getClientPath("login");
LoginPostBody data = new LoginPostBody(credentials.getLocalPart(), credentials.getPassword());
getDeviceId().ifPresent(data::setDeviceId);
Optional.ofNullable(context.getInitialDeviceName()).ifPresent(data::setInitialDeviceDisplayName);
updateContext(execute(new Request.Builder().post(getJsonBody(data)).url(url)));
}
@Override
public void logout() {
URL path = getClientPath("logout");
executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
context.setToken(null);
context.setUser(null);
context.setDeviceId(null);
}
@Override
public _SyncData sync(_SyncOptions options) {
long start = System.currentTimeMillis();
HttpUrl.Builder path = getClientPathBuilder("sync");
path.addQueryParameter("timeout", options.getTimeout().map(Long::intValue).orElse(30000).toString());
options.getSince().ifPresent(since -> path.addQueryParameter("since", since));
options.getFilter().ifPresent(filter -> path.addQueryParameter("filter", filter));
options.withFullState().ifPresent(state -> path.addQueryParameter("full_state", state ? "true" : "false"));
options.getSetPresence().ifPresent(presence -> path.addQueryParameter("presence", presence));
String body = executeAuthenticated(new Request.Builder().get().url(path.build().url()));
long request = System.currentTimeMillis();
log.info("Sync: network request took {} ms", (request - start));
SyncDataJson data = new SyncDataJson(GsonUtil.parseObj(body));
long parsing = System.currentTimeMillis();
log.info("Sync: parsing took {} ms", (parsing - request));
return data;
}
@Override
public _MatrixContent getMedia(String mxUri) throws IllegalArgumentException {
return getMedia(URI.create(mxUri));
}
@Override
public _MatrixContent getMedia(URI mxUri) throws IllegalArgumentException {
return new MatrixHttpContent(context, mxUri);
}
private String putMedia(Request.Builder builder, String filename) {
HttpUrl.Builder b = getMediaPathBuilder("upload");
if (StringUtils.isNotEmpty(filename)) b.addQueryParameter("filename", filename);
String body = executeAuthenticated(builder.url(b.build()));
return GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "content_uri");
}
@Override
public String putMedia(byte[] data, String type) {
return putMedia(data, type, null);
}
@Override
public String putMedia(byte[] data, String type, String filename) {
return putMedia(new Request.Builder().post(RequestBody.create(MediaType.parse(type), data)), filename);
}
@Override
public String putMedia(File data, String type) {
return putMedia(data, type, null);
}
@Override
public String putMedia(File data, String type, String filename) {
return putMedia(new Request.Builder().post(RequestBody.create(MediaType.parse(type), data)), filename);
}
@Override
public List<JsonObject> getPushers() {
URL url = getClientPath("pushers");
JsonObject response = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().get().url(url)));
return GsonUtil.findArray(response, "pushers").map(array -> GsonUtil.asList(array, JsonObject.class))
.orElse(Collections.emptyList());
}
@Override
public void setPusher(JsonObject pusher) {
URL url = getClientPath("pushers", "set");
executeAuthenticated(new Request.Builder().url(url).post(getJsonBody(pusher)));
}
@Override
public void deletePusher(String pushKey) {
JsonObject pusher = new JsonObject();
pusher.add("kind", JsonNull.INSTANCE);
pusher.addProperty("pushkey", pushKey);
setPusher(pusher);
}
@Override
public _GlobalPushRulesSet getPushRules() {
URL url = getClientPath("pushrules", "global", "");
JsonObject response = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().url(url).get()));
return new GlobalPushRulesSet(response);
}
@Override
public _PushRule getPushRule(String scope, String kind, String id) {
return new MatrixHttpPushRule(context, scope, kind, id);
}
}

View File

@@ -0,0 +1,48 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonObject;
import io.kamax.matrix.client._Presence;
import io.kamax.matrix.json.GsonUtil;
public class Presence implements _Presence {
private String status;
private Long lastActive;
public Presence(JsonObject json) {
this.status = GsonUtil.getStringOrThrow(json, "presence");
this.lastActive = GsonUtil.getLong(json, "last_active_ago");
}
@Override
public String getStatus() {
return status;
}
@Override
public Long getLastActive() {
return lastActive;
}
}

View File

@@ -0,0 +1,390 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.client._SyncData;
import io.kamax.matrix.event.EventKey;
import io.kamax.matrix.event._MatrixAccountDataEvent;
import io.kamax.matrix.event._MatrixEphemeralEvent;
import io.kamax.matrix.event._MatrixPersistentEvent;
import io.kamax.matrix.event._MatrixStateEvent;
import io.kamax.matrix.json.MatrixJsonObject;
import java.util.*;
public class SyncDataJson extends MatrixJsonObject implements _SyncData {
public class MatrixPersistentEventJson extends MatrixJsonObject implements _MatrixPersistentEvent {
public MatrixPersistentEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getId() {
return findString(EventKey.Id.get()).orElse(""); // FIXME refactor event structure
}
@Override
public String getType() {
return getString(EventKey.Type.get());
}
@Override
public Long getTime() {
return getLong(EventKey.Timestamp.get());
}
@Override
public _MatrixID getSender() {
return MatrixID.from(getString(EventKey.Sender.get())).acceptable();
}
}
public class MatrixEphemeralEventJson extends MatrixJsonObject implements _MatrixEphemeralEvent {
public MatrixEphemeralEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getType() {
return getString(EventKey.Type.get());
}
}
public class MatrixAccountDataEventJson extends MatrixJsonObject implements _MatrixAccountDataEvent {
public MatrixAccountDataEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getType() {
return getString(EventKey.Type.get());
}
}
public class MatrixStateEventJson extends MatrixPersistentEventJson implements _MatrixStateEvent {
public MatrixStateEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getStateKey() {
return getString(EventKey.StateKey.get());
}
}
public class StateJson extends MatrixJsonObject implements _SyncData.State {
private List<_MatrixStateEvent> events = new ArrayList<>();
public StateJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixStateEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixStateEvent> getEvents() {
return events;
}
}
public class TimelineJson extends MatrixJsonObject implements _SyncData.Timeline {
private List<_MatrixPersistentEvent> events = new ArrayList<>();
public TimelineJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixPersistentEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixPersistentEvent> getEvents() {
return events;
}
@Override
public boolean isLimited() {
return findString("limited").map("true"::equals).orElse(false);
}
@Override
public String getPreviousBatchToken() {
return getString("prev_batch");
}
}
public class EphemeralJson extends MatrixJsonObject implements _SyncData.Ephemeral {
private List<_MatrixEphemeralEvent> events = new ArrayList<>();
public EphemeralJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixEphemeralEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixEphemeralEvent> getEvents() {
return events;
}
}
public class AccountDataJson extends MatrixJsonObject implements _SyncData.AccountData {
private List<_MatrixAccountDataEvent> events = new ArrayList<>();
public AccountDataJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixAccountDataEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixAccountDataEvent> getEvents() {
return events;
}
}
public class InvitedRoomJson extends MatrixJsonObject implements _SyncData.InvitedRoom {
private String id;
private State state;
public InvitedRoomJson(String id, JsonObject data) {
super(data);
this.id = id;
this.state = new StateJson(findObj("invite_state").orElseGet(JsonObject::new));
}
@Override
public String getId() {
return id;
}
@Override
public State getState() {
return state;
}
}
public class UnreadNotificationsJson extends MatrixJsonObject implements _SyncData.UnreadNotifications {
private long highlights;
private long global;
public UnreadNotificationsJson(JsonObject data) {
super(data);
this.highlights = findLong("highlight_count").orElse(0L);
this.global = findLong("notification_count").orElse(0L);
}
@Override
public long getHighlightCount() {
return highlights;
}
@Override
public long getNotificationCount() {
return global;
}
}
public class JoinedRoomJson extends MatrixJsonObject implements _SyncData.JoinedRoom {
private String id;
private State state;
private Timeline timeline;
private UnreadNotifications unreadNotifications;
private Ephemeral ephemeral;
private AccountData accountData;
public JoinedRoomJson(String id, JsonObject data) {
super(data);
this.id = id;
this.state = new StateJson(findObj("state").orElseGet(JsonObject::new));
this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new));
this.unreadNotifications = new UnreadNotificationsJson(computeObj("unread_notifications"));
this.ephemeral = new EphemeralJson(findObj("ephemeral").orElseGet(JsonObject::new));
this.accountData = new AccountDataJson(findObj("account_data").orElseGet(JsonObject::new));
}
@Override
public String getId() {
return id;
}
@Override
public State getState() {
return state;
}
@Override
public Timeline getTimeline() {
return timeline;
}
@Override
public Ephemeral getEphemeral() {
return ephemeral;
}
@Override
public AccountData getAccountData() {
return accountData;
}
@Override
public UnreadNotifications getUnreadNotifications() {
return unreadNotifications;
}
}
public class LeftRoomJson extends MatrixPersistentEventJson implements _SyncData.LeftRoom {
private String id;
private State state;
private Timeline timeline;
public LeftRoomJson(String id, JsonObject data) {
super(data);
this.id = id;
this.state = new StateJson(findObj("state").orElseGet(JsonObject::new));
this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new));
}
@Override
public String getId() {
return id;
}
@Override
public State getState() {
return state;
}
@Override
public Timeline getTimeline() {
return timeline;
}
}
public class RoomsJson extends MatrixJsonObject implements _SyncData.Rooms {
private Set<InvitedRoom> invited = new HashSet<>();
private Set<JoinedRoom> joined = new HashSet<>();
private Set<LeftRoom> left = new HashSet<>();
public RoomsJson(JsonObject obj) {
super(obj);
findObj("invite").ifPresent(o -> {
for (Map.Entry<String, JsonElement> entry : o.entrySet()) {
invited.add(new InvitedRoomJson(entry.getKey(), asObj(entry.getValue())));
}
});
findObj("join").ifPresent(o -> {
for (Map.Entry<String, JsonElement> entry : o.entrySet()) {
joined.add(new JoinedRoomJson(entry.getKey(), asObj(entry.getValue())));
}
});
findObj("leave").ifPresent(o -> {
for (Map.Entry<String, JsonElement> entry : o.entrySet()) {
left.add(new LeftRoomJson(entry.getKey(), asObj(entry.getValue())));
}
});
}
@Override
public Set<InvitedRoom> getInvited() {
return invited;
}
@Override
public Set<JoinedRoom> getJoined() {
return joined;
}
@Override
public Set<LeftRoom> getLeft() {
return left;
}
}
private String nextBatch;
private AccountDataJson accountData;
private RoomsJson rooms;
public SyncDataJson(JsonObject data) {
super(data);
nextBatch = getString("next_batch");
accountData = new AccountDataJson(findObj("account_data").orElseGet(JsonObject::new));
rooms = new RoomsJson(findObj("rooms").orElseGet(JsonObject::new));
}
@Override
public String nextBatchToken() {
return nextBatch;
}
@Override
public AccountData getAccountData() {
return accountData;
}
@Override
public Rooms getRooms() {
return rooms;
}
}

View File

@@ -0,0 +1,103 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import io.kamax.matrix.client._SyncOptions;
import java.util.Optional;
public class SyncOptions implements _SyncOptions {
public static class Builder {
private final SyncOptions obj;
public Builder() {
this.obj = new SyncOptions();
}
public SyncOptions get() {
return obj;
}
public Builder setSince(String since) {
obj.since = since;
return this;
}
public Builder setFilter(String filter) {
obj.filter = filter;
return this;
}
public Builder setWithFullState(boolean withFullState) {
obj.fullState = withFullState;
return this;
}
public Builder setPresence(boolean setPresence) {
obj.setPresence = setPresence ? null : "offline";
return this;
}
public Builder setTimeout(long timeout) {
obj.timeout = timeout;
return this;
}
}
public static Builder build() {
return new Builder();
}
private String since;
private String filter;
private Boolean fullState;
private String setPresence;
private Long timeout;
@Override
public Optional<String> getSince() {
return Optional.ofNullable(since);
}
@Override
public Optional<String> getFilter() {
return Optional.ofNullable(filter);
}
@Override
public Optional<Boolean> withFullState() {
return Optional.ofNullable(fullState);
}
@Override
public Optional<String> getSetPresence() {
return Optional.ofNullable(setPresence);
}
@Override
public Optional<Long> getTimeout() {
return Optional.ofNullable(timeout);
}
}

View File

@@ -0,0 +1,36 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.codec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class MxBase64 {
public static String encode(byte[] data) {
return Base64.getEncoder().withoutPadding().encodeToString(data);
}
public static String encode(String data) {
return encode(data.getBytes(StandardCharsets.UTF_8));
}
}

View File

@@ -0,0 +1,47 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.codec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MxSha256 {
private MessageDigest md;
public MxSha256() {
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public String hash(byte[] data) {
return MxBase64.encode(md.digest(data));
}
public String hash(String data) {
return hash(data.getBytes(StandardCharsets.UTF_8));
}
}

View File

@@ -0,0 +1,80 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class KeyFileStore implements _KeyStore {
private final Charset charset = StandardCharsets.UTF_8;
private File file;
public KeyFileStore(String path) {
File file = new File(path);
if (!file.exists()) {
throw new IllegalArgumentException("Signing key file storage " + path + " does not exist");
}
if (file.isDirectory()) {
throw new IllegalArgumentException("Signing key file storage " + path + " is a directory");
}
if (!file.isFile()) {
throw new IllegalArgumentException("Signing key file storage " + path + " is not a regular file");
}
if (!file.canRead()) {
throw new IllegalArgumentException("Signing key file storage " + path + " is not readable");
}
this.file = file;
}
@Override
public Optional<String> load() {
try {
List<String> keys = FileUtils.readLines(file, charset);
return keys.stream().filter(StringUtils::isNotBlank).findFirst();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void store(String key) {
try {
FileUtils.writeLines(file, charset.name(), Collections.singletonList(key), false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import io.kamax.matrix.codec.MxBase64;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
public class KeyManager {
public static KeyManager fromFile(String path) {
return new KeyManager(new KeyFileStore(path));
}
public static KeyManager fromMemory() {
return new KeyManager(new KeyMemoryStore());
}
private EdDSAParameterSpec keySpecs;
private List<KeyPair> keys;
public KeyManager(_KeyStore store) {
keySpecs = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
keys = new ArrayList<>();
String seedBase64 = store.load().orElseGet(() -> {
KeyPair pair = (new KeyPairGenerator()).generateKeyPair();
String keyEncoded = getPrivateKeyBase64((EdDSAPrivateKey) pair.getPrivate());
store.store(keyEncoded);
return keyEncoded;
});
byte[] seed = Base64.getDecoder().decode(seedBase64);
EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(seed, keySpecs);
EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKeySpec.getA(), keySpecs);
keys.add(new KeyPair(new EdDSAPublicKey(pubKeySpec), new EdDSAPrivateKey(privKeySpec)));
}
public int getCurrentIndex() {
return 0;
}
public KeyPair getKeys(int index) {
return keys.get(index);
}
public EdDSAPrivateKey getPrivateKey(int index) {
return (EdDSAPrivateKey) getKeys(index).getPrivate();
}
protected String getPrivateKeyBase64(EdDSAPrivateKey key) {
return MxBase64.encode(key.getSeed());
}
public String getPrivateKeyBase64(int index) {
return getPrivateKeyBase64(getPrivateKey(index));
}
public EdDSAPublicKey getPublicKey(int index) {
return (EdDSAPublicKey) getKeys(index).getPublic();
}
public EdDSAParameterSpec getSpecs() {
return keySpecs;
}
public String getPublicKeyBase64(int index) {
return MxBase64.encode(getPublicKey(index).getAbyte());
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import java.util.Optional;
public class KeyMemoryStore implements _KeyStore {
private String data;
public KeyMemoryStore() {
}
public KeyMemoryStore(String data) {
this.data = data;
}
@Override
public Optional<String> load() {
return Optional.ofNullable(data);
}
@Override
public void store(String key) {
data = key;
}
}

View File

@@ -0,0 +1,80 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import com.google.gson.JsonObject;
import io.kamax.matrix.codec.MxBase64;
import io.kamax.matrix.json.MatrixJson;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import net.i2p.crypto.eddsa.EdDSAEngine;
public class SignatureManager {
private KeyManager keyMgr;
private String domain;
private EdDSAEngine signEngine;
public SignatureManager(KeyManager keyMgr, String domain) {
this.keyMgr = keyMgr;
this.domain = domain;
try {
signEngine = new EdDSAEngine(MessageDigest.getInstance(keyMgr.getSpecs().getHashAlgorithm()));
signEngine.initSign(keyMgr.getPrivateKey(keyMgr.getCurrentIndex()));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException(e);
}
}
public String sign(JsonObject obj) {
return sign(MatrixJson.encodeCanonical(obj));
}
public String sign(String message) {
try {
byte[] signRaw = signEngine.signOneShot(message.getBytes());
return MxBase64.encode(signRaw);
} catch (SignatureException e) {
throw new RuntimeException(e);
}
}
public JsonObject signMessageGson(String message) {
String sign = sign(message);
JsonObject keySignature = new JsonObject();
// FIXME should create a signing key object what would give this ed and index values
keySignature.addProperty("ed25519:" + keyMgr.getCurrentIndex(), sign);
JsonObject signature = new JsonObject();
signature.add(domain, keySignature);
return signature;
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import java.util.Optional;
public interface _KeyStore {
Optional<String> load();
void store(String key);
}

View File

@@ -0,0 +1,88 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.kamax.matrix.MalformedEventException;
import io.kamax.matrix.json.GsonUtil;
import java.util.Optional;
public enum EventKey {
AuthEvents("auth_events"),
Content("content"),
Depth("depth"),
Hashes("hashes"),
Id("event_id"),
Origin("origin"),
Timestamp("origin_server_ts"),
PreviousEvents("prev_events"),
PreviousState("prev_state"),
RoomId("room_id"),
Sender("sender"),
Signatures("signatures"),
StateKey("state_key"),
Type("type"),
Membership("membership"),
Unsigned("unsigned");
private String key;
EventKey(String key) {
this.key = key;
}
public String get() {
return key;
}
public JsonObject getObj(JsonObject o) {
return findObj(o).orElseThrow(() -> new MalformedEventException(key));
}
public JsonElement getElement(JsonObject o) {
return GsonUtil.findElement(o, key).orElseThrow(() -> new MalformedEventException(key));
}
public Optional<JsonObject> findObj(JsonObject o) {
return GsonUtil.findObj(o, key);
}
public Optional<String> findString(JsonObject o) {
return GsonUtil.findString(o, key);
}
public String getString(JsonObject o) {
return findString(o).orElseThrow(() -> new MalformedEventException(key));
}
public String getStringOrNull(JsonObject o) {
return GsonUtil.getStringOrNull(o, key);
}
public long getLong(JsonObject o) {
return GsonUtil.getLong(o, key);
}
}

View File

@@ -0,0 +1,34 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import io.kamax.matrix._MatrixID;
import java.util.List;
import java.util.Map;
public interface _DirectEvent extends _MatrixEphemeralEvent {
String Type = "m.direct";
Map<_MatrixID, List<String>> getMappings();
}

View File

@@ -0,0 +1,24 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
public interface _MatrixAccountDataEvent extends _MatrixEvent {
}

View File

@@ -0,0 +1,25 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package io.kamax.matrix.event;
public interface _MatrixEphemeralEvent extends _MatrixEvent {
}

View File

@@ -0,0 +1,32 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package io.kamax.matrix.event;
import com.google.gson.JsonObject;
public interface _MatrixEvent {
String getType();
JsonObject getJson();
}

View File

@@ -0,0 +1,33 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import io.kamax.matrix._MatrixID;
public interface _MatrixPersistentEvent extends _MatrixEvent {
String getId();
Long getTime();
_MatrixID getSender();
}

View File

@@ -0,0 +1,27 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
public interface _MatrixStateEvent extends _MatrixPersistentEvent {
String getStateKey();
}

View File

@@ -0,0 +1,32 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package io.kamax.matrix.event;
import io.kamax.matrix.json.event.MatrixJsonReadReceiptEvent;
import java.util.List;
public interface _ReadReceiptEvent extends _MatrixEphemeralEvent {
List<MatrixJsonReadReceiptEvent.Receipt> getReceipts();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import java.util.List;
public interface _RoomAliasesEvent extends _RoomEvent {
List<String> getAliases();
}

View File

@@ -0,0 +1,27 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
public interface _RoomAvatarEvent extends _RoomEvent {
String getUrl();
}

View File

@@ -0,0 +1,33 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import java.util.Optional;
public interface _RoomCanonicalAliasEvent extends _RoomEvent {
String Type = "m.room.canonical_alias";
boolean hasAlias();
Optional<String> getAlias();
}

View File

@@ -0,0 +1,27 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
public interface _RoomEvent extends _MatrixPersistentEvent {
String getRoomId();
}

View File

@@ -0,0 +1,34 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import io.kamax.matrix.room.RoomHistoryVisibility;
public interface _RoomHistoryVisibilityEvent extends _RoomEvent {
/**
* There is an enum for handling the return values defined in th specification: {@link RoomHistoryVisibility}
*
* @return The current setting of the room for the visibility of future messages.
*/
String getHistoryVisibility();
}

View File

@@ -0,0 +1,37 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import io.kamax.matrix._MatrixID;
import java.util.Optional;
public interface _RoomMembershipEvent extends _RoomEvent {
String getMembership();
Optional<String> getAvatarUrl();
Optional<String> getDisplayName();
_MatrixID getInvitee();
}

View File

@@ -0,0 +1,35 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import java.util.Optional;
public interface _RoomMessageEvent extends _RoomEvent {
String getBody();
String getBodyType();
Optional<String> getFormat();
Optional<String> getFormattedBody();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import java.util.Optional;
public interface _RoomNameEvent extends _RoomEvent {
Optional<String> getName();
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import java.util.Map;
import java.util.Optional;
public interface _RoomPowerLevelsEvent extends _RoomEvent {
Optional<Double> getBan();
Map<String, Double> getEvents();
Optional<Double> getEventsDefault();
Optional<Double> getInvite();
Optional<Double> getKick();
Optional<Double> getRedact();
Optional<Double> getStateDefault();
Map<String, Double> getUsers();
Optional<Double> getUsersDefault();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import java.util.Optional;
public interface _RoomTopicEvent extends _RoomEvent {
Optional<String> getTopic();
}

View File

@@ -0,0 +1,34 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.event;
import io.kamax.matrix.room.Tag;
import java.util.List;
public interface _TagsEvent extends _MatrixEvent {
String Type = "m.tag";
List<Tag> getTags();
}

View File

@@ -0,0 +1,58 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.hs;
import java.net.MalformedURLException;
import java.net.URL;
public class MatrixHomeserver implements _MatrixHomeserver {
private String domain;
private URL base;
private static URL getURL(String url) {
try {
return new URL(url);
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
public MatrixHomeserver(String domain, URL baseUrl) {
this.domain = domain;
this.base = baseUrl;
}
public MatrixHomeserver(String domain, String baseUrl) {
this(domain, getURL(baseUrl));
}
@Override
public String getDomain() {
return domain;
}
@Override
public URL getBaseEndpoint() {
return base;
}
}

View File

@@ -0,0 +1,45 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.hs;
public enum RoomMembership {
Invite("invite"),
Join("join"),
Leave("leave"),
Ban("ban"),
Knock("knock");
private String id;
RoomMembership(String id) {
this.id = id;
}
public String get() {
return id;
}
public boolean is(String id) {
return this.id.contentEquals(id);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.hs;
import java.net.URL;
public interface _MatrixHomeserver {
String getDomain();
URL getBaseEndpoint();
}

View File

@@ -0,0 +1,159 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.hs;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixErrorInfo;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUserProfile;
import io.kamax.matrix.room.*;
import java.util.List;
import java.util.Optional;
public interface _MatrixRoom {
_MatrixHomeserver getHomeserver();
String getAddress();
Optional<String> getName();
Optional<String> getTopic();
Optional<String> getAvatarUrl();
Optional<_MatrixContent> getAvatar();
String getId();
/**
* Get a state event
*
* @param type
* The type of state to look for
* @return An optional JsonObject representing the content key of the event
*/
Optional<JsonObject> getState(String type);
/**
* Get a state event
*
* @param type
* The type of state to look for
* @param key
* The state key to match
* @return An optional JsonObject representing the content key of the event
*/
Optional<JsonObject> getState(String type, String key);
void join();
void join(List<String> servers);
Optional<MatrixErrorInfo> tryJoin();
Optional<MatrixErrorInfo> tryJoin(List<String> servers);
void leave();
Optional<MatrixErrorInfo> tryLeave();
void kick(_MatrixID user);
void kick(_MatrixID user, String reason);
Optional<MatrixErrorInfo> tryKick(_MatrixID user);
Optional<MatrixErrorInfo> tryKick(_MatrixID user, String reason);
String sendEvent(String type, JsonObject content);
String sendText(String message);
String sendFormattedText(String formatted, String rawFallback);
String sendNotice(String message);
String sendNotice(String formatted, String plain);
/**
* Send a receipt for an event
*
* @param type
* The receipt type to send
* @param eventId
* The Event ID targeted by the receipt
*/
void sendReceipt(String type, String eventId);
/**
* Send a receipt for an event
*
* @param type
* The receipt type to send
* @param eventId
* The Event ID targeted by the receipt
*/
void sendReceipt(ReceiptType type, String eventId);
/**
* Send a Read receipt for an event
*
* @param eventId
* The Event ID targeted by the read receipt
*/
void sendReadReceipt(String eventId);
void invite(_MatrixID mxId);
List<_MatrixUserProfile> getJoinedUsers();
_MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options);
List<Tag> getAllTags();
List<Tag> getUserTags();
void addUserTag(String tag);
void addUserTag(String tag, double order);
void deleteUserTag(String tag);
void addFavouriteTag();
void addFavouriteTag(double order);
void deleteFavouriteTag();
Optional<Tag> getFavouriteTag();
void addLowpriorityTag();
void addLowpriorityTag(double order);
Optional<Tag> getLowpriorityTag();
void deleteLowpriorityTag();
}

View File

@@ -0,0 +1,35 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.is;
import io.kamax.matrix._ThreePid;
import io.kamax.matrix._ThreePidMapping;
import java.util.List;
import java.util.Optional;
public interface _IdentityServer {
Optional<_ThreePidMapping> find(_ThreePid threePid);
List<_ThreePidMapping> find(List<_ThreePid> threePidList);
}

View File

@@ -0,0 +1,193 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import com.google.gson.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class GsonUtil {
private static Gson instance = build();
private static Gson instancePretty = buildPretty();
private static GsonBuilder buildImpl() {
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.disableHtmlEscaping();
}
public static Gson buildPretty() {
return buildImpl().setPrettyPrinting().create();
}
public static Gson build() {
return buildImpl().create();
}
public static JsonArray asArray(List<JsonElement> elements) {
JsonArray a = new JsonArray();
elements.forEach(a::add);
return a;
}
public static JsonArray asArrayObj(List<? extends Object> elements) {
return asArray(elements.stream().map(e -> get().toJsonTree(e)).collect(Collectors.toList()));
}
public static JsonArray asArray(String... elements) {
return asArray(
Arrays.stream(elements).map(JsonPrimitive::new).collect(Collectors.toList()));
}
public static JsonArray asArray(Collection<String> elements) {
JsonArray a = new JsonArray();
elements.forEach(a::add);
return a;
}
public static <T> List<T> asList(JsonArray a, Class<T> c) {
List<T> l = new ArrayList<>();
for (JsonElement v : a) {
l.add(GsonUtil.get().fromJson(v, c));
}
return l;
}
public static <T> List<T> asList(JsonObject obj, String member, Class<T> c) {
return asList(getArray(obj, member), c);
}
public static JsonObject makeObj(Object o) {
return instance.toJsonTree(o).getAsJsonObject();
}
public static JsonObject makeObj(String key, Object value) {
return makeObj(key, instance.toJsonTree(value));
}
public static JsonObject makeObj(String key, JsonElement el) {
JsonObject obj = new JsonObject();
obj.add(key, el);
return obj;
}
public static JsonObject makeObj(Consumer<JsonObject> consumer) {
JsonObject obj = new JsonObject();
consumer.accept(obj);
return obj;
}
public static Gson get() {
return instance;
}
public static Gson getPretty() {
return instancePretty;
}
public static String getPrettyForLog(Object o) {
return System.lineSeparator() + getPretty().toJson(o);
}
public static JsonElement parse(String s) {
try {
return new JsonParser().parse(s);
} catch (JsonParseException e) {
throw new InvalidJsonException(e);
}
}
public static JsonObject parseObj(String s) {
try {
return parse(s).getAsJsonObject();
} catch (IllegalStateException e) {
throw new InvalidJsonException("Not an object");
}
}
public static JsonArray getArray(JsonObject obj, String member) {
return findArray(obj, member).orElseThrow(() -> new InvalidJsonException("Not an array"));
}
public static JsonObject getObj(JsonObject obj, String member) {
return findObj(obj, member).orElseThrow(() -> new InvalidJsonException("No object for member " + member));
}
public static Optional<String> findString(JsonObject o, String key) {
return findPrimitive(o, key).map(JsonPrimitive::getAsString);
}
public static String getStringOrNull(JsonObject o, String key) {
JsonElement el = o.get(key);
if (el != null && el.isJsonPrimitive()) {
return el.getAsString();
} else {
return null;
}
}
public static String getStringOrThrow(JsonObject obj, String member) {
if (!obj.has(member)) {
throw new InvalidJsonException(member + " key is missing");
}
return obj.get(member).getAsString();
}
public static Optional<JsonElement> findElement(JsonObject o, String key) {
return Optional.ofNullable(o.get(key));
}
public static Optional<JsonPrimitive> findPrimitive(JsonObject o, String key) {
return findElement(o, key).map(el -> el.isJsonPrimitive() ? el.getAsJsonPrimitive() : null);
}
public static JsonPrimitive getPrimitive(JsonObject o, String key) {
return findPrimitive(o, key).orElseThrow(() -> new InvalidJsonException("No primitive value for key " + key));
}
public static Optional<Long> findLong(JsonObject o, String key) {
return findPrimitive(o, key).map(JsonPrimitive::getAsLong);
}
public static long getLong(JsonObject o, String key) {
return findLong(o, key).orElseThrow(() -> new InvalidJsonException("No numeric value for key " + key));
}
public static Optional<JsonObject> findObj(JsonObject o, String key) {
if (!o.has(key)) {
return Optional.empty();
}
return Optional.ofNullable(o.getAsJsonObject(key));
}
public static Optional<JsonArray> findArray(JsonObject o, String key) {
return findElement(o, key).filter(JsonElement::isJsonArray).map(JsonElement::getAsJsonArray);
}
}

View File

@@ -0,0 +1,35 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import io.kamax.matrix.MatrixException;
public class InvalidJsonException extends MatrixException {
public InvalidJsonException(Throwable t) {
super("M_BAD_JSON", t.getMessage(), t);
}
public InvalidJsonException(String error) {
super("M_BAD_JSON", error);
}
}

View File

@@ -0,0 +1,33 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class JsonCanonicalException extends RuntimeException {
public JsonCanonicalException(String message) {
super(message);
}
public JsonCanonicalException(Throwable t) {
super(t);
}
}

View File

@@ -0,0 +1,58 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class LoginPostBody {
private String type = "m.login.password";
private String user;
private String password;
private String deviceId;
private String initialDeviceDisplayName;
public LoginPostBody(String user, String password) {
this.user = user;
this.password = password;
}
public LoginPostBody(String user, String password, String deviceId) {
this(user, password);
this.deviceId = deviceId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getInitialDeviceDisplayName() {
return initialDeviceDisplayName;
}
public void setInitialDeviceDisplayName(String initialDeviceDisplayName) {
this.initialDeviceDisplayName = initialDeviceDisplayName;
}
}

View File

@@ -0,0 +1,45 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class LoginResponse {
private String access_token;
private String home_server;
private String user_id;
private String device_id;
public String getAccessToken() {
return access_token;
}
public String getHomeServer() {
return home_server;
}
public String getUserId() {
return user_id;
}
public String getDeviceId() {
return device_id;
}
}

View File

@@ -0,0 +1,115 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.Map;
public class MatrixJson {
// Needed to avoid silly try/catch block in lambdas
// We only use ByteArray streams, so IOException will not happen (unless irrecoverable situation like OOM)
private static class JsonWriterUnchecked extends JsonWriter {
public JsonWriterUnchecked(Writer out) {
super(out);
}
@Override
public JsonWriter name(String value) {
try {
return super.name(value);
} catch (IOException e) {
throw new JsonCanonicalException(e);
}
}
}
private static JsonParser parser = new JsonParser();
private static void encodeCanonical(JsonObject el, JsonWriterUnchecked writer) throws IOException {
writer.beginObject();
el.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entry -> {
writer.name(entry.getKey());
encodeCanonicalElement(entry.getValue(), writer);
});
writer.endObject();
}
private static void encodeCanonicalArray(JsonArray array, JsonWriterUnchecked writer) throws IOException {
writer.beginArray();
array.forEach(el -> encodeCanonicalElement(el, writer));
writer.endArray();
}
private static void encodeCanonicalElement(JsonElement el, JsonWriterUnchecked writer) {
try {
if (el.isJsonObject()) encodeCanonical(el.getAsJsonObject(), writer);
else if (el.isJsonPrimitive()) writer.jsonValue(el.toString());
else if (el.isJsonArray()) encodeCanonicalArray(el.getAsJsonArray(), writer);
else if (el.isJsonNull()) writer.nullValue();
else throw new JsonCanonicalException("Unexpected JSON type, this is a bug, report!");
} catch (IOException e) {
throw new JsonCanonicalException(e);
}
}
public static String encodeCanonical(JsonObject obj) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
JsonWriterUnchecked writer = new JsonWriterUnchecked(new OutputStreamWriter(out, StandardCharsets.UTF_8));
writer.setIndent("");
writer.setHtmlSafe(false);
writer.setLenient(false);
encodeCanonical(obj, writer);
writer.close();
return out.toString(StandardCharsets.UTF_8.name());
} catch (IOException e) {
throw new JsonCanonicalException(e);
}
}
public static String encodeCanonical(String data) {
JsonElement el = parser.parse(data);
if (!el.isJsonObject()) {
/*
* TODO seems implied because of how signing/checking signatures is done and because of
* https://matrix.to/#/!XqBunHwQIXUiqCaoxq:matrix.org/$15075894901530229RWcIi:matrix.org
* with the "whole object".
*/
throw new JsonCanonicalException("Not a JSON object, cannot encode canonical");
}
return encodeCanonical(el.getAsJsonObject());
}
}

View File

@@ -0,0 +1,76 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import com.google.gson.JsonObject;
import io.kamax.matrix.event.*;
import io.kamax.matrix.json.event.*;
import java.util.Optional;
public class MatrixJsonEventFactory {
public static _MatrixEvent get(JsonObject obj) {
String type = obj.get("type").getAsString();
if ("m.room.member".contentEquals(type)) {
return new MatrixJsonRoomMembershipEvent(obj);
} else if ("m.room.power_levels".contentEquals(type)) {
return new MatrixJsonRoomPowerLevelsEvent(obj);
} else if ("m.room.avatar".contentEquals(type)) {
return new MatrixJsonRoomAvatarEvent(obj);
} else if ("m.room.name".contentEquals(type)) {
return new MatrixJsonRoomNameEvent(obj);
} else if ("m.room.topic".contentEquals(type)) {
return new MatrixJsonRoomTopicEvent(obj);
} else if ("m.room.aliases".contentEquals(type)) {
return new MatrixJsonRoomAliasesEvent(obj);
} else if (_RoomCanonicalAliasEvent.Type.contentEquals(type)) {
return new MatrixJsonRoomCanonicalAliasEvent(obj);
} else if ("m.room.message".contentEquals(type)) {
return new MatrixJsonRoomMessageEvent(obj);
} else if ("m.receipt".contentEquals(type)) {
return new MatrixJsonReadReceiptEvent(obj);
} else if ("m.room.history_visibility".contentEquals(type)) {
return new MatrixJsonRoomHistoryVisibilityEvent(obj);
} else if (_TagsEvent.Type.contentEquals(type)) {
return new MatrixJsonRoomTagsEvent(obj);
} else if (_DirectEvent.Type.contentEquals(type)) {
return new MatrixJsonDirectEvent(obj);
} else {
Optional<String> timestamp = EventKey.Timestamp.findString(obj);
Optional<String> sender = EventKey.Sender.findString(obj);
if (!timestamp.isPresent() || !sender.isPresent()) {
return new MatrixJsonEphemeralEvent(obj);
} else {
Optional<String> rId = EventKey.RoomId.findString(obj);
if (rId.isPresent()) {
return new MatrixJsonRoomEvent(obj);
}
return new MatrixJsonPersistentEvent(obj);
}
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import com.google.gson.*;
import java.util.Objects;
import java.util.Optional;
public class MatrixJsonObject {
private JsonObject obj;
public MatrixJsonObject(JsonObject obj) {
if (Objects.isNull(obj)) {
throw new InvalidJsonException("JSON Object is null");
}
this.obj = obj;
}
protected Optional<String> findString(String field) {
return GsonUtil.findString(obj, field);
}
protected String getString(String field) {
return GsonUtil.getStringOrNull(obj, field);
}
protected String getStringOrNull(JsonObject obj, String field) {
return GsonUtil.findString(obj, field).orElse(null);
}
protected String getStringOrNull(String field) {
return getStringOrNull(obj, field);
}
protected int getInt(String field) {
return GsonUtil.getPrimitive(obj, field).getAsInt();
}
protected int getInt(String field, int failover) {
return GsonUtil.findPrimitive(obj, field).map(JsonPrimitive::getAsInt).orElse(failover);
}
protected Optional<Long> findLong(String field) {
return GsonUtil.findLong(obj, field);
}
protected long getLong(String field) {
return GsonUtil.getLong(obj, field);
}
/*
* Returns the Double value, if the key is present, null else
*/
protected Double getDoubleIfPresent(String field) {
if (obj.get(field) != null) {
return GsonUtil.getPrimitive(obj, field).getAsDouble();
}
return null;
}
protected JsonObject asObj(JsonElement el) {
if (!el.isJsonObject()) {
throw new IllegalArgumentException("Not a JSON object");
}
return el.getAsJsonObject();
}
protected JsonObject getObj(String field) {
return GsonUtil.getObj(obj, field);
}
protected Optional<JsonObject> findObj(String field) {
return GsonUtil.findObj(obj, field);
}
protected JsonObject computeObj(String field) {
return findObj(field).orElseGet(JsonObject::new);
}
protected Optional<JsonArray> findArray(String field) {
return GsonUtil.findArray(obj, field);
}
public JsonObject getJson() {
return obj;
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import java.util.List;
public class RoomAliasLookupJson {
private String roomId;
private List<String> servers;
public String getRoomId() {
return roomId;
}
public void setRoomId(String roomId) {
this.roomId = roomId;
}
public List<String> getServers() {
return servers;
}
public void setServers(List<String> servers) {
this.servers = servers;
}
}

View File

@@ -0,0 +1,57 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import com.google.gson.JsonElement;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.room._RoomCreationOptions;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class RoomCreationRequestJson {
private String visibility;
private String roomAliasName;
private String name;
private String topic;
private Set<String> invite;
private Map<String, JsonElement> creationContent;
private String preset;
private Boolean isDirect;
private Boolean guestCanJoin;
public RoomCreationRequestJson(_RoomCreationOptions options) {
this.visibility = options.getVisibility().orElse(null);
this.roomAliasName = options.getAliasName().orElse(null);
this.name = options.getName().orElse(null);
this.topic = options.getTopic().orElse(null);
this.invite = options.getInvites().filter(ids -> !ids.isEmpty())
.map(ids -> ids.stream().map(_MatrixID::getId).collect(Collectors.toSet())).orElse(null);
this.creationContent = options.getCreationContent().filter(c -> !c.isEmpty()).orElse(null);
this.preset = options.getPreset().orElse(null);
this.isDirect = options.isDirect().orElse(null);
this.guestCanJoin = options.isGuestCanJoin().orElse(null);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class RoomCreationResponseJson {
private String roomId;
public String getRoomId() {
return roomId;
}
}

View File

@@ -0,0 +1,45 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
import com.google.gson.JsonObject;
import java.util.List;
public class RoomMessageChunkResponseJson {
private String start;
private String end;
private List<JsonObject> chunk;
public String getStart() {
return start;
}
public String getEnd() {
return end;
}
public List<JsonObject> getChunk() {
return chunk;
}
}

View File

@@ -0,0 +1,48 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class RoomMessageFormattedTextPutBody extends RoomMessageTextPutBody {
private String formatted_body;
private String format = "org.matrix.custom.html";
public RoomMessageFormattedTextPutBody(String body, String formattedBody) {
super(body);
this.formatted_body = formattedBody;
}
public RoomMessageFormattedTextPutBody(String msgtype, String body, String formattedBody) {
super(msgtype, body);
this.formatted_body = formattedBody;
}
public String getFormatted_body() {
return formatted_body;
}
public String getFormat() {
return format;
}
}

View File

@@ -0,0 +1,45 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class RoomMessageTextPutBody {
private String msgtype = "m.text";
private String body;
public RoomMessageTextPutBody(String body) {
this.body = body;
}
public RoomMessageTextPutBody(String msgType, String body) {
this(body);
this.msgtype = msgType;
}
public String getMsgtype() {
return msgtype;
}
public String getBody() {
return body;
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class RoomTagSetBody {
private String order;
public RoomTagSetBody(double order) {
this.order = String.valueOf(order);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class UserDisplaynameSetBody {
private String displayname;
public UserDisplaynameSetBody(String displayname) {
this.displayname = displayname;
}
}

View File

@@ -0,0 +1,40 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json;
public class VirtualUserRegistrationBody {
private String type = "m.login.application_server";
private String username;
public VirtualUserRegistrationBody(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,63 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json.event;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.event._DirectEvent;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.InvalidJsonException;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MatrixJsonDirectEvent extends MatrixJsonEphemeralEvent implements _DirectEvent {
private Map<_MatrixID, List<String>> mappings = new HashMap<>();
public MatrixJsonDirectEvent(JsonObject obj) {
super(obj);
if (!StringUtils.equals(Type, getType())) { // FIXME check should be done in the abstract class
throw new InvalidJsonException("Type is not " + Type);
}
getObj("content").entrySet().forEach(entry -> {
if (!entry.getValue().isJsonArray()) {
throw new InvalidJsonException("Content key " + entry.getKey() + " is not an array");
}
_MatrixID id = MatrixID.asAcceptable(entry.getKey());
mappings.put(id, GsonUtil.asList(entry.getValue().getAsJsonArray(), String.class));
});
}
@Override
public Map<_MatrixID, List<String>> getMappings() {
return Collections.unmodifiableMap(mappings);
}
}

View File

@@ -0,0 +1,43 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package io.kamax.matrix.json.event;
import com.google.gson.JsonObject;
import io.kamax.matrix.event._MatrixEphemeralEvent;
import io.kamax.matrix.json.MatrixJsonObject;
public class MatrixJsonEphemeralEvent extends MatrixJsonObject implements _MatrixEphemeralEvent {
private String type;
public MatrixJsonEphemeralEvent(JsonObject obj) {
super(obj);
type = getString("type");
}
@Override
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,68 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json.event;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.event._MatrixPersistentEvent;
import io.kamax.matrix.json.MatrixJsonObject;
public class MatrixJsonPersistentEvent extends MatrixJsonObject implements _MatrixPersistentEvent {
private String id;
private String type;
private Long time;
private int age;
private _MatrixID sender;
public MatrixJsonPersistentEvent(JsonObject obj) {
super(obj);
id = getString("event_id");
type = getString("type");
time = getLong("origin_server_ts");
age = getInt("age", -1);
sender = MatrixID.asAcceptable(getString("sender"));
}
@Override
public String getId() {
return id;
}
@Override
public String getType() {
return type;
}
@Override
public Long getTime() {
return time;
}
@Override
public _MatrixID getSender() {
return sender;
}
}

View File

@@ -0,0 +1,95 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Arne Augenstein
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package io.kamax.matrix.json.event;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix.event._ReadReceiptEvent;
import io.kamax.matrix.json.GsonUtil;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class MatrixJsonReadReceiptEvent extends MatrixJsonEphemeralEvent implements _ReadReceiptEvent {
/**
* Read receipts for a specific event.
*/
public static class Receipt {
/**
* ID of the event, the read markers point to.
*/
private String eventId;
/**
* Every user whose read marker is set to the event specified by eventId
* and it's point in time when this marker has been set to this event.
*/
private Map<MatrixID, Long> users;
public Receipt(String id, Map<MatrixID, Long> readMarkers) {
this.eventId = id;
this.users = readMarkers;
}
public Map<MatrixID, Long> getUsersWithTimestamp() {
return users;
}
public Set<MatrixID> getUsers() {
return users.keySet();
}
public String getEventId() {
return eventId;
}
}
private List<Receipt> receipts;
@Override
public List<Receipt> getReceipts() {
return receipts;
}
public MatrixJsonReadReceiptEvent(JsonObject obj) {
super(obj);
JsonObject content = getObj("content");
List<String> eventIds = content.entrySet().stream().map(Map.Entry::getKey)
.collect(Collectors.toList());
receipts = eventIds.stream().map(id -> {
JsonObject targetEvent = content.getAsJsonObject(id);
JsonObject mRead = targetEvent.getAsJsonObject("m.read");
Map<MatrixID, Long> readMarkers = mRead.entrySet().stream()
.collect(Collectors.toMap(it -> MatrixID.asAcceptable(it.getKey()),
it -> GsonUtil.getLong(it.getValue().getAsJsonObject(), "ts")));
return new Receipt(id, readMarkers);
}).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,66 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json.event;
import com.google.gson.JsonObject;
import io.kamax.matrix.event._RoomAliasesEvent;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.MatrixJsonObject;
import java.util.Collections;
import java.util.List;
public class MatrixJsonRoomAliasesEvent extends MatrixJsonRoomEvent implements _RoomAliasesEvent {
public static class Content extends MatrixJsonObject {
private List<String> aliases;
public Content(JsonObject obj) {
super(obj);
setAliases(GsonUtil.asList(obj, "aliases", String.class));
}
public List<String> getAliases() {
return aliases;
}
public void setAliases(List<String> aliases) {
this.aliases = aliases;
}
}
protected Content content;
public MatrixJsonRoomAliasesEvent(JsonObject obj) {
super(obj);
this.content = new Content(getObj("content"));
}
@Override
public List<String> getAliases() {
return Collections.unmodifiableList(content.getAliases());
}
}

View File

@@ -0,0 +1,56 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.json.event;
import com.google.gson.JsonObject;
import io.kamax.matrix.event._RoomAvatarEvent;
import io.kamax.matrix.json.GsonUtil;
public class MatrixJsonRoomAvatarEvent extends MatrixJsonRoomEvent implements _RoomAvatarEvent {
public static class Content {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
protected Content content;
public MatrixJsonRoomAvatarEvent(JsonObject obj) {
super(obj);
this.content = GsonUtil.get().fromJson(getObj("content"), Content.class);
}
@Override
public String getUrl() {
return content.getUrl();
}
}

Some files were not shown because too many files have changed in this diff Show More