PartnerConfiguration.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Waarp 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.openr66.protocol.configuration;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.waarp.common.digest.FilesystemBasedDigest.DigestAlgo;
import org.waarp.common.json.JsonHandler;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.openr66.protocol.utils.R66Versions;
import org.waarp.openr66.protocol.utils.Version;
import java.util.Map;
/**
* Partner Configuration
*/
public class PartnerConfiguration {
/**
* Internal Logger
*/
private static final WaarpLogger logger =
WaarpLoggerFactory.getLogger(PartnerConfiguration.class);
/**
* Uses as separator in field
*/
public static final String BAR_JSON_FIELD = "{";
/**
* Uses as separator in field
*/
public static final String BAR_SEPARATOR_FIELD = ";";
/**
* Uses as separator in field
*/
public static final String BLANK_SEPARATOR_FIELD = " ";
public static final String VERSION_R66_SOFTWARE_3_6_1 = "3.6.1";
/**
* Uses as separator in field
*/
private static String SEPARATOR_FIELD = BAR_SEPARATOR_FIELD;
/**
* JSON Fields
*/
public enum FIELDS {
HOSTID("nohostid"), VERSION(R66Versions.V2_4_12.getVersion()),
DIGESTALGO(DigestAlgo.MD5.algoName), FILESIZE(false), FINALHASH(false),
PROXIFIED(false), SEPARATOR(BLANK_SEPARATOR_FIELD),
R66VERSION(R66Versions.V2_4_12.getVersion()), COMPRESSION(false);
final String name;
final Object defaultValue;
FIELDS(final Object def) {
name = name();
defaultValue = def;
}
}
private final String id;
private final ObjectNode root = JsonHandler.createObjectNode();
private final String version;
private final String r66Version;
private final boolean useJson;
private final boolean changeFileInfoEnabled;
private final DigestAlgo digestAlgo;
private final boolean compression;
private final String separator;
private final boolean supportReuseAuthentication;
/**
* Constructor for an external HostId
*
* @param id
* @param json mainly the version information
*/
public PartnerConfiguration(final String id, final String json) {
this.id = id;
JsonHandler.setValue(root, FIELDS.HOSTID, id);
final int pos = json == null? -1 : json.indexOf('{');
if (pos > 1) {
version = json.substring(0, pos - 1);
} else {
version = json;
}
JsonHandler.setValue(root, FIELDS.VERSION, version);
String r66 = R66Versions.V2_4_12.getVersion();
if (isVersion2GEQVersion1(R66Versions.V2_4_12.getVersion(), version)) {
JsonHandler.setValue(root, FIELDS.FILESIZE, true);
JsonHandler.setValue(root, FIELDS.FINALHASH, true);
} else {
JsonHandler.setValue(root, FIELDS.FILESIZE,
(Boolean) FIELDS.FILESIZE.defaultValue);
JsonHandler.setValue(root, FIELDS.FINALHASH,
(Boolean) FIELDS.FINALHASH.defaultValue);
}
JsonHandler.setValue(root, FIELDS.DIGESTALGO,
Configuration.configuration.getDigest().algoName);
JsonHandler.setValue(root, FIELDS.PROXIFIED,
(Boolean) FIELDS.PROXIFIED.defaultValue);
String sep = getSEPARATOR_FIELD();
if (!isVersion2GEQVersion1(R66Versions.V2_4_13.getVersion(), version)) {
r66 = R66Versions.V2_4_12.getVersion();
sep = BLANK_SEPARATOR_FIELD;
}
if (isVersion2GEQVersion1(R66Versions.V2_4_17.getVersion(), version)) {
r66 = R66Versions.V2_4_17.getVersion();
logger.debug("UseJson for {}:{}", id, json);
useJson = true;
} else {
logger.debug("NOT UseJson for {}:{}", id, json);
useJson = false;
}
if (isVersion2GEQVersion1(R66Versions.V3_0_4.getVersion(), version)) {
r66 = R66Versions.V3_0_4.getVersion();
changeFileInfoEnabled = true;
} else {
changeFileInfoEnabled = false;
}
final boolean comp = false;
if (isVersion2GEQVersion1(R66Versions.V3_1_0.getVersion(), version)) {
r66 = R66Versions.V3_1_0.getVersion();
}
JsonHandler.setValue(root, FIELDS.R66VERSION, r66);
JsonHandler.setValue(root, FIELDS.COMPRESSION, comp);
JsonHandler.setValue(root, FIELDS.SEPARATOR, sep);
if (json != null && pos > 1) {
final String realjson = json.substring(pos);
final ObjectNode info = JsonHandler.getFromString(realjson);
if (info != null) {
root.setAll(info);
}
}
if (isProxified()) {
Configuration.configuration.setBlacklistBadAuthent(false);
}
digestAlgo = getDigestAlgoInternal();
compression = root.get(FIELDS.COMPRESSION.name).asBoolean();
r66Version = root.get(FIELDS.R66VERSION.name).asText();
separator = root.get(FIELDS.SEPARATOR.name).asText();
supportReuseAuthentication =
isVersion2GEQVersion1(VERSION_R66_SOFTWARE_3_6_1, r66Version);
logger.info("Info on HostId: {}", root);
}
/**
* Self constructor
*
* @param id
*/
public PartnerConfiguration(final String id) {
this.id = id;
JsonHandler.setValue(root, FIELDS.HOSTID, id);
version = Version.ID;
JsonHandler.setValue(root, FIELDS.VERSION, Version.ID);
JsonHandler.setValue(root, FIELDS.FILESIZE, true);
JsonHandler.setValue(root, FIELDS.FINALHASH,
Configuration.configuration.isGlobalDigest());
JsonHandler.setValue(root, FIELDS.DIGESTALGO,
Configuration.configuration.getDigest().algoName);
JsonHandler.setValue(root, FIELDS.PROXIFIED,
Configuration.configuration.isHostProxyfied());
JsonHandler.setValue(root, FIELDS.SEPARATOR, getSEPARATOR_FIELD());
JsonHandler.setValue(root, FIELDS.R66VERSION,
org.waarp.common.utility.Version.version());
r66Version = org.waarp.common.utility.Version.version();
compression = Configuration.configuration.isCompressionAvailable();
JsonHandler.setValue(root, FIELDS.COMPRESSION, compression);
useJson = true;
changeFileInfoEnabled = true;
digestAlgo = getDigestAlgoInternal();
separator = getSEPARATOR_FIELD();
supportReuseAuthentication =
isVersion2GEQVersion1(VERSION_R66_SOFTWARE_3_6_1, r66Version);
logger.debug("Info on HostId: {}", root);
}
/**
* @return the associated HostId
*/
public final String getId() {
return id;
}
/**
* @return the version for this Host
*/
public final String getVersion() {
return version;
}
/**
* @return the R66Version for this Host
*/
public final String getR66Version() {
return r66Version;
}
/**
* @return True if compression is supported
*/
public final boolean isCompression() {
return compression;
}
/**
* @return True if this Host returns FileSize
*/
public final boolean useFileSize() {
return root.path(FIELDS.FILESIZE.name)
.asBoolean((Boolean) FIELDS.FILESIZE.defaultValue);
}
/**
* @return True if this Host returns a final hash
*/
public final boolean useFinalHash() {
return root.path(FIELDS.FINALHASH.name)
.asBoolean((Boolean) FIELDS.FINALHASH.defaultValue);
}
/**
* @return DigestAlgo if this Host returns Digest Algo used
*/
public final DigestAlgo getDigestAlgo() {
return digestAlgo;
}
/**
* Used to initialize the DigestAlgo for this partner
*
* @return the DigestAlgo
*/
private DigestAlgo getDigestAlgoInternal() {
final String algo = root.path(FIELDS.DIGESTALGO.name).asText();
return getDigestAlgo(algo);
}
/**
* @return True if this Host is proxified
*/
public final boolean isProxified() {
return root.path(FIELDS.PROXIFIED.name)
.asBoolean((Boolean) FIELDS.PROXIFIED.defaultValue);
}
/**
* @return the separator for this Host
*/
public final String getSeperator() {
return separator;
}
/**
* @return the useJson
*/
public final boolean useJson() {
return useJson;
}
/**
* @return the changeFileInfoEnabled
*/
public final boolean changeFileInfoEnabled() {
return changeFileInfoEnabled;
}
/**
* @return True if this Host support Reuse Authentication
*/
public final boolean supportReuseAuthentication() {
return supportReuseAuthentication;
}
/**
* @return the String representation as version.json
*/
@Override
public final String toString() {
return version + '.' + JsonHandler.writeAsString(root);
}
/**
* @param algo
*
* @return the DigestAlgo corresponding
*/
public static DigestAlgo getDigestAlgo(final String algo) {
for (final DigestAlgo alg : DigestAlgo.values()) {
if (alg.algoName.equals(algo)) {
return alg;
}
}
try {
return DigestAlgo.valueOf(algo);
} catch (final IllegalArgumentException ignored) {
// ignore
}
return Configuration.configuration.getDigest();
}
/**
* @param remoteHost
*
* @return the separator to be used
*/
public static String getSeparator(final String remoteHost) {
logger.debug("Versions: search: {} in {}", remoteHost,
Configuration.configuration.getVersions());
final PartnerConfiguration partner =
Configuration.configuration.getVersions().get(remoteHost);
if (partner != null) {
return partner.getSeperator();
}
return BLANK_SEPARATOR_FIELD;
}
/**
* Compare 2 versions
*
* @param version1
* @param version2
*
* @return True if version2 >= version1
*/
public static boolean isVersion2GEQVersion1(final String version1,
final String version2) {
if (version1 == null || version2 == null) {
return false;
}
try {
final int major1;
final int rank1;
final int subversion1;
String[] vals = version1.split("\\.");
major1 = Integer.parseInt(vals[0]);
rank1 = Integer.parseInt(vals[1]);
final int pos = vals[2].indexOf('-');
if (pos > 0) {
subversion1 = Integer.parseInt(vals[2].substring(0, pos));
} else {
subversion1 = Integer.parseInt(vals[2]);
}
final int major2;
final int rank2;
final int subversion2;
vals = version2.split("\\.");
major2 = Integer.parseInt(vals[0]);
rank2 = Integer.parseInt(vals[1]);
final int pos2 = vals[2].indexOf('-');
if (pos2 > 0) {
subversion2 = Integer.parseInt(vals[2].substring(0, pos2));
} else {
subversion2 = Integer.parseInt(vals[2]);
}
final boolean b = major1 < major2 || (major1 == major2 &&
(rank1 < rank2 || (rank1 == rank2 &&
subversion1 <=
subversion2)));
logger.trace("1: {}:{}:{} <=? {}:{}:{} = {}", major1, rank1, subversion1,
major2, rank2, subversion2, b);
return b;
} catch (final Exception e) {
logger.error("Error while comparing versions {} vs {}: {}", version1,
version2, e.getMessage());
return false;
}
}
/**
* Compare strictly 2 versions
*
* @param version1
* @param version2
*
* @return True if version2 > version1
*/
public static boolean isVersion2GTVersion1(final String version1,
final String version2) {
if (version1 == null || version2 == null) {
return false;
}
try {
final int major1;
final int rank1;
final int subversion1;
String[] vals = version1.split("\\.");
major1 = Integer.parseInt(vals[0]);
rank1 = Integer.parseInt(vals[1]);
final int pos = vals[2].indexOf('-');
if (pos > 0) {
subversion1 = Integer.parseInt(vals[2].substring(0, pos));
} else {
subversion1 = Integer.parseInt(vals[2]);
}
final int major2;
final int rank2;
final int subversion2;
vals = version2.split("\\.");
major2 = Integer.parseInt(vals[0]);
rank2 = Integer.parseInt(vals[1]);
final int pos2 = vals[2].indexOf('-');
if (pos2 > 0) {
subversion2 = Integer.parseInt(vals[2].substring(0, pos2));
} else {
subversion2 = Integer.parseInt(vals[2]);
}
final boolean b = major1 < major2 || (major1 == major2 &&
(rank1 < rank2 || (rank1 == rank2 &&
subversion1 <
subversion2)));
logger.debug("1: {}:{}:{} <? {}:{}:{} = {}", major1, rank1, subversion1,
major2, rank2, subversion2, b);
return b;
} catch (final Exception e) {
logger.error("Error while comparing versions {} vs {}: {}", version1,
version2, e.getMessage());
return false;
}
}
/**
* @param host
*
* @return True if this host is referenced as using Json
*/
public static boolean useJson(final String host) {
if (logger.isDebugEnabled()) {
logger.debug("UseJson host: '{}':{}", host,
Configuration.configuration.getVersions().containsKey(host)?
Configuration.configuration.getVersions().get(host)
.useJson() : "no:" +
((Map<String, PartnerConfiguration>) Configuration.configuration.getVersions()).keySet());
}
return Configuration.configuration.getVersions().containsKey(host) &&
Configuration.configuration.getVersions().get(host).useJson();
}
/**
* @return the sEPARATOR_FIELD
*/
public static String getSEPARATOR_FIELD() {
return SEPARATOR_FIELD;
}
/**
* @param separatorFIELD the sEPARATOR_FIELD to set
*/
public static void setSEPARATOR_FIELD(final String separatorFIELD) {
SEPARATOR_FIELD = separatorFIELD;
}
}