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; } } }