diff --git a/common/src/main/java/org/apache/sqoop/common/SupportedDirections.java b/common/src/main/java/org/apache/sqoop/common/SupportedDirections.java new file mode 100644 index 00000000..25ba2762 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/common/SupportedDirections.java @@ -0,0 +1,41 @@ +/** + * 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.sqoop.common; + +/** + * Represents which Directions are supported. + */ +public class SupportedDirections { + private boolean from; + private boolean to; + + public SupportedDirections(boolean from, boolean to) { + this.from = from; + this.to = to; + } + + /** + * Check if direction is supported. + * @param direction + * @return boolean + */ + public boolean isDirectionSupported(Direction direction) { + return direction == Direction.FROM && from + || direction == Direction.TO && to; + } +} diff --git a/common/src/main/java/org/apache/sqoop/model/MConnector.java b/common/src/main/java/org/apache/sqoop/model/MConnector.java index 335a0cc1..3dc1014d 100644 --- a/common/src/main/java/org/apache/sqoop/model/MConnector.java +++ b/common/src/main/java/org/apache/sqoop/model/MConnector.java @@ -20,6 +20,7 @@ import org.apache.sqoop.common.Direction; import org.apache.sqoop.common.DirectionError; import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.common.SupportedDirections; /** * Connector metadata. @@ -139,4 +140,9 @@ public String getVersion() { public void setVersion(String version) { this.version = version; } + + public SupportedDirections getSupportedDirections() { + return new SupportedDirections(this.getJobForms(Direction.FROM) != null, + this.getJobForms(Direction.TO) != null); + } } diff --git a/common/src/test/java/org/apache/sqoop/common/TestSupportedDirections.java b/common/src/test/java/org/apache/sqoop/common/TestSupportedDirections.java new file mode 100644 index 00000000..4fbaf82d --- /dev/null +++ b/common/src/test/java/org/apache/sqoop/common/TestSupportedDirections.java @@ -0,0 +1,55 @@ +/** + * 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.sqoop.common; + +import org.junit.Assert; +import org.junit.Test; + +public class TestSupportedDirections { + + @Test + public void testIsDirectionSupported() { + // Both + SupportedDirections supportedDirections = new SupportedDirections(true, true); + Assert.assertTrue( + supportedDirections.isDirectionSupported(Direction.FROM)); + Assert.assertTrue( + supportedDirections.isDirectionSupported(Direction.TO)); + + // FROM + supportedDirections = new SupportedDirections(true, false); + Assert.assertTrue( + supportedDirections.isDirectionSupported(Direction.FROM)); + Assert.assertFalse( + supportedDirections.isDirectionSupported(Direction.TO)); + + // TO + supportedDirections = new SupportedDirections(false, true); + Assert.assertFalse( + supportedDirections.isDirectionSupported(Direction.FROM)); + Assert.assertTrue( + supportedDirections.isDirectionSupported(Direction.TO)); + + // NONE + supportedDirections = new SupportedDirections(false, false); + Assert.assertFalse( + supportedDirections.isDirectionSupported(Direction.FROM)); + Assert.assertFalse( + supportedDirections.isDirectionSupported(Direction.TO)); + } +} diff --git a/common/src/test/java/org/apache/sqoop/model/TestMConnector.java b/common/src/test/java/org/apache/sqoop/model/TestMConnector.java index 9672d9d5..3fde47b2 100644 --- a/common/src/test/java/org/apache/sqoop/model/TestMConnector.java +++ b/common/src/test/java/org/apache/sqoop/model/TestMConnector.java @@ -20,8 +20,10 @@ import static org.junit.Assert.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.apache.sqoop.common.Direction; import org.junit.Test; /** @@ -29,6 +31,34 @@ */ public class TestMConnector { + private MConnector createConnector(List supportedDirections) { + List forms = new ArrayList(); + MIntegerInput input = new MIntegerInput("INTEGER-INPUT", false); + input.setValue(100); + MStringInput strInput = new MStringInput("STRING-INPUT",false,(short)20); + strInput.setValue("TEST-VALUE"); + List> list = new ArrayList>(); + list.add(input); + list.add(strInput); + MForm form = new MForm("FORMNAME", list); + forms.add(form); + + MConnectionForms connectionForms1 = new MConnectionForms(forms); + MJobForms fromForm = null; + MJobForms toForm = null; + + if (supportedDirections.contains(Direction.FROM)) { + fromForm = new MJobForms(forms); + } + + if (supportedDirections.contains(Direction.TO)) { + toForm = new MJobForms(forms); + } + + return new MConnector("NAME", "CLASSNAME", "1.0", + connectionForms1, fromForm, toForm); + } + /** * Test for initialization */ @@ -65,47 +95,58 @@ public void testInitialization() { } } -// @Test -// public void testClone() { -// List forms = new ArrayList(); -// MIntegerInput input = new MIntegerInput("INTEGER-INPUT", false); -// input.setValue(100); -// MStringInput strInput = new MStringInput("STRING-INPUT",false,(short)20); -// strInput.setValue("TEST-VALUE"); -// List> list = new ArrayList>(); -// list.add(input); -// list.add(strInput); -// MForm form = new MForm("FORMNAME", list); -// forms.add(form); -// MConnectionForms connectionForms1 = new MConnectionForms(forms); -// MJobForms jobform1 = new MJobForms(MJob.Type.EXPORT, forms); -// List jobFormList = new ArrayList(); -// jobFormList.add(jobform1); -// MConnector connector1 = new MConnector("NAME", "CLASSNAME", "1.0", -// connectionForms1, jobFormList); -// assertEquals("NAME", connector1.getUniqueName()); -// assertEquals("CLASSNAME", connector1.getClassName()); -// assertEquals("1.0", connector1.getVersion()); -// //Clone with values. Checking values copying after the cloning. But form values will be null -// MConnector clone1 = connector1.clone(true); -// assertEquals("NAME", clone1.getUniqueName()); -// assertEquals("CLASSNAME", clone1.getClassName()); -// assertEquals("1.0", clone1.getVersion()); -// MForm clonedForm1 = clone1.getConnectionForms().getForms().get(0); -// assertNull(clonedForm1.getInputs().get(0).getValue()); -// assertNull(clonedForm1.getInputs().get(1).getValue()); -// -// MForm clonedForm2 = clone1.getJobForms(MJob.Type.EXPORT).getForms().get(0); -// assertNull(clonedForm2.getInputs().get(0).getValue()); -// assertNull(clonedForm2.getInputs().get(1).getValue()); -// -// //Clone without values. Inputs value will be null after cloning. -// MConnector clone2 = connector1.clone(false); -// clonedForm1 = clone2.getConnectionForms().getForms().get(0); -// assertNull(clonedForm1.getInputs().get(0).getValue()); -// assertNull(clonedForm1.getInputs().get(1).getValue()); -// clonedForm2 = clone2.getJobForms(MJob.Type.EXPORT).getForms().get(0); -// assertNull(clonedForm2.getInputs().get(0).getValue()); -// assertNull(clonedForm2.getInputs().get(1).getValue()); -// } + @Test + public void testClone() { + MConnector connector1 = createConnector(Arrays.asList(Direction.FROM, Direction.TO)); + assertEquals("NAME", connector1.getUniqueName()); + assertEquals("CLASSNAME", connector1.getClassName()); + assertEquals("1.0", connector1.getVersion()); + //Clone with values. Checking values copying after the cloning. But form values will be null + MConnector clone1 = connector1.clone(true); + assertEquals("NAME", clone1.getUniqueName()); + assertEquals("CLASSNAME", clone1.getClassName()); + assertEquals("1.0", clone1.getVersion()); + MForm clonedForm1 = clone1.getConnectionForms().getForms().get(0); + assertNull(clonedForm1.getInputs().get(0).getValue()); + assertNull(clonedForm1.getInputs().get(1).getValue()); + + MForm clonedForm2 = clone1.getJobForms(Direction.FROM).getForms().get(0); + assertNull(clonedForm2.getInputs().get(0).getValue()); + assertNull(clonedForm2.getInputs().get(1).getValue()); + + MForm clonedForm3 = clone1.getJobForms(Direction.TO).getForms().get(0); + assertNull(clonedForm3.getInputs().get(0).getValue()); + assertNull(clonedForm3.getInputs().get(1).getValue()); + + //Clone without values. Inputs value will be null after cloning. + MConnector clone2 = connector1.clone(false); + clonedForm1 = clone2.getConnectionForms().getForms().get(0); + assertNull(clonedForm1.getInputs().get(0).getValue()); + assertNull(clonedForm1.getInputs().get(1).getValue()); + clonedForm2 = clone2.getJobForms(Direction.FROM).getForms().get(0); + assertNull(clonedForm2.getInputs().get(0).getValue()); + assertNull(clonedForm2.getInputs().get(1).getValue()); + clonedForm3 = clone2.getJobForms(Direction.TO).getForms().get(0); + assertNull(clonedForm3.getInputs().get(0).getValue()); + assertNull(clonedForm3.getInputs().get(1).getValue()); + } + + @Test + public void testGetSupportedDirections() { + MConnector connector = createConnector(Arrays.asList(Direction.FROM, Direction.TO)); + assertTrue(connector.getSupportedDirections().isDirectionSupported(Direction.FROM)); + assertTrue(connector.getSupportedDirections().isDirectionSupported(Direction.TO)); + + connector = createConnector(Arrays.asList(Direction.FROM)); + assertTrue(connector.getSupportedDirections().isDirectionSupported(Direction.FROM)); + assertFalse(connector.getSupportedDirections().isDirectionSupported(Direction.TO)); + + connector = createConnector(Arrays.asList(Direction.TO)); + assertFalse(connector.getSupportedDirections().isDirectionSupported(Direction.FROM)); + assertTrue(connector.getSupportedDirections().isDirectionSupported(Direction.TO)); + + connector = createConnector(Arrays.asList(new Direction[]{})); + assertFalse(connector.getSupportedDirections().isDirectionSupported(Direction.FROM)); + assertFalse(connector.getSupportedDirections().isDirectionSupported(Direction.TO)); + } } diff --git a/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java b/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java index 87822091..6c10b548 100644 --- a/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java +++ b/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java @@ -98,15 +98,11 @@ public ConnectorHandler(URL configFileUrl) { if (connector.getSupportedDirections().contains(Direction.FROM)) { fromJobForms = new MJobForms(FormUtils.toForms( connector.getJobConfigurationClass(Direction.FROM))); - } else { - fromJobForms = new MJobForms(new ArrayList()); } if (connector.getSupportedDirections().contains(Direction.TO)) { toJobForms = new MJobForms(FormUtils.toForms( connector.getJobConfigurationClass(Direction.TO))); - } else { - toJobForms = new MJobForms(new ArrayList()); } MConnectionForms connectionForms = new MConnectionForms( diff --git a/shell/src/main/java/org/apache/sqoop/shell/ShowConnectorFunction.java b/shell/src/main/java/org/apache/sqoop/shell/ShowConnectorFunction.java index bbfbb3f1..50978ff1 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/ShowConnectorFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/ShowConnectorFunction.java @@ -23,6 +23,8 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.OptionBuilder; +import org.apache.sqoop.common.Direction; +import org.apache.sqoop.common.SupportedDirections; import org.apache.sqoop.model.MConnector; import org.apache.sqoop.shell.core.Constants; import org.apache.sqoop.shell.utils.TableDisplayer; @@ -33,6 +35,8 @@ @SuppressWarnings("serial") public class ShowConnectorFunction extends SqoopFunction { + private static final char SUPPORTED_DIRECTIONS_SEPARATOR = '/'; + @SuppressWarnings("static-access") public ShowConnectorFunction() { this.addOption(OptionBuilder @@ -66,20 +70,23 @@ private void showSummary() { header.add(resourceString(Constants.RES_TABLE_HEADER_NAME)); header.add(resourceString(Constants.RES_TABLE_HEADER_VERSION)); header.add(resourceString(Constants.RES_TABLE_HEADER_CLASS)); + header.add(resourceString(Constants.RES_TABLE_HEADER_SUPPORTED_DIRECTIONS)); List ids = new LinkedList(); List uniqueNames = new LinkedList(); List versions = new LinkedList(); List classes = new LinkedList(); + List supportedDirections = new LinkedList(); for(MConnector connector : connectors) { ids.add(String.valueOf(connector.getPersistenceId())); uniqueNames.add(connector.getUniqueName()); versions.add(connector.getVersion()); classes.add(connector.getClassName()); + supportedDirections.add(getSupportedDirections(connector)); } - TableDisplayer.display(header, ids, uniqueNames, versions, classes); + TableDisplayer.display(header, ids, uniqueNames, versions, classes, supportedDirections); } private void showConnectors() { @@ -105,8 +112,34 @@ private void displayConnector(MConnector connector) { connector.getPersistenceId(), connector.getUniqueName(), connector.getClassName(), - connector.getVersion() + connector.getVersion(), + getSupportedDirections(connector) ); displayFormMetadataDetails(connector, client.getResourceBundle(connector.getPersistenceId())); } + + /** + * Creates a nicely formatted string for which directions are supported. + * Example: FROM/TO. + * @param connector + * @return String + */ + private String getSupportedDirections(MConnector connector) { + StringBuffer supportedDirectionsBuffer = new StringBuffer(); + SupportedDirections supportedDirections + = connector.getSupportedDirections(); + + if (supportedDirections.isDirectionSupported(Direction.FROM)) { + supportedDirectionsBuffer.append(Direction.FROM); + + if (supportedDirections.isDirectionSupported(Direction.TO)) { + supportedDirectionsBuffer.append(SUPPORTED_DIRECTIONS_SEPARATOR); + supportedDirectionsBuffer.append(Direction.TO); + } + } else if (supportedDirections.isDirectionSupported(Direction.TO)) { + supportedDirectionsBuffer.append(Direction.TO); + } + + return supportedDirectionsBuffer.toString(); + } } diff --git a/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java b/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java index efabc460..f0dc3a6f 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java +++ b/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java @@ -333,6 +333,8 @@ public class Constants { "table.header.version"; public static final String RES_TABLE_HEADER_CLASS = "table.header.class"; + public static final String RES_TABLE_HEADER_SUPPORTED_DIRECTIONS = + "table.header.supported_directions"; public static final String RES_TABLE_HEADER_CONNECTOR = "table.header.connector"; public static final String RES_TABLE_HEADER_FROM_CONNECTOR = diff --git a/shell/src/main/resources/shell-resource.properties b/shell/src/main/resources/shell-resource.properties index 73a19e87..247ceae7 100644 --- a/shell/src/main/resources/shell-resource.properties +++ b/shell/src/main/resources/shell-resource.properties @@ -137,8 +137,8 @@ show.prompt_display_all_connectors = Display all connectors show.prompt_display_connector_cid = Display the connector with cid show.connector_usage = Usage: show connector show.prompt_connectors_to_show = @|bold {0} connector(s) to show: |@ -show.prompt_connector_info = Connector with id {0}:\n Name: {1} \n \ -Class: {2}\n Version: {3} +show.prompt_connector_info = Connector with id {0}:\n Name: {1} \n \ +Class: {2}\n Version: {3}\n Supported Directions {4} show.framework_usage = Usage: show framework show.prompt_framework_opts = @|bold Framework specific options: |@\nPersistent id: {0} @@ -190,6 +190,7 @@ table.header.id = Id table.header.name = Name table.header.version = Version table.header.class = Class +table.header.supported_directions = Supported Directions table.header.connector = Connector table.header.connector.from = From Connector table.header.connector.to = To Connector