org.tinymediamanager.thirdparty.SplitUri Maven / Gradle / Ivy
The newest version!
package org.tinymediamanager.thirdparty;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.fourthline.cling.UpnpService;
import org.fourthline.cling.model.meta.Device;
import org.fourthline.cling.model.types.UDN;
import org.fourthline.cling.registry.Registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinymediamanager.thirdparty.upnp.Upnp;
/**
* Splits an URI (Kodi datasource, file, UNC, ...) in it's parameters
*
* Type:
* LOCAL for local datasources
* UPNP for UPNP ones
* SMB/NFS/... Url schema for other remotes
*
* @author Myron Boyle
*
*/
public class SplitUri {
private static final Logger LOGGER = LoggerFactory.getLogger(SplitUri.class);
public String file = "";
public String datasource = "";
public String label = "";
public String type = "";
public String ip = "";
public String hostname = "";
private Map lookup = new HashMap<>();
@SuppressWarnings("unused")
private SplitUri() {
}
public SplitUri(String ds, String file) {
this(ds, file, "", "");
}
public SplitUri(String ds, String file, String label, String ipForLocal) {
// remove trailing slashes
if (ds.matches(".*[\\\\/]$")) {
ds = ds.substring(0, ds.length() - 1);
}
// remove datasource from file
if (file.startsWith(ds)) {
file = file.substring(ds.length());
}
this.datasource = ds;
this.file = file;
int schema = file.indexOf("://");
if (schema == -1) {
schema = file.indexOf(":\\\\");
}
if (schema > 0) {
this.file = this.file.substring(schema + 3);
}
this.file = Paths.get(this.file).toString(); // unify slashes
this.label = label;
// try to parse datasource and unify
URI u = null;
try {
try {
ds = URLDecoder.decode(ds, "UTF-8");
ds = URLDecoder.decode(ds, "UTF-8");
ds = URLDecoder.decode(ds, "UTF-8");
}
catch (Exception e) {
LOGGER.warn("Could not decode uri '{}': {}", ds, e.getMessage());
}
ds = ds.replaceAll("\\\\", "/");
// for directories, we might get a trailing delimiter - remove
if (ds.endsWith("/")) {
ds = ds.substring(0, ds.length() - 1);
}
if (ds.contains(":///")) {
// 3 = file with scheme - parse as URI, but keep one slash
ds = ds.replaceAll(" ", "%20"); // space in urls
ds = ds.replaceAll("#", "%23"); // hash sign in urls
u = new URI(ds.substring(ds.indexOf(":///") + 3));
}
else if (ds.contains("://")) {
// 2 = //hostname/path - parse as URI
ds = ds.replaceAll(" ", "%20"); // space in urls
ds = ds.replaceAll("#", "%23"); // hash sign in urls
u = new URI(ds);
}
else {
// 0 = local file - parse as Path
u = Paths.get(ds).toUri();
}
}
catch (URISyntaxException e) {
try {
ds = ds.replaceAll(".*?:/{2,3}", ""); // replace scheme
u = Paths.get(ds).toAbsolutePath().toUri();
}
catch (InvalidPathException e2) {
LOGGER.warn("Invalid path: {} - {}", ds, e2.getMessage());
}
}
catch (InvalidPathException e) {
LOGGER.warn("Invalid path: {} - {}", ds, e.getMessage());
}
if (u != null && !StringUtils.isBlank(u.getHost())) {
if (ds.startsWith("upnp")) {
this.type = "UPNP";
this.hostname = getMacFromUpnpUUID(u.getHost());
UpnpService us = Upnp.getInstance().getUpnpService();
if (us != null) {
Registry registry = us.getRegistry();
if (registry != null) {
@SuppressWarnings("rawtypes")
Device foundDevice = registry.getDevice(UDN.valueOf(u.getHost()), true);
if (foundDevice != null) {
this.ip = foundDevice.getDetails().getPresentationURI().getHost();
}
}
}
}
else {
this.type = u.getScheme().toUpperCase(Locale.ROOT);
this.hostname = u.getHost();
try {
String ip = lookup.get(u.getHost());
// cache
if (ip == null) {
InetAddress i = InetAddress.getByName(u.getHost());
ip = i.getHostAddress();
lookup.put(u.getHost(), ip);
}
this.ip = ip;
}
catch (Exception e) {
LOGGER.warn("Could not lookup IP for {}: {}", u.getHost(), e.getMessage());
}
}
this.datasource = u.getPath(); // datasource is just path without server
}
else {
this.type = "LOCAL";
if (ipForLocal.isEmpty()) {
this.ip = "127.0.0.1";
this.hostname = "localhost";
}
else {
try {
String tmp = lookup.get(ipForLocal);
if (tmp == null) {
InetAddress i = InetAddress.getByName(ipForLocal);
this.ip = i.getHostAddress();
this.hostname = i.getHostName();
lookup.put(ipForLocal, ip);
lookup.put(hostname, ip);
}
}
catch (Exception e) {
LOGGER.warn("Could not lookup hostname for {}: {}", ipForLocal, e.getMessage());
}
}
}
try {
this.datasource = Paths.get(this.datasource).toString(); // convert forward & backslashes to same format
}
catch (Exception e) {
LOGGER.warn("Invalid path: {} - {}", ds, e.getMessage());
}
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((file == null) ? 0 : file.hashCode());
result = prime * result + ((hostname == null) ? 0 : hostname.hashCode());
result = prime * result + ((ip == null) ? 0 : ip.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SplitUri other = (SplitUri) obj;
if (datasource == null || datasource.isEmpty() || other.datasource == null || other.datasource.isEmpty()) {
return false;
}
// 1: same? - step directly out
if (file.equals(other.file) && datasource.equals(other.datasource)) {
return true;
}
// 2: - check either matching IP or hostname
if (file.equals(other.file) && ip != null && !ip.isEmpty() && ip.equals(other.ip)) {
return true;
}
if (file.equals(other.file) && hostname != null && !hostname.isEmpty() && hostname.equalsIgnoreCase(other.hostname)) {
return true;
}
// 3: did not match? return false
return false;
}
/**
* gets the MAC from an upnp UUID string (= last 6 bytes reversed)
* like upnp://00113201-aac2-0011-c2aa-02aa01321100 -> 00113201AA02
*
* @param uuid
* @return
*/
private static String getMacFromUpnpUUID(String uuid) {
String s = uuid.substring(uuid.lastIndexOf('-') + 1);
StringBuilder result = new StringBuilder();
for (int i = s.length() - 2; i >= 0; i = i - 2) {
result.append(new StringBuilder(s.substring(i, i + 2)));
result.append(i > 1 ? ":" : ""); // skip last
}
return result.toString().toUpperCase(Locale.ROOT);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy