Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.alibaba.wasp.jdbc; import com.alibaba.wasp.FConstants; import com.alibaba.wasp.SQLErrorCode; import com.alibaba.wasp.conf.WaspConfiguration; import com.alibaba.wasp.util.New; import com.alibaba.wasp.util.StringUtils; import com.alibaba.wasp.util.Utils; import org.apache.hadoop.conf.Configuration; import java.util.ArrayList; import java.util.HashSet; import java.util.Properties; /** * Encapsulates the connection settings, including user name and password. */ public class ConnectionInfo implements Cloneable { private static final HashSet<String> KNOWN_SETTINGS = New.hashSet(); private Properties properties = new Properties(); private String originalURL; private String url; private String user; private byte[] userPasswordHash; /** * The database name */ private String name; private boolean remote; private boolean ssl; private boolean persistent; private boolean unnamed; private Configuration conf = WaspConfiguration.create(); /** * Create a connection info object. * * @param name * the database name (including tags), but without the "jdbc:wasp:" * prefix */ public ConnectionInfo(String name) { this.name = name; this.url = FConstants.START_URL + name; parseName(); } /** * Create a connection info object. * * @param url * the database URL (must start with jdbc:h2:) * @param info * the connection properties */ public ConnectionInfo(String url, Properties info) { this.originalURL = url; if (!url.startsWith(FConstants.START_URL)) { throw JdbcException.getInvalidValueException("url", url); } this.url = url; readProperties(info); readSettingsFromURL(); setUserName(removeProperty("USER", "")); name = this.url.substring(FConstants.START_URL.length()); parseName(); } static { ArrayList<String> list = SetTypes.getTypes(); HashSet<String> set = KNOWN_SETTINGS; set.addAll(list); String[] connectionTime = { "ACCESS_MODE_DATA", "AUTOCOMMIT", "CIPHER", "CREATE", "CACHE_TYPE", "FILE_LOCK", "IGNORE_UNKNOWN_SETTINGS", "IFEXISTS", "INIT", "PASSWORD", "RECOVER", "RECOVER_TEST", "USER", "AUTO_SERVER", "AUTO_SERVER_PORT", "NO_UPGRADE", "AUTO_RECONNECT", "OPEN_NEW", "PAGE_SIZE", "PASSWORD_HASH", "JMX" }; for (String key : connectionTime) { if (set.contains(key)) { JdbcException.throwInternalError(key); } set.add(key); } } private static boolean isKnownSetting(String s) { return KNOWN_SETTINGS.contains(s); } public Object clone() throws CloneNotSupportedException { ConnectionInfo clone = (ConnectionInfo) super.clone(); clone.properties = (Properties) properties.clone(); clone.userPasswordHash = Utils.cloneByteArray(userPasswordHash); return clone; } private void parseName() { if (".".equals(name)) { name = "mem:"; } if (name.startsWith("tcp:")) { remote = true; name = name.substring("tcp:".length()); } else if (name.startsWith("ssl:")) { remote = true; ssl = true; name = name.substring("ssl:".length()); } else if (name.startsWith("mem:")) { persistent = false; if ("mem:".equals(name)) { unnamed = true; } } else if (name.startsWith("file:")) { name = name.substring("file:".length()); persistent = true; } else { persistent = true; } if (persistent && !remote) { name = name.replace('/', '\\'); } } /** * Check if this is a remote connection. * * @return true if it is */ public boolean isRemote() { return remote; } /** * Check if the referenced database is persistent. * * @return true if it is */ public boolean isPersistent() { return persistent; } /** * Check if the referenced database is an unnamed in-memory database. * * @return true if it is */ boolean isUnnamedInMemory() { return unnamed; } private void readProperties(Properties info) { Object[] list = new Object[info.size()]; info.keySet().toArray(list); Configuration conf = null; for (Object k : list) { String key = StringUtils.toUpperEnglish(k.toString()); if (properties.containsKey(key)) { throw JdbcException.get(SQLErrorCode.DUPLICATE_PROPERTY_1, key); } Object value = info.get(k); if (isKnownSetting(key)) { properties.put(key, value); } else { if (conf == null) { conf = getConf(); } if (conf.get(key) != null) { properties.put(key, value); } } } } private void readSettingsFromURL() { Configuration conf = getConf(); int idx = url.indexOf(';'); if (idx >= 0) { String settings = url.substring(idx + 1); url = url.substring(0, idx); String[] list = StringUtils.arraySplit(settings, ';', false); for (String setting : list) { if (setting.length() == 0) { continue; } int equal = setting.indexOf('='); if (equal < 0) { throw getFormatException(); } String value = setting.substring(equal + 1); String key = setting.substring(0, equal); key = StringUtils.toUpperEnglish(key); if (!isKnownSetting(key) && conf.get(key) == null) { throw JdbcException.get(SQLErrorCode.UNSUPPORTED_SETTING_1, key); } String old = properties.getProperty(key); if (old != null && !old.equals(value)) { throw JdbcException.get(SQLErrorCode.DUPLICATE_PROPERTY_1, key); } properties.setProperty(key, value); } } } /** * Get a boolean property if it is set and return the value. * * @param key * the property name * @param defaultValue * the default value * @return the value */ boolean getProperty(String key, boolean defaultValue) { String x = getProperty(key, null); if (x == null) { return defaultValue; } // support 0 / 1 (like the parser) if (x.length() == 1 && Character.isDigit(x.charAt(0))) { return Integer.parseInt(x) != 0; } return Boolean.parseBoolean(x); } /** * Remove a boolean property if it is set and return the value. * * @param key * the property name * @param defaultValue * the default value * @return the value */ public boolean removeProperty(String key, boolean defaultValue) { String x = removeProperty(key, null); return x == null ? defaultValue : Boolean.parseBoolean(x); } /** * Remove a String property if it is set and return the value. * * @param key * the property name * @param defaultValue * the default value * @return the value */ private String removeProperty(String key, String defaultValue) { if (!isKnownSetting(key)) { JdbcException.throwInternalError(key); } Object x = properties.remove(key); return x == null ? defaultValue : x.toString(); } /** * Get the name of the user. * * @return the user name */ public String getUserName() { return user; } /** * Get the user password hash. * * @return the password hash */ byte[] getUserPasswordHash() { return userPasswordHash; } /** * Get the property keys. * * @return the property keys */ String[] getKeys() { String[] keys = new String[properties.size()]; properties.keySet().toArray(keys); return keys; } /** * Get the value of the given property. * * @param key * the property key * @return the value as a String */ String getProperty(String key) { Object value = properties.get(key); if (value == null || !(value instanceof String)) { return null; } return value.toString(); } /** * Get the value of the given property. * * @param key * the property key * @param defaultValue * the default value * @return the value as a String */ int getProperty(String key, int defaultValue) { if (!isKnownSetting(key)) { JdbcException.throwInternalError(key); } String s = getProperty(key); return s == null ? defaultValue : Integer.parseInt(s); } /** * Get the value of the given property. * * @param key * the property key * @param defaultValue * the default value * @return the value as a String */ public String getProperty(String key, String defaultValue) { if (!isKnownSetting(key)) { JdbcException.throwInternalError(key); } String s = getProperty(key); return s == null ? defaultValue : s; } /** * Get the value of the given property. * * @param setting * the setting id * @param defaultValue * the default value * @return the value as a String */ String getProperty(int setting, String defaultValue) { String key = SetTypes.getTypeName(setting); String s = getProperty(key); return s == null ? defaultValue : s; } /** * Get the value of the given property. * * @param setting * the setting id * @param defaultValue * the default value * @return the value as an integer */ int getIntProperty(int setting, int defaultValue) { String key = SetTypes.getTypeName(setting); String s = getProperty(key, null); try { return s == null ? defaultValue : Integer.decode(s); } catch (NumberFormatException e) { return defaultValue; } } /** * Check if this is a remote connection with SSL enabled. * * @return true if it is */ boolean isSSL() { return ssl; } /** * Overwrite the user name. The user name is case-insensitive and stored in * uppercase. English conversion is used. * * @param name * the user name */ public void setUserName(String name) { this.user = StringUtils.toUpperEnglish(name); } /** * Set the user password hash. * * @param hash * the new hash value */ public void setUserPasswordHash(byte[] hash) { this.userPasswordHash = hash; } /** * Overwrite a property. * * @param key * the property name * @param value * the value */ public void setProperty(String key, String value) { // value is null if the value is an object if (value != null) { properties.setProperty(key, value); } } /** * Get the database URL. * * @return the URL */ public String getURL() { return url; } /** * Get the complete original database URL. * * @return the database URL */ public String getOriginalURL() { return originalURL; } /** * Set the original database URL. * * @param url * the database url */ public void setOriginalURL(String url) { originalURL = url; } /** * Generate an URL format exception. * * @return the exception */ JdbcException getFormatException() { String format = FConstants.URL_FORMAT; return JdbcException.get(SQLErrorCode.URL_FORMAT_ERROR_2, format, url); } /** * Switch to server mode, and set the server name and database key. * * @param serverKey * the server name, '/', and the security key */ public void setServerKey(String serverKey) { remote = true; persistent = false; this.name = serverKey; } public Configuration getConf() { return conf; } public String getName() { return name; } }