/** * DataCleaner (community edition) * Copyright (C) 2014 Neopost - Customer Information Management * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.datacleaner.database; import java.io.File; import java.io.Serializable; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Arrays; import org.apache.commons.vfs2.FileObject; import org.apache.metamodel.util.CollectionUtils; import org.datacleaner.extensions.ClassLoaderUtils; import org.datacleaner.util.ReflectionUtils; import org.datacleaner.util.VFSUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Represents a database driver that the user has installed. Such database * drivers are based on (JAR) files on the filesystem and are loaded dynamically * (as opposed to statically loaded drivers, which are loaded at startup time). */ public final class UserDatabaseDriver implements Serializable { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(UserDatabaseDriver.class); private final File[] _files; private final String _driverClassName; private transient Driver _driverInstance; private transient Driver _registeredDriver; private transient boolean _loaded = false; public UserDatabaseDriver(final FileObject[] files, final String driverClassName) { this(convert(files), driverClassName); } public UserDatabaseDriver(final File[] files, final String driverClassName) { if (files == null) { throw new IllegalStateException("Driver file(s) cannot be null"); } if (driverClassName == null) { throw new IllegalStateException("Driver class name cannot be null"); } _files = files; _driverClassName = driverClassName; } private static File[] convert(final FileObject[] files) { return CollectionUtils.map(files, VFSUtils::toFile).toArray(new File[0]); } public String getDriverClassName() { return _driverClassName; } public File[] getFiles() { return Arrays.copyOf(_files, _files.length); } public UserDatabaseDriver loadDriver() throws IllegalStateException { if (!_loaded) { final ClassLoader driverClassLoader = ClassLoaderUtils.createClassLoader(_files); final Class<?> loadedClass; try { loadedClass = Class.forName(_driverClassName, true, driverClassLoader); } catch (final Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IllegalStateException("Could not load driver class", e); } logger.info("Loaded class: {}", loadedClass.getName()); if (ReflectionUtils.is(loadedClass, Driver.class)) { _driverInstance = (Driver) ReflectionUtils.newInstance(loadedClass); _registeredDriver = new DriverWrapper(_driverInstance); try { DriverManager.registerDriver(_registeredDriver); } catch (final SQLException e) { throw new IllegalStateException("Could not register driver", e); } } else { throw new IllegalStateException("Class is not a Driver class: " + _driverClassName); } _loaded = true; } return this; } public void unloadDriver() { try { DriverManager.deregisterDriver(_registeredDriver); _registeredDriver = null; _driverInstance = null; _loaded = false; } catch (final SQLException e) { logger.error("Exception occurred while unloading driver: " + _driverClassName, e); } } public boolean isLoaded() { return _loaded; } public DatabaseDriverState getState() { if (_loaded) { return DatabaseDriverState.INSTALLED_WORKING; } return DatabaseDriverState.INSTALLED_NOT_WORKING; } }