/** * 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.huawei.streaming.datasource; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.List; import java.util.Locale; import com.huawei.streaming.encrypt.NoneEncrypt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Lists; import com.huawei.streaming.config.StreamingConfig; import com.huawei.streaming.encrypt.StreamingDecrypt; import com.huawei.streaming.event.TupleEventType; import com.huawei.streaming.exception.ErrorCode; import com.huawei.streaming.exception.StreamingException; import com.huawei.streaming.exception.StreamingRuntimeException; import com.huawei.streaming.util.StreamingDataType; import com.huawei.streaming.util.StreamingUtils; import com.huawei.streaming.util.datatype.DataTypeParser; /** * RDB数据源 * */ public abstract class RDBDataSource implements IDataSource { private static final long serialVersionUID = 8056232432674642637L; private static final Logger LOG = LoggerFactory.getLogger(RDBDataSource.class); private String url; private String driver; private String username; private String password; private TupleEventType schema; private String decryptClass; private transient Connection connection; private DecryptType decryptType; private DataTypeParser[] parsers; private StreamingConfig config; /** * {@inheritDoc} */ @Override public void setConfig(StreamingConfig conf) throws StreamingException { driver = conf.getStringValue(StreamingConfig.DATASOURCE_RDB_DRIVER); url = conf.getStringValue(StreamingConfig.DATASOURCE_RDB_URL); username = conf.getStringValue(StreamingConfig.DATASOURCE_RDB_USERNAME); password = conf.getStringValue(StreamingConfig.DATASOURCE_RDB_PASSWORD); decryptClass = conf.getStringValue(StreamingConfig.DATASOURCE_RDB_DECRYPTCLASS); setDecryptType(conf); this.config = conf; } /** * {@inheritDoc} */ @Override public void setSchema(TupleEventType eventType) { this.schema = eventType; } /** * {@inheritDoc} */ @Override public void initialize() throws StreamingException { parsers = new DataTypeParser[schema.getSize()]; Class< ? >[] attributes = schema.getAllAttributeTypes(); for (int i = 0; i < schema.getSize(); i++) { parsers[i] = StreamingDataType.getDataTypeParser(attributes[i], config); } loadDriveClass(); try { connection = createConnection(); } catch (SQLException e) { LOG.error("Failed to create sql connection!", e); throw new StreamingRuntimeException("Failed to create sql connection!", e); } LOG.info("Create database connection successs."); } /** * {@inheritDoc} */ @Override public void destroy() throws StreamingException { LOG.info("Start to close database connection."); StreamingUtils.close(connection); LOG.info("Close database connection success."); } private void loadDriveClass() { LOG.info("Start to initialize rdb datasource"); try { Class.forName(driver); } catch (ClassNotFoundException e) { LOG.error("can't load JDBC class {}", driver); throw new StreamingRuntimeException("can't load JDBC class " + driver); } LOG.info("Finished to load driver class. and start to create connection to database."); } protected List<Object[]> parseQueryResults(ResultSet result) throws SQLException, StreamingException { List<Object[]> results = Lists.newArrayList(); ResultSetMetaData metaData = result.getMetaData(); if (null != metaData) { int columnCount = metaData.getColumnCount(); while (result.next()) { Object[] values = parseRowValues(result, columnCount); results.add(values); } } return results; } private Object[] parseRowValues(ResultSet result, int columnCount) throws StreamingException, SQLException { Object[] values = new Object[columnCount]; for (int i = 0; i < columnCount; i++) { values[i] = parsers[i].createValue(result.getString(i + 1)); } return values; } private Connection createConnection() throws SQLException, StreamingException { String newUserName = username; String newPassWord = password; StreamingDecrypt decrypt = createDecryptInstance(); switch (decryptType) { case USER: newUserName = decrypt.decrypt(newUserName); break; case PASSWORD: newPassWord = decrypt.decrypt(newPassWord); break; case ALL: newUserName = decrypt.decrypt(newUserName); newPassWord = decrypt.decrypt(newPassWord); break; default: break; } return DriverManager.getConnection(url, newUserName, newPassWord); } private StreamingDecrypt createDecryptInstance() throws StreamingException { if(decryptType == DecryptType.NONE) { return new NoneEncrypt(); } try { return (StreamingDecrypt)Class.forName(decryptClass).newInstance(); } catch (ReflectiveOperationException e) { LOG.error("can not found decrypt class " + decryptClass, e); throw new StreamingException("can not found decrypt class " + decryptClass, e); } } /** * 获取数据库连接 */ protected Connection getConnection() { return connection; } private void setDecryptType(StreamingConfig conf) throws StreamingException { String strDecryptType = conf.getStringValue(StreamingConfig.DATASOURCE_RDB_DECRYPTTYPE); try { decryptType = DecryptType.valueOf(strDecryptType.toUpperCase(Locale.US)); } catch (IllegalArgumentException e) { StreamingException exception= new StreamingException(ErrorCode.CONFIG_FORMAT, strDecryptType, "enum"); LOG.error(ErrorCode.CONFIG_FORMAT.getFullMessage(strDecryptType, "enum")); throw exception; } } private enum DecryptType { /** * 用户名加密 */ USER, /** * 密码加密 */ PASSWORD, /** * 不加密 */ NONE, /** * 全部都加密 */ ALL; } }