/** * 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 org.apache.drill.jdbc; import static org.junit.Assert.assertEquals; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Paths; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.UUID; import java.util.Vector; import org.apache.commons.io.FileUtils; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class ITTestShadedJar { private static DrillbitClassLoader drillbitLoader; private static URLClassLoader rootClassLoader; private static URL getJdbcUrl() throws MalformedURLException { return new URL( String.format("%s../../target/drill-jdbc-all-%s.jar", ClassLoader.getSystemClassLoader().getResource("").toString(), System.getProperty("project.version") )); } static { String dirConfDir = "DRILL_CONF_DIR"; if (System.getProperty(dirConfDir) == null) { final File condDir = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString()); condDir.mkdirs(); condDir.deleteOnExit(); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { FileUtils.deleteQuietly(condDir); } }); System.setProperty(dirConfDir, condDir.getAbsolutePath()); } } @Test public void testDatabaseVersion() throws Exception { // print class path for debugging System.out.println("java.class.path:"); System.out.println(System.getProperty("java.class.path")); final URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader(); Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); method.setAccessible(true); method.invoke(loader, getJdbcUrl()); Class<?> clazz = loader.loadClass("org.apache.drill.jdbc.Driver"); try { Driver driver = (Driver) clazz.newInstance(); try (Connection c = driver.connect("jdbc:drill:drillbit=localhost:31010", null)) { DatabaseMetaData metadata = c.getMetaData(); assertEquals("Apache Drill JDBC Driver", metadata.getDriverName()); assertEquals("Apache Drill Server", metadata.getDatabaseProductName()); //assertEquals() } } catch (Exception ex) { throw ex; } } @Test public void executeJdbcAllQuery() throws Exception { // print class path for debugging System.out.println("java.class.path:"); System.out.println(System.getProperty("java.class.path")); final URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader(); Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); method.setAccessible(true); method.invoke(loader, getJdbcUrl()); Class<?> clazz = loader.loadClass("org.apache.drill.jdbc.Driver"); try { Driver driver = (Driver) clazz.newInstance(); try (Connection c = driver.connect("jdbc:drill:drillbit=localhost:31010", null)) { String path = Paths.get("").toAbsolutePath().toString() + "/src/test/resources/types.json"; printQuery(c, "select * from dfs.`" + path + "`"); } } catch (Exception ex) { throw ex; } } private static void printQuery(Connection c, String query) throws SQLException { try (Statement s = c.createStatement(); ResultSet result = s.executeQuery(query)) { while (result.next()) { final int columnCount = result.getMetaData().getColumnCount(); for(int i = 1; i < columnCount+1; i++){ System.out.print(result.getObject(i)); System.out.print('\t'); } System.out.println(result.getObject(1)); } } } @BeforeClass public static void setupDefaultTestCluster() throws Exception { drillbitLoader = new DrillbitClassLoader(); rootClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); try { runWithLoader("DrillbitStartThread", drillbitLoader); } catch (Exception e) { printClassesLoaded("root", rootClassLoader); throw e; } } @AfterClass public static void closeClient() throws Exception { runWithLoader("DrillbitStopThread", drillbitLoader); } private static int getClassesLoadedCount(ClassLoader classLoader) { try { Field f = ClassLoader.class.getDeclaredField("classes"); f.setAccessible(true); Vector<Class<?>> classes = (Vector<Class<?>>) f.get(classLoader); return classes.size(); } catch (Exception e) { System.out.println("Failure while loading class count."); return -1; } } private static void printClassesLoaded(String prefix, ClassLoader classLoader) { try { Field f = ClassLoader.class.getDeclaredField("classes"); f.setAccessible(true); Vector<Class<?>> classes = (Vector<Class<?>>) f.get(classLoader); for (Class<?> c : classes) { System.out.println(prefix + ": " + c.getName()); } } catch (Exception e) { System.out.println("Failure while printing loaded classes."); } } private static void runWithLoader(String name, ClassLoader loader) throws Exception { Class<?> clazz = loader.loadClass(ITTestShadedJar.class.getName() + "$" + name); Object o = clazz.getDeclaredConstructors()[0].newInstance(loader); clazz.getMethod("go").invoke(o); } public abstract static class AbstractLoaderThread extends Thread { private Exception ex; protected final ClassLoader loader; public AbstractLoaderThread(ClassLoader loader) { this.setContextClassLoader(loader); this.loader = loader; } @Override public final void run() { try { internalRun(); } catch (Exception e) { this.ex = e; } } protected abstract void internalRun() throws Exception; public void go() throws Exception { start(); join(); if (ex != null) { throw ex; } } } public static class DrillbitStartThread extends AbstractLoaderThread { public DrillbitStartThread(ClassLoader loader) { super(loader); } @Override protected void internalRun() throws Exception { Class<?> clazz = loader.loadClass("org.apache.drill.BaseTestQuery"); clazz.getMethod("setupDefaultTestCluster").invoke(null); // loader.loadClass("org.apache.drill.exec.exception.SchemaChangeException"); // execute a single query to make sure the drillbit is fully up clazz.getMethod("testNoResult", String.class, new Object[] {}.getClass()) .invoke(null, "select * from (VALUES 1)", new Object[] {}); } } public static class DrillbitStopThread extends AbstractLoaderThread { public DrillbitStopThread(ClassLoader loader) { super(loader); } @Override protected void internalRun() throws Exception { Class<?> clazz = loader.loadClass("org.apache.drill.BaseTestQuery"); clazz.getMethod("setupDefaultTestCluster").invoke(null); } } }