package org.skywalking.apm.plugin.jdbc.connectionurl.parser;
import org.skywalking.apm.plugin.jdbc.ConnectionInfo;
/**
* {@link H2URLParser} presents that skywalking how to parse the connection url of H2 database.
* {@link ConnectionInfo#host} will return localhost and {@link ConnectionInfo#port} will return
* -1 if H2 running with memory mode or file mode, or it will return the host and the port.
* <p>
* {@link H2URLParser} check the connection url if contains "file" or "mem". if yes. the database
* name substring the connection url from the index after "file" index or the "mem" index to the
* index of first charset ";".
* <p>
* The {@link ConnectionInfo#host} be set the string between charset "//" and the first charset "/" after
* the charset "//", and {@link ConnectionInfo#databaseName} be set the string between the last index of "/" and
* the first charset ";".
*
* @author zhangxin
*/
public class H2URLParser extends AbstractURLParser {
private static final String LOCALHOST = "localhost";
private static final int DEFAULT_PORT = 8084;
/**
* Flag that H2 running with file mode.
*/
private static final String FILE_MODE_FLAG = "file";
/**
* Flag that H2 running with memory mode.
*/
private static final String MEMORY_MODE_FLAG = "mem";
private static final String H2_DB_TYPE = "H2";
public H2URLParser(String url) {
super(url);
}
@Override
protected int[] fetchDatabaseHostsIndexRange() {
int hostLabelStartIndex = url.indexOf("//");
int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2);
return new int[] {hostLabelStartIndex + 2, hostLabelEndIndex};
}
@Override
protected int[] fetchDatabaseNameIndexRange() {
int databaseStartTag = url.lastIndexOf("/");
int databaseEndTag = url.indexOf(";");
if (databaseEndTag == -1) {
databaseEndTag = url.length();
}
return new int[] {databaseStartTag + 1, databaseEndTag};
}
@Override
public ConnectionInfo parse() {
int[] databaseNameRangeIndex = fetchDatabaseNameRangeIndexFromURLForH2FileMode();
if (databaseNameRangeIndex != null) {
return new ConnectionInfo(H2_DB_TYPE, LOCALHOST, -1, fetchDatabaseNameFromURL(databaseNameRangeIndex));
}
databaseNameRangeIndex = fetchDatabaseNameRangeIndexFromURLForH2MemMode();
if (databaseNameRangeIndex != null) {
return new ConnectionInfo(H2_DB_TYPE, LOCALHOST, -1, fetchDatabaseNameFromURL(databaseNameRangeIndex));
}
String[] hostAndPort = fetchDatabaseHostsFromURL().split(":");
if (hostAndPort.length == 1) {
return new ConnectionInfo(H2_DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL());
} else {
return new ConnectionInfo(H2_DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL());
}
}
/**
* Fetch range index that the database name from connection url if H2 database running with file mode.
*
* @return range index that the database name.
*/
private int[] fetchDatabaseNameRangeIndexFromURLForH2FileMode() {
int fileLabelIndex = url.indexOf(FILE_MODE_FLAG);
int parameterLabelIndex = url.indexOf(";", fileLabelIndex);
if (parameterLabelIndex == -1) {
parameterLabelIndex = url.length();
}
if (fileLabelIndex != -1) {
return new int[] {fileLabelIndex + FILE_MODE_FLAG.length() + 1, parameterLabelIndex};
} else {
return null;
}
}
/**
* Fetch range index that the database name from connection url if H2 database running with memory mode.
*
* @return range index that the database name.
*/
private int[] fetchDatabaseNameRangeIndexFromURLForH2MemMode() {
int fileLabelIndex = url.indexOf(MEMORY_MODE_FLAG);
int parameterLabelIndex = url.indexOf(";", fileLabelIndex);
if (parameterLabelIndex == -1) {
parameterLabelIndex = url.length();
}
if (fileLabelIndex != -1) {
return new int[] {fileLabelIndex + MEMORY_MODE_FLAG.length() + 1, parameterLabelIndex};
} else {
return null;
}
}
}