/* * Copyright © 2014-2015 Cask Data, Inc. * * Licensed 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 co.cask.cdap.explore.service; import com.google.common.base.Joiner; import com.google.common.io.ByteStreams; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.MRJobConfig; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hive.service.auth.HiveAuthFactory; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.net.URI; import java.net.URL; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * */ public class ExploreServiceUtilsTest { @ClassRule public static TemporaryFolder tmpFolder = new TemporaryFolder(); @Test public void testHiveVersion() throws Exception { // This would throw an exception if it didn't pass ExploreServiceUtils.checkHiveSupport(getClass().getClassLoader()); } @Test public void hijackConfFileTest() throws Exception { Configuration conf = new Configuration(false); conf.set("foo", "bar"); Assert.assertEquals(1, conf.size()); File tempDir = tmpFolder.newFolder(); File confFile = tmpFolder.newFile("hive-site.xml"); try (FileOutputStream os = new FileOutputStream(confFile)) { conf.writeXml(os); } File newConfFile = ExploreServiceUtils.updateConfFileForExplore(confFile, tempDir); conf = new Configuration(false); conf.addResource(newConfFile.toURI().toURL()); Assert.assertEquals(3, conf.size()); Assert.assertEquals("false", conf.get(Job.MAPREDUCE_JOB_USER_CLASSPATH_FIRST)); Assert.assertEquals("false", conf.get(Job.MAPREDUCE_JOB_CLASSLOADER)); Assert.assertEquals("bar", conf.get("foo")); // check yarn-site changes confFile = tmpFolder.newFile("yarn-site.xml"); conf = new YarnConfiguration(); try (FileOutputStream os = new FileOutputStream(confFile)) { conf.writeXml(os); } String yarnApplicationClassPath = "$PWD/*," + conf.get(YarnConfiguration.YARN_APPLICATION_CLASSPATH, Joiner.on(",").join(YarnConfiguration.DEFAULT_YARN_APPLICATION_CLASSPATH)); newConfFile = ExploreServiceUtils.updateConfFileForExplore(confFile, tempDir); conf = new Configuration(false); conf.addResource(newConfFile.toURI().toURL()); Assert.assertEquals(yarnApplicationClassPath, conf.get(YarnConfiguration.YARN_APPLICATION_CLASSPATH)); // check mapred-site changes confFile = tmpFolder.newFile("mapred-site.xml"); conf = new YarnConfiguration(); try (FileOutputStream os = new FileOutputStream(confFile)) { conf.writeXml(os); } String mapredApplicationClassPath = "$PWD/*," + conf.get(MRJobConfig.MAPREDUCE_APPLICATION_CLASSPATH, MRJobConfig.DEFAULT_MAPREDUCE_APPLICATION_CLASSPATH); newConfFile = ExploreServiceUtils.updateConfFileForExplore(confFile, tempDir); conf = new Configuration(false); conf.addResource(newConfFile.toURI().toURL()); Assert.assertEquals(mapredApplicationClassPath, conf.get(MRJobConfig.MAPREDUCE_APPLICATION_CLASSPATH)); // Ensure conf files that are not hive-site.xml/mapred-site.xml/yarn-site.xml are unchanged confFile = tmpFolder.newFile("core-site.xml"); Assert.assertEquals(confFile, ExploreServiceUtils.updateConfFileForExplore(confFile, tempDir)); } @Test public void testRewriteHiveAuthFactory() throws Exception { URL hiveAuthURL = getClass().getClassLoader().getResource( HiveAuthFactory.class.getName().replace('.', '/') + ".class"); String hiveJarFilePath = hiveAuthURL.getPath(); File hiveJarFile = new File(URI.create(hiveJarFilePath.substring(0, hiveJarFilePath.indexOf("!/")))); File targetJar = ExploreServiceUtils.rewriteHiveAuthFactory(hiveJarFile, new File(tmpFolder.newFolder(), "hive.jar")); try ( TestHiveAuthFactoryClassLoader cl = new TestHiveAuthFactoryClassLoader(targetJar, getClass().getClassLoader()) ) { Class<?> hiveAuthFactoryClass = cl.loadClass(HiveAuthFactory.class.getName()); Method loginFromKeytab = hiveAuthFactoryClass.getMethod("loginFromKeytab", HiveConf.class); // If the write is not successful, this will throw exception loginFromKeytab.invoke(null, new Object[] { null }); } } /** * A class loader which tries to load from the given jarFile first rather than the parent. */ private static final class TestHiveAuthFactoryClassLoader extends ClassLoader implements Closeable { private final JarFile jarFile; public TestHiveAuthFactoryClassLoader(File jarFile, ClassLoader parent) throws IOException { super(parent); this.jarFile = new JarFile(jarFile); } @Override public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, true); } @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // Try to load from itself first String fileName = name.replace('.', '/') + ".class"; JarEntry jarEntry = jarFile.getJarEntry(fileName); if (jarEntry == null) { return super.loadClass(name, resolve); } try (InputStream input = jarFile.getInputStream(jarEntry)) { byte[] bytes = ByteStreams.toByteArray(input); Class<?> cls = defineClass(name, bytes, 0, bytes.length); if (resolve) { resolveClass(cls); } return cls; } catch (IOException e) { throw new ClassNotFoundException("Class " + name + " not found.", e); } } @Override public void close() throws IOException { jarFile.close(); } } }