/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.plugin.jdbc.postgresql;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.DefaultDatabaseInfo;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.JdbcUrlParserV2;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.StringMaker;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.UnKnownDatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Brad Hong
*/
public class PostgreSqlJdbcUrlParser implements JdbcUrlParserV2 {
private static final String URL_PREFIX = "jdbc:postgresql:";
// jdbc:postgresql:loadbalance://10.22.33.44:3306,10.22.33.55:3306/PostgreSQL?characterEncoding=UTF-8
private static final String LOADBALANCE_URL_PREFIX = URL_PREFIX + "loadbalance:";
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
@Override
public DatabaseInfo parse(String jdbcUrl) {
if (jdbcUrl == null) {
logger.info("jdbcUrl may not be null");
return UnKnownDatabaseInfo.INSTANCE;
}
if (!jdbcUrl.startsWith(URL_PREFIX)) {
logger.info("jdbcUrl has invalid prefix.(url:{}, prefix:{})", jdbcUrl, URL_PREFIX);
return UnKnownDatabaseInfo.INSTANCE;
}
DatabaseInfo result = null;
try {
result = parse0(jdbcUrl);
} catch (Exception e) {
logger.info("PostgreJdbcUrl parse error. url: {}, Caused: {}", jdbcUrl, e.getMessage(), e);
result = UnKnownDatabaseInfo.createUnknownDataBase(PostgreSqlConstants.POSTGRESQL, PostgreSqlConstants.POSTGRESQL_EXECUTE_QUERY, jdbcUrl);
}
return result;
}
private DatabaseInfo parse0(String url) {
if (isLoadbalanceUrl(url)) {
return parseLoadbalancedUrl(url);
}
return parseNormal(url);
}
private DatabaseInfo parseLoadbalancedUrl(String url) {
// jdbc:postgresql://1.2.3.4:5678/test_db
StringMaker maker = new StringMaker(url);
maker.after(URL_PREFIX);
// 1.2.3.4:5678 In case of replication driver could have multiple values
// We have to consider mm db too.
String host = maker.after("//").before('/').value();
// Decided not to cache regex. This is not invoked often so don't waste memory.
String[] parsedHost = host.split(",");
List<String> hostList = Arrays.asList(parsedHost);
String databaseId = maker.next().afterLast('/').before('?').value();
String normalizedUrl = maker.clear().before('?').value();
return new DefaultDatabaseInfo(PostgreSqlConstants.POSTGRESQL, PostgreSqlConstants.POSTGRESQL_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId);
}
private boolean isLoadbalanceUrl(String url) {
return url.regionMatches(true, 0, LOADBALANCE_URL_PREFIX, 0, LOADBALANCE_URL_PREFIX.length());
}
private DatabaseInfo parseNormal(String url) {
// jdbc:postgresql://1.2.3.4:5678/test_db
StringMaker maker = new StringMaker(url);
maker.after(URL_PREFIX);
// 1.2.3.4:5678 In case of replication driver could have multiple values
// We have to consider mm db too.
String host = maker.after("//").before('/').value();
List<String> hostList = new ArrayList<String>(1);
hostList.add(host);
// String port = maker.next().after(':').before('/').value();
String databaseId = maker.next().afterLast('/').before('?').value();
String normalizedUrl = maker.clear().before('?').value();
return new DefaultDatabaseInfo(PostgreSqlConstants.POSTGRESQL, PostgreSqlConstants.POSTGRESQL_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId);
}
@Override
public ServiceType getServiceType() {
return PostgreSqlConstants.POSTGRESQL;
}
}