001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    package org.apache.logging.log4j.core.appender.db.jdbc;
018    
019    import java.sql.Connection;
020    import java.sql.Driver;
021    import java.sql.DriverManager;
022    import java.sql.SQLException;
023    
024    import org.apache.logging.log4j.Logger;
025    import org.apache.logging.log4j.core.config.plugins.Plugin;
026    import org.apache.logging.log4j.core.config.plugins.PluginAttr;
027    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
028    import org.apache.logging.log4j.core.helpers.NameUtil;
029    import org.apache.logging.log4j.status.StatusLogger;
030    
031    /**
032     * A {@link JDBCAppender} connection source that uses a standard JDBC URL, username, and password to connect to the
033     * database.
034     */
035    @Plugin(name = "DriverManager", category = "Core", elementType = "connectionSource", printObject = true)
036    public final class DriverManagerConnectionSource implements ConnectionSource {
037        private static final Logger LOGGER = StatusLogger.getLogger();
038    
039        private final String databasePassword;
040        private final String databaseUrl;
041        private final String databaseUsername;
042        private final String description;
043    
044        private DriverManagerConnectionSource(final String databaseUrl, final String databaseUsername,
045                                              final String databasePassword) {
046            this.databaseUrl = databaseUrl;
047            this.databaseUsername = databaseUsername;
048            this.databasePassword = databasePassword;
049            this.description = "driverManager{ url=" + this.databaseUrl + ", username=" + this.databaseUsername
050                    + ", passwordHash=" + NameUtil.md5(this.databasePassword + this.getClass().getName()) + " }";
051        }
052    
053        @Override
054        public Connection getConnection() throws SQLException {
055            if (this.databaseUsername == null) {
056                return DriverManager.getConnection(this.databaseUrl);
057            }
058            return DriverManager.getConnection(this.databaseUrl, this.databaseUsername, this.databasePassword);
059        }
060    
061        @Override
062        public String toString() {
063            return this.description;
064        }
065    
066        /**
067         * Factory method for creating a connection source within the plugin manager.
068         *
069         * @param url The JDBC URL to use to connect to the logging database. A driver that can accept this URL must be on
070         *            the classpath.
071         * @param username The username with which to log in to the database, if applicable.
072         * @param password The password with which to log in to the database, if applicable.
073         * @return the created connection source.
074         */
075        @PluginFactory
076        public static DriverManagerConnectionSource createConnectionSource(@PluginAttr("url") final String url,
077                                                                           @PluginAttr("username") String username,
078                                                                           @PluginAttr("password") String password) {
079            if (url == null || url.length() == 0) {
080                LOGGER.error("No JDBC URL specified for the database.", url);
081                return null;
082            }
083    
084            Driver driver;
085            try {
086                driver = DriverManager.getDriver(url);
087            } catch (final SQLException e) {
088                LOGGER.error("No matching driver found for database URL [" + url + "].", e);
089                return null;
090            }
091    
092            if (driver == null) {
093                LOGGER.error("No matching driver found for database URL [" + url + "].");
094                return null;
095            }
096    
097            if (username == null || username.trim().length() == 0) {
098                username = null;
099                password = null;
100            }
101    
102            return new DriverManagerConnectionSource(url, username, password);
103        }
104    }