001/* 002 * (C) Copyright 2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * dmetzler 018 */ 019package org.nuxeo.launcher.config.backingservices; 020 021import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_DRIVER; 022import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_HOST; 023import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_JDBC_URL; 024import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_NAME; 025import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_PORT; 026import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_PWD; 027import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_DB_USER; 028import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_TEMPLATE_DBNAME; 029 030import java.io.File; 031import java.io.FileNotFoundException; 032import java.io.IOException; 033import java.net.MalformedURLException; 034import java.net.URL; 035import java.net.URLClassLoader; 036import java.sql.Connection; 037import java.sql.Driver; 038import java.sql.DriverManager; 039import java.sql.SQLException; 040import java.util.ArrayList; 041import java.util.Arrays; 042import java.util.List; 043import java.util.Properties; 044 045import org.apache.commons.lang3.ArrayUtils; 046import org.apache.commons.logging.Log; 047import org.apache.commons.logging.LogFactory; 048import org.nuxeo.common.codec.CryptoProperties; 049import org.nuxeo.common.utils.TextTemplate; 050import org.nuxeo.launcher.commons.DatabaseDriverException; 051import org.nuxeo.launcher.config.ConfigurationException; 052import org.nuxeo.launcher.config.ConfigurationGenerator; 053 054/** 055 * @since 9.2 056 */ 057public class DBCheck implements BackingChecker { 058 059 private static final Log log = LogFactory.getLog(DBCheck.class); 060 061 public static final List<String> DB_EXCLUDE_CHECK_LIST = Arrays.asList("default", "none"); 062 063 @Override 064 public boolean accepts(ConfigurationGenerator cg) { 065 return !DB_EXCLUDE_CHECK_LIST.contains( 066 cg.getUserConfig().getProperty(ConfigurationGenerator.PARAM_TEMPLATE_DBTYPE)); 067 068 } 069 070 @Override 071 public void check(ConfigurationGenerator cg) throws ConfigurationException { 072 try { 073 checkDatabaseConnection(cg); 074 } catch (IOException e) { 075 throw new ConfigurationException(e); 076 } catch (DatabaseDriverException e) { 077 log.debug(e, e); 078 log.error(e.getMessage()); 079 throw new ConfigurationException("Could not find database driver: " + e.getMessage()); 080 } catch (SQLException e) { 081 log.debug(e, e); 082 log.error(e.getMessage()); 083 throw new ConfigurationException("Failed to connect on database: " + e.getMessage()); 084 } 085 } 086 087 /** 088 * Check driver availability and database connection 089 * 090 * @throws DatabaseDriverException 091 * @throws IOException 092 * @throws FileNotFoundException 093 * @throws SQLException 094 */ 095 public void checkDatabaseConnection(ConfigurationGenerator cg) 096 throws FileNotFoundException, IOException, DatabaseDriverException, SQLException { 097 CryptoProperties config = cg.getUserConfig(); 098 String databaseTemplate = config.getProperty(ConfigurationGenerator.PARAM_TEMPLATE_DBNAME); 099 String dbName = config.getProperty(ConfigurationGenerator.PARAM_DB_NAME); 100 String dbUser = config.getProperty(ConfigurationGenerator.PARAM_DB_USER); 101 String dbPassword = config.getProperty(ConfigurationGenerator.PARAM_DB_PWD); 102 String dbHost = config.getProperty(ConfigurationGenerator.PARAM_DB_HOST); 103 String dbPort = config.getProperty(ConfigurationGenerator.PARAM_DB_PORT); 104 105 File databaseTemplateDir = new File(cg.getNuxeoHome(), ConfigurationGenerator.TEMPLATES + File.separator + databaseTemplate); 106 Properties templateProperties = ConfigurationGenerator.loadTrimmedProperties(new File(databaseTemplateDir, ConfigurationGenerator.NUXEO_DEFAULT_CONF)); 107 String classname, connectionUrl; 108 // check if value is set in nuxeo.conf 109 if (config.containsKey(PARAM_DB_DRIVER)) { 110 classname = (String) config.get(PARAM_DB_DRIVER); 111 } else { 112 classname = templateProperties.getProperty(PARAM_DB_DRIVER); 113 } 114 if (config.containsKey(PARAM_DB_JDBC_URL)) { 115 connectionUrl = (String) config.get(PARAM_DB_JDBC_URL); 116 } else { 117 connectionUrl = templateProperties.getProperty(PARAM_DB_JDBC_URL); 118 } 119 // Load driver class from template or default lib directory 120 Driver driver = lookupDriver(cg, databaseTemplate, databaseTemplateDir, classname); 121 // Test db connection 122 DriverManager.registerDriver(driver); 123 Properties ttProps = new Properties(config); 124 ttProps.put(PARAM_DB_HOST, dbHost); 125 ttProps.put(PARAM_DB_PORT, dbPort); 126 ttProps.put(PARAM_DB_NAME, dbName); 127 ttProps.put(PARAM_DB_USER, dbUser); 128 ttProps.put(PARAM_DB_PWD, dbPassword); 129 TextTemplate tt = new TextTemplate(ttProps); 130 String url = tt.processText(connectionUrl); 131 Properties conProps = new Properties(); 132 conProps.put("user", dbUser); 133 conProps.put("password", dbPassword); 134 log.debug("Testing URL " + url + " with " + conProps); 135 Connection con = driver.connect(url, conProps); 136 con.close(); 137 } 138 139 140 /** 141 * Build an {@link URLClassLoader} for the given databaseTemplate looking in the templates directory and in the 142 * server lib directory, then looks for a driver 143 * @param cg 144 * 145 * @param classname Driver class name, defined by {@link #PARAM_DB_DRIVER} 146 * @return Driver driver if found, else an Exception must have been raised. 147 * @throws IOException 148 * @throws FileNotFoundException 149 * @throws DatabaseDriverException If there was an error when trying to instantiate the driver. 150 * @since 5.6 151 */ 152 private Driver lookupDriver(ConfigurationGenerator cg, String databaseTemplate, File databaseTemplateDir, String classname) 153 throws FileNotFoundException, IOException, DatabaseDriverException { 154 File[] files = (File[]) ArrayUtils.addAll( // 155 new File(databaseTemplateDir, "lib").listFiles(), // 156 cg.getServerConfigurator().getServerLibDir().listFiles()); 157 List<URL> urlsList = new ArrayList<>(); 158 if (files != null) { 159 for (File file : files) { 160 if (file.getName().endsWith("jar")) { 161 try { 162 urlsList.add(new URL("jar:file:" + file.getPath() + "!/")); 163 log.debug("Added " + file.getPath()); 164 } catch (MalformedURLException e) { 165 log.error(e); 166 } 167 } 168 } 169 } 170 URLClassLoader ucl = new URLClassLoader(urlsList.toArray(new URL[0])); 171 try { 172 return (Driver) Class.forName(classname, true, ucl).newInstance(); 173 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { 174 throw new DatabaseDriverException(e); 175 } 176 } 177 178}