From 85f0bb95870de59d4e53e486bee991fb11593298 Mon Sep 17 00:00:00 2001
From: Jonathan Hsieh <jon@cloudera.com>
Date: Mon, 2 May 2011 14:23:49 -0700
Subject: [PATCH] SQOOP-118. Sqoop should work without HBase where possible.

---
 bin/configure-sqoop                                |   10 ++--
 src/java/com/cloudera/sqoop/hbase/HBaseUtil.java   |   51 ++++++++++++++++++++
 .../com/cloudera/sqoop/manager/SqlManager.java     |   10 ++++-
 .../com/cloudera/sqoop/hbase/TestHBaseImport.java  |   19 +++++++
 .../cloudera/sqoop/hbase/TestHBaseQueryImport.java |   20 ++++++++
 .../com/cloudera/sqoop/hbase/TestHBaseUtil.java    |   44 +++++++++++++++++
 6 files changed, 149 insertions(+), 5 deletions(-)
 create mode 100644 src/java/com/cloudera/sqoop/hbase/HBaseUtil.java
 create mode 100644 src/test/com/cloudera/sqoop/hbase/TestHBaseUtil.java

diff --git a/bin/configure-sqoop b/bin/configure-sqoop
index 19e9f61..31a75eb 100755
--- a/bin/configure-sqoop
+++ b/bin/configure-sqoop
@@ -44,13 +44,13 @@ if [ ! -d "${HADOOP_HOME}" ]; then
   echo 'Please set $HADOOP_HOME to the root of your Hadoop installation.'
   exit 1
 fi
+
+## Moved to be a runtime check in sqoop.
 if [ ! -d "${HBASE_HOME}" ]; then
-  echo "Error: $HBASE_HOME does not exist!"
+  echo "Warning: $HBASE_HOME does not exist! HBase imports will fail."
   echo 'Please set $HBASE_HOME to the root of your HBase installation.'
-  exit 1
 fi
 
-
 # Where to find the main Sqoop jar
 SQOOP_JAR_DIR=$SQOOP_HOME
 
@@ -76,7 +76,9 @@ if [ -d "$SQOOP_HOME/lib" ]; then
 fi
 
 # Add HBase to dependency list
-SQOOP_CLASSPATH=`$HBASE_HOME/bin/hbase classpath`:${SQOOP_CLASSPATH}
+if [ -e "$HBASE_HOME/bin/hbase" ]; then
+  SQOOP_CLASSPATH=`$HBASE_HOME/bin/hbase classpath`:${SQOOP_CLASSPATH}
+fi
 
 ZOOCFGDIR=${ZOOCFGDIR:-/etc/zookeeper}
 if [ -d "${ZOOCFGDIR}" ]; then
diff --git a/src/java/com/cloudera/sqoop/hbase/HBaseUtil.java b/src/java/com/cloudera/sqoop/hbase/HBaseUtil.java
new file mode 100644
index 0000000..dab5e36
--- /dev/null
+++ b/src/java/com/cloudera/sqoop/hbase/HBaseUtil.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.sqoop.hbase;
+
+/**
+ * This class provides a method that checks if HBase jars are present in the
+ * current classpath. It also provides a setAlwaysNoHBaseJarMode mechanism for
+ * testing and simulation the condition where the is on HBase jar (since hbase
+ * is pulled automatically by ivy)
+ */
+public final class HBaseUtil {
+  private static boolean testingMode = false;
+
+  private HBaseUtil() {
+  }
+
+  /**
+   * This is a way to make this always return false for testing.
+   */
+  public static void setAlwaysNoHBaseJarMode(boolean mode) {
+    testingMode = mode;
+  }
+
+  public static boolean isHBaseJarPresent() {
+    if (testingMode) {
+      return false;
+    }
+    try {
+      Class.forName("org.apache.hadoop.hbase.client.HTable");
+    } catch (ClassNotFoundException cnfe) {
+      return false;
+    }
+    return true;
+  }
+}
diff --git a/src/java/com/cloudera/sqoop/manager/SqlManager.java b/src/java/com/cloudera/sqoop/manager/SqlManager.java
index 655c2d6..ed3c92f 100644
--- a/src/java/com/cloudera/sqoop/manager/SqlManager.java
+++ b/src/java/com/cloudera/sqoop/manager/SqlManager.java
@@ -21,6 +21,7 @@ package com.cloudera.sqoop.manager;
 import java.sql.Timestamp;
 
 import com.cloudera.sqoop.SqoopOptions;
+import com.cloudera.sqoop.hbase.HBaseUtil;
 import com.cloudera.sqoop.hive.HiveTypes;
 import com.cloudera.sqoop.lib.BlobRef;
 import com.cloudera.sqoop.lib.ClobRef;
@@ -369,7 +370,6 @@ public abstract class SqlManager extends ConnManager {
           + tableName + ". Please specify one with --split-by or perform "
           + "a sequential import with '-m 1'.");
     }
-
   }
 
   /**
@@ -387,6 +387,10 @@ public abstract class SqlManager extends ConnManager {
     ImportJobBase importer;
     if (opts.getHBaseTable() != null) {
       // Import to HBase.
+      if (!HBaseUtil.isHBaseJarPresent()) {
+        throw new ImportException("HBase jars are not present in "
+            + "classpath, cannot import to HBase!");
+      }
       importer = new HBaseImportJob(opts, context);
     } else {
       // Import to HDFS.
@@ -415,6 +419,10 @@ public abstract class SqlManager extends ConnManager {
     ImportJobBase importer;
     if (opts.getHBaseTable() != null) {
       // Import to HBase.
+      if (!HBaseUtil.isHBaseJarPresent()) {
+        throw new ImportException("HBase jars are not present in classpath,"
+            + " cannot import to HBase!");
+      }
       importer = new HBaseImportJob(opts, context);
     } else {
       // Import to HDFS.
diff --git a/src/test/com/cloudera/sqoop/hbase/TestHBaseImport.java b/src/test/com/cloudera/sqoop/hbase/TestHBaseImport.java
index a446621..edd6f03 100644
--- a/src/test/com/cloudera/sqoop/hbase/TestHBaseImport.java
+++ b/src/test/com/cloudera/sqoop/hbase/TestHBaseImport.java
@@ -93,4 +93,23 @@ public class TestHBaseImport extends HBaseTestCase {
     // This cell should not be placed in the results..
     verifyHBaseCell("nullT", "0", "nullF", getColName(2), null);
   }
+
+  @Test
+  public void testExitFailure() throws IOException {
+    String [] types = { "INT", "INT", "INT" };
+    String [] vals = { "0", "42", "43" };
+    createTableWithColTypes(types, vals);
+
+    String [] argv = getArgv(true, "NoHBaseT", "NoHBaseF", true, null);
+    try {
+      HBaseUtil.setAlwaysNoHBaseJarMode(true);
+      runImport(argv);
+    } catch (IOException e)  {
+      return;
+    } finally {
+      HBaseUtil.setAlwaysNoHBaseJarMode(false);
+    }
+
+    fail("should have gotten exception");
+  }
 }
diff --git a/src/test/com/cloudera/sqoop/hbase/TestHBaseQueryImport.java b/src/test/com/cloudera/sqoop/hbase/TestHBaseQueryImport.java
index b40d7ab..2f72fce 100644
--- a/src/test/com/cloudera/sqoop/hbase/TestHBaseQueryImport.java
+++ b/src/test/com/cloudera/sqoop/hbase/TestHBaseQueryImport.java
@@ -44,4 +44,24 @@ public class TestHBaseQueryImport extends HBaseTestCase {
     // This cell should not be placed in the results..
     verifyHBaseCell("queryT", "0", "queryF", getColName(2), null);
   }
+
+  @Test
+  public void testExitFailure() throws IOException {
+    String [] types = { "INT", "INT", "INT" };
+    String [] vals = { "0", "42", "43" };
+    createTableWithColTypes(types, vals);
+
+    String [] argv = getArgv(true, "queryT", "queryF", true,
+        "SELECT " + getColName(0) + ", " + getColName(1) + " FROM "
+        + getTableName() + " WHERE $CONDITIONS");
+    try {
+      HBaseUtil.setAlwaysNoHBaseJarMode(true);
+      runImport(argv);
+    } catch (Exception e)  {
+      return;
+    } finally {
+      HBaseUtil.setAlwaysNoHBaseJarMode(false);
+    }
+    fail("should have gotten exception");
+  }
 }
diff --git a/src/test/com/cloudera/sqoop/hbase/TestHBaseUtil.java b/src/test/com/cloudera/sqoop/hbase/TestHBaseUtil.java
new file mode 100644
index 0000000..ef66be1
--- /dev/null
+++ b/src/test/com/cloudera/sqoop/hbase/TestHBaseUtil.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.sqoop.hbase;
+
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+/**
+ * This tests to verify that HBase is present (default when running test cases)
+ * and that when in fake not present mode, the method return false.
+ */
+public class TestHBaseUtil extends TestCase {
+
+  @Test
+  public void testHBasePresent() {
+    assertTrue(HBaseUtil.isHBaseJarPresent());
+  }
+
+  @Test
+  public void testHBaseNotPresent() {
+    HBaseUtil.setAlwaysNoHBaseJarMode(true);
+    boolean present = HBaseUtil.isHBaseJarPresent();
+    HBaseUtil.setAlwaysNoHBaseJarMode(false);
+    assertFalse(present);
+  }
+
+}
-- 
1.7.1

