Repository: sqoop Updated Branches: refs/heads/sqoop2 96cb5ef1f -> eed2b3f50
SQOOP-1513: Sqoop2: Refactor LinkRequestHandler (Veena Basavaraj via Abraham Elmahrek) Project: http://git-wip-us.apache.org/repos/asf/sqoop/repo Commit: http://git-wip-us.apache.org/repos/asf/sqoop/commit/eed2b3f5 Tree: http://git-wip-us.apache.org/repos/asf/sqoop/tree/eed2b3f5 Diff: http://git-wip-us.apache.org/repos/asf/sqoop/diff/eed2b3f5 Branch: refs/heads/sqoop2 Commit: eed2b3f50a1d0568cc20d5667aa35de0be3f629f Parents: 96cb5ef Author: Abraham Elmahrek <[email protected]> Authored: Mon Oct 27 22:14:44 2014 -0700 Committer: Abraham Elmahrek <[email protected]> Committed: Mon Oct 27 22:14:44 2014 -0700 ---------------------------------------------------------------------- .../client/request/LinkResourceRequest.java | 35 +-- .../java/org/apache/sqoop/json/LinkBean.java | 33 ++- .../java/org/apache/sqoop/json/LinksBean.java | 59 ++++ .../org/apache/sqoop/json/TestLinkBean.java | 6 +- .../apache/sqoop/repository/JdbcRepository.java | 28 +- .../sqoop/repository/JdbcRepositoryHandler.java | 25 +- .../org/apache/sqoop/repository/Repository.java | 18 +- .../derby/DerbyRepositoryHandler.java | 112 +++++--- ...erbySchemaInsertUpdateDeleteSelectQuery.java | 15 + .../repository/derby/TestLinkHandling.java | 34 ++- .../apache/sqoop/handler/JobRequestHandler.java | 2 - .../sqoop/handler/LinkRequestHandler.java | 283 ++++++++++--------- .../org/apache/sqoop/server/RequestContext.java | 8 + .../apache/sqoop/server/common/ServerError.java | 3 + .../sqoop/server/v1/ConnectorServlet.java | 2 +- .../apache/sqoop/server/v1/DriverServlet.java | 2 +- .../org/apache/sqoop/server/v1/LinkServlet.java | 27 ++ .../apache/sqoop/server/v1/LinksServlet.java | 48 ++++ server/src/main/webapp/WEB-INF/web.xml | 12 + .../apache/sqoop/shell/UpdateLinkFunction.java | 1 + 20 files changed, 504 insertions(+), 249 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/client/src/main/java/org/apache/sqoop/client/request/LinkResourceRequest.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/sqoop/client/request/LinkResourceRequest.java b/client/src/main/java/org/apache/sqoop/client/request/LinkResourceRequest.java index 64e5cb1..f03acb4 100644 --- a/client/src/main/java/org/apache/sqoop/client/request/LinkResourceRequest.java +++ b/client/src/main/java/org/apache/sqoop/client/request/LinkResourceRequest.java @@ -18,6 +18,7 @@ package org.apache.sqoop.client.request; import org.apache.sqoop.json.LinkBean; +import org.apache.sqoop.json.LinksBean; import org.apache.sqoop.json.ValidationResultBean; import org.apache.sqoop.model.MLink; import org.json.simple.JSONObject; @@ -29,30 +30,33 @@ import org.json.simple.JSONValue; */ public class LinkResourceRequest extends ResourceRequest { - public static final String RESOURCE = "v1/link/"; + public static final String LINK_RESOURCE = "v1/link/"; private static final String ENABLE = "/enable"; private static final String DISABLE = "/disable"; - public LinkBean read(String serverUrl, Long xid) { + public LinkBean read(String serverUrl, Long linkId) { String response; - if (xid == null) { - response = super.get(serverUrl + RESOURCE + "all"); + if (linkId == null) { + response = super.get(serverUrl + LINK_RESOURCE + "all"); } else { - response = super.get(serverUrl + RESOURCE + xid); + response = super.get(serverUrl + LINK_RESOURCE + linkId); } - JSONObject jsonObject = (JSONObject)JSONValue.parse(response); - LinkBean linkBean = new LinkBean(); - linkBean.restore(jsonObject); - return linkBean; + JSONObject jsonObject = (JSONObject) JSONValue.parse(response); + // defaults to all + LinkBean bean = new LinksBean(); + if (linkId != null) { + bean = new LinkBean(); + } + bean.restore(jsonObject); + return bean; } public ValidationResultBean create(String serverUrl, MLink link) { LinkBean linkBean = new LinkBean(link); - // Extract all config inputs including sensitive inputs JSONObject linkJson = linkBean.extract(false); - String response = super.post(serverUrl + RESOURCE, linkJson.toJSONString()); + String response = super.post(serverUrl + LINK_RESOURCE, linkJson.toJSONString()); ValidationResultBean validationBean = new ValidationResultBean(); validationBean.restore((JSONObject) JSONValue.parse(response)); return validationBean; @@ -60,24 +64,23 @@ public class LinkResourceRequest extends ResourceRequest { public ValidationResultBean update(String serverUrl, MLink link) { LinkBean linkBean = new LinkBean(link); - // Extract all config inputs including sensitive inputs JSONObject linkJson = linkBean.extract(false); - String response = super.put(serverUrl + RESOURCE + link.getPersistenceId(), linkJson.toJSONString()); + String response = super.put(serverUrl + LINK_RESOURCE + link.getPersistenceId(), linkJson.toJSONString()); ValidationResultBean validationBean = new ValidationResultBean(); validationBean.restore((JSONObject) JSONValue.parse(response)); return validationBean; } public void delete(String serverUrl, Long id) { - super.delete(serverUrl + RESOURCE + id); + super.delete(serverUrl + LINK_RESOURCE + id); } public void enable(String serverUrl, Long id, Boolean enabled) { if (enabled) { - super.put(serverUrl + RESOURCE + id + ENABLE, null); + super.put(serverUrl + LINK_RESOURCE + id + ENABLE, null); } else { - super.put(serverUrl + RESOURCE + id + DISABLE, null); + super.put(serverUrl + LINK_RESOURCE + id + DISABLE, null); } } } http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/common/src/main/java/org/apache/sqoop/json/LinkBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/LinkBean.java b/common/src/main/java/org/apache/sqoop/json/LinkBean.java index 2762500..bc59352 100644 --- a/common/src/main/java/org/apache/sqoop/json/LinkBean.java +++ b/common/src/main/java/org/apache/sqoop/json/LinkBean.java @@ -19,8 +19,6 @@ package org.apache.sqoop.json; import static org.apache.sqoop.json.util.ConfigInputSerialization.extractConfigList; import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigList; -import static org.apache.sqoop.json.util.ConfigBundleSerialization.extractConfigParamBundle; -import static org.apache.sqoop.json.util.ConfigBundleSerialization.restoreConfigParamBundle; import java.util.ArrayList; import java.util.Date; @@ -45,8 +43,11 @@ public class LinkBean implements JsonBean { static final String CONNECTOR_ID = "connector-id"; static final String LINK_CONFIG = "link-config"; + static final String LINK = "link"; + // Required + // Stores all links for a given connector private List<MLink> links; // Optional @@ -85,14 +86,20 @@ public class LinkBean implements JsonBean { return linkConfigBundles.get(id); } - @Override @SuppressWarnings("unchecked") + @Override public JSONObject extract(boolean skipSensitive) { JSONArray linkArray = new JSONArray(); + extractLinks(skipSensitive, linkArray); + JSONObject all = new JSONObject(); + all.put(LINK, linkArray); + return all; + } + @SuppressWarnings("unchecked") + protected void extractLinks(boolean skipSensitive, JSONArray linkArray) { for(MLink link : links) { JSONObject linkJsonObject = new JSONObject(); - linkJsonObject.put(ID, link.getPersistenceId()); linkJsonObject.put(NAME, link.getName()); linkJsonObject.put(ENABLED, link.getEnabled()); @@ -103,31 +110,24 @@ public class LinkBean implements JsonBean { linkJsonObject.put(CONNECTOR_ID, link.getConnectorId()); linkJsonObject.put(LINK_CONFIG, extractConfigList(link.getConnectorLinkConfig().getConfigs(), link.getConnectorLinkConfig().getType(), skipSensitive)); - linkArray.add(linkJsonObject); } - - JSONObject all = new JSONObject(); - all.put(ALL, linkArray); - return all; } @Override public void restore(JSONObject jsonObject) { - links = new ArrayList<MLink>(); - - JSONArray array = (JSONArray) jsonObject.get(ALL); + JSONArray array = (JSONArray) jsonObject.get(LINK); + restoreLinks(array); + } + protected void restoreLinks(JSONArray array) { + links = new ArrayList<MLink>(); for (Object obj : array) { JSONObject object = (JSONObject) obj; - long connectorId = (Long) object.get(CONNECTOR_ID); JSONArray connectorLinkConfig = (JSONArray) object.get(LINK_CONFIG); - List<MConfig> linkConfig = restoreConfigList(connectorLinkConfig); - MLink link = new MLink(connectorId, new MLinkConfig(linkConfig)); - link.setPersistenceId((Long) object.get(ID)); link.setName((String) object.get(NAME)); link.setEnabled((Boolean) object.get(ENABLED)); @@ -135,7 +135,6 @@ public class LinkBean implements JsonBean { link.setCreationDate(new Date((Long) object.get(CREATION_DATE))); link.setLastUpdateUser((String) object.get(UPDATE_USER)); link.setLastUpdateDate(new Date((Long) object.get(UPDATE_DATE))); - links.add(link); } } http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/common/src/main/java/org/apache/sqoop/json/LinksBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/LinksBean.java b/common/src/main/java/org/apache/sqoop/json/LinksBean.java new file mode 100644 index 0000000..5858a18 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/LinksBean.java @@ -0,0 +1,59 @@ +/** + * 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.json; + +import java.util.List; + +import org.apache.sqoop.model.MLink; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class LinksBean extends LinkBean { + + static final String LINKS = "links"; + + public LinksBean(MLink link) { + super(link); + } + + public LinksBean(List<MLink> links) { + super(links); + } + + // For "restore" + public LinksBean() { + + } + + @SuppressWarnings("unchecked") + @Override + public JSONObject extract(boolean skipSensitive) { + JSONArray linkArray = new JSONArray(); + super.extractLinks(skipSensitive, linkArray); + JSONObject links = new JSONObject(); + links.put(LINKS, linkArray); + return links; + } + + @Override + public void restore(JSONObject jsonObject) { + + JSONArray array = (JSONArray) jsonObject.get(LINKS); + super.restoreLinks(array); + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java ---------------------------------------------------------------------- diff --git a/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java b/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java index 526ec52..811cbf0 100644 --- a/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java +++ b/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java @@ -59,7 +59,7 @@ public class TestLinkBean { JSONObject json = linkBean.extract(false); // Check for sensitivity - JSONArray all = (JSONArray)json.get(JsonBean.ALL); + JSONArray all = (JSONArray)json.get(LinkBean.LINK); JSONObject allItem = (JSONObject)all.get(0); JSONArray connectors = (JSONArray)allItem.get(LinkBean.LINK_CONFIG); JSONObject connector = (JSONObject)connectors.get(0); @@ -116,7 +116,7 @@ public class TestLinkBean { JSONObject jsonFiltered = bean.extract(true); // Sensitive values should exist - JSONArray all = (JSONArray)json.get(JsonBean.ALL); + JSONArray all = (JSONArray)json.get(LinkBean.LINK); JSONObject allItem = (JSONObject)all.get(0); JSONArray connectors = (JSONArray)allItem.get(LinkBean.LINK_CONFIG); JSONObject connector = (JSONObject)connectors.get(0); @@ -127,7 +127,7 @@ public class TestLinkBean { assertTrue(password.containsKey(ConfigInputConstants.CONFIG_INPUT_VALUE)); // Sensitive values should not exist - all = (JSONArray)jsonFiltered.get(JsonBean.ALL); + all = (JSONArray)jsonFiltered.get(LinkBean.LINK); allItem = (JSONObject)all.get(0); connectors = (JSONArray)allItem.get(LinkBean.LINK_CONFIG); connector = (JSONObject)connectors.get(0); http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java b/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java index 254ba9e..2aeb07e 100644 --- a/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java +++ b/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java @@ -349,11 +349,24 @@ public class JdbcRepository extends Repository { * {@inheritDoc} */ @Override - public MLink findLink(final long connectionId) { + public MLink findLink(final long id) { return (MLink) doWithConnection(new DoWithConnection() { @Override public Object doIt(Connection conn) { - return handler.findLink(connectionId, conn); + return handler.findLink(id, conn); + } + }); + } + + /** + * {@inheritDoc} + */ + @Override + public MLink findLink(final String name) { + return (MLink) doWithConnection(new DoWithConnection() { + @Override + public Object doIt(Connection conn) { + return handler.findLink(name, conn); } }); } @@ -609,13 +622,13 @@ public class JdbcRepository extends Repository { /** * {@inheritDoc} */ + @SuppressWarnings("unchecked") @Override - public List<MLink> findLinksForConnector(final long - connectorID) { + public List<MLink> findLinksForConnector(final long connectorId) { return (List<MLink>) doWithConnection(new DoWithConnection() { @Override public Object doIt(Connection conn) throws Exception { - return handler.findLinksForConnector(connectorID, conn); + return handler.findLinksForConnector(connectorId, conn); } }); } @@ -623,12 +636,13 @@ public class JdbcRepository extends Repository { /** * {@inheritDoc} */ + @SuppressWarnings("unchecked") @Override - public List<MJob> findJobsForConnector(final long connectorID) { + public List<MJob> findJobsForConnector(final long connectorId) { return (List<MJob>) doWithConnection(new DoWithConnection() { @Override public Object doIt(Connection conn) throws Exception { - return handler.findJobsForConnector(connectorID, conn); + return handler.findJobsForConnector(connectorId, conn); } }); } http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java b/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java index 7d78826..ad380d3 100644 --- a/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java +++ b/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java @@ -71,22 +71,20 @@ public abstract class JdbcRepositoryHandler { /** * Retrieve links which use the given connector. - * @param connectorID Connector ID whose links should be fetched + * @param connectorId Connector ID whose links should be fetched * @param conn JDBC link for querying repository * @return List of MLinks that use <code>connectorID</code>. */ - public abstract List<MLink> findLinksForConnector(long - connectorID, Connection conn); + public abstract List<MLink> findLinksForConnector(long connectorId, Connection conn); /** * Retrieve jobs which use the given link. * - * @param connectorID Connector ID whose jobs should be fetched + * @param connectorId Connector ID whose jobs should be fetched * @param conn JDBC link for querying repository * @return List of MJobs that use <code>linkID</code>. */ - public abstract List<MJob> findJobsForConnector(long connectorID, - Connection conn); + public abstract List<MJob> findJobsForConnector(long c, Connection conn); /** * Upgrade the connector with the new data supplied in the <tt>newConnector</tt>. @@ -234,20 +232,29 @@ public abstract class JdbcRepositoryHandler { /** * Delete the input values for the link with given id from the * repository. - * @param id Link object whose inputs should be removed from repository + * @param linkId Link object whose inputs should be removed from repository * @param conn Connection to the repository */ - public abstract void deleteLinkInputs(long id, Connection conn); + public abstract void deleteLinkInputs(long linkId, Connection conn); /** * Find link with given id in repository. * * @param linkId Link id * @param conn Connection to the repository - * @return Deserialized config of the link that is saved in repository + * @return the link that is saved in repository */ public abstract MLink findLink(long linkId, Connection conn); /** + * Find link with given name in repository. + * + * @param linkName unique link name + * @param conn Connection to the repository + * @return the link that is saved in repository or returns null if not found + */ + public abstract MLink findLink(String linkName, Connection conn); + + /** * Get all link objects. * * @param conn Connection to the repository http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/core/src/main/java/org/apache/sqoop/repository/Repository.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/sqoop/repository/Repository.java b/core/src/main/java/org/apache/sqoop/repository/Repository.java index fcee48b..79742b9 100644 --- a/core/src/main/java/org/apache/sqoop/repository/Repository.java +++ b/core/src/main/java/org/apache/sqoop/repository/Repository.java @@ -176,11 +176,19 @@ public abstract class Repository { * Find link with given id in repository. * * @param id Link id - * @return Deserialized config of the link that is saved in repository + * @return link that is saved in repository */ public abstract MLink findLink(long id); /** + * Find link with given id in repository. + * + * @param name unique link name + * @return link that is saved in repository or null if it does not exists + */ + public abstract MLink findLink(String name); + + /** * Get all Link objects. * * @return List will all saved link objects @@ -297,18 +305,18 @@ public abstract class Repository { /** * Retrieve links which use the given connector. - * @param connectorID Connector ID whose links should be fetched + * @param connectorId Connector ID whose links should be fetched * @return List of MLink that use <code>connectorID</code>. */ - public abstract List<MLink> findLinksForConnector(long connectorID); + public abstract List<MLink> findLinksForConnector(long connectorId); /** * Retrieve jobs which use the given link. * - * @param connectorID Connector ID whose jobs should be fetched + * @param connectorId Connector ID whose jobs should be fetched * @return List of MJobs that use <code>linkID</code>. */ - public abstract List<MJob> findJobsForConnector(long connectorID); + public abstract List<MJob> findJobsForConnector(long connectorId); /** * Update the connector with the new data supplied in the http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java ---------------------------------------------------------------------- diff --git a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java index 7f19c28..e584a19 100644 --- a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java +++ b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java @@ -17,11 +17,9 @@ */ package org.apache.sqoop.repository.derby; -import static org.apache.sqoop.repository.derby.DerbySchemaUpgradeQuery.*; import static org.apache.sqoop.repository.derby.DerbySchemaCreateQuery.*; import static org.apache.sqoop.repository.derby.DerbySchemaInsertUpdateDeleteSelectQuery.*; - - +import static org.apache.sqoop.repository.derby.DerbySchemaUpgradeQuery.*; import java.net.URL; import java.sql.Connection; import java.sql.DriverManager; @@ -158,7 +156,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { // Register link type config registerConfigs(connectorId, null /* No direction for LINK type config*/, mc.getLinkConfig().getConfigs(), - MConfigType.LINK.name(), baseConfigStmt, baseInputStmt, conn); + MConfigType.LINK.name(), baseConfigStmt, baseInputStmt, conn); // Register both from/to job type config for connector if (mc.getSupportedDirections().isDirectionSupported(Direction.FROM)) { @@ -1196,27 +1194,51 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { * {@inheritDoc} */ @Override - public MLink findLink(long id, Connection conn) { - PreparedStatement stmt = null; + public MLink findLink(long linkId, Connection conn) { + PreparedStatement linkFetchStmt = null; try { - stmt = conn.prepareStatement(STMT_SELECT_LINK_SINGLE); - stmt.setLong(1, id); + linkFetchStmt = conn.prepareStatement(STMT_SELECT_LINK_SINGLE); + linkFetchStmt.setLong(1, linkId); - List<MLink> connections = loadLinks(stmt, conn); + List<MLink> links = loadLinks(linkFetchStmt, conn); - if(connections.size() != 1) { + if(links.size() != 1) { throw new SqoopException(DerbyRepoError.DERBYREPO_0024, "Couldn't find" - + " link with id " + id); + + " link with id " + linkId); } - // Return the first and only one link object - return connections.get(0); + // Return the first and only one link object with the given id + return links.get(0); } catch (SQLException ex) { - logException(ex, id); + logException(ex, linkId); throw new SqoopException(DerbyRepoError.DERBYREPO_0023, ex); } finally { - closeStatements(stmt); + closeStatements(linkFetchStmt); + } + } + + @Override + public MLink findLink(String linkName, Connection conn) { + PreparedStatement linkFetchStmt = null; + try { + linkFetchStmt = conn.prepareStatement(STMT_SELECT_LINK_SINGLE_BY_NAME); + linkFetchStmt.setString(1, linkName); + + List<MLink> links = loadLinks(linkFetchStmt, conn); + + if (links.size() != 1) { + return null; + } + + // Return the first and only one link object with the given name + return links.get(0); + + } catch (SQLException ex) { + logException(ex, linkName); + throw new SqoopException(DerbyRepoError.DERBYREPO_0023, ex); + } finally { + closeStatements(linkFetchStmt); } } @@ -1225,17 +1247,17 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { */ @Override public List<MLink> findLinks(Connection conn) { - PreparedStatement stmt = null; + PreparedStatement linksFetchStmt = null; try { - stmt = conn.prepareStatement(STMT_SELECT_LINK_ALL); + linksFetchStmt = conn.prepareStatement(STMT_SELECT_LINK_ALL); - return loadLinks(stmt, conn); + return loadLinks(linksFetchStmt, conn); } catch (SQLException ex) { logException(ex); throw new SqoopException(DerbyRepoError.DERBYREPO_0023, ex); } finally { - closeStatements(stmt); + closeStatements(linksFetchStmt); } } @@ -1246,17 +1268,17 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { * */ @Override - public List<MLink> findLinksForConnector(long connectorID, Connection conn) { - PreparedStatement stmt = null; + public List<MLink> findLinksForConnector(long connectorId, Connection conn) { + PreparedStatement linkByConnectorFetchStmt = null; try { - stmt = conn.prepareStatement(STMT_SELECT_LINK_FOR_CONNECTOR_CONFIGURABLE); - stmt.setLong(1, connectorID); - return loadLinks(stmt, conn); + linkByConnectorFetchStmt = conn.prepareStatement(STMT_SELECT_LINK_FOR_CONNECTOR_CONFIGURABLE); + linkByConnectorFetchStmt.setLong(1, connectorId); + return loadLinks(linkByConnectorFetchStmt, conn); } catch (SQLException ex) { - logException(ex, connectorID); + logException(ex, connectorId); throw new SqoopException(DerbyRepoError.DERBYREPO_0023, ex); } finally { - closeStatements(stmt); + closeStatements(linkByConnectorFetchStmt); } } @@ -2128,7 +2150,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { List<MConfig> fromConfig = new ArrayList<MConfig>(); List<MConfig> toConfig = new ArrayList<MConfig>(); - loadConfigTypes(linkConfig, fromConfig, toConfig, connectorConfigFetchStmt, + loadConnectorConfigTypes(linkConfig, fromConfig, toConfig, connectorConfigFetchStmt, connectorConfigInputFetchStmt, 1, conn); SupportedDirections supportedDirections @@ -2154,20 +2176,16 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { return connectors; } - private List<MLink> loadLinks(PreparedStatement stmt, - Connection conn) - throws SQLException { + private List<MLink> loadLinks(PreparedStatement linkFetchStmt, Connection conn) throws SQLException { List<MLink> links = new ArrayList<MLink>(); ResultSet rsConnection = null; - PreparedStatement connectorConfigFetchStatement = null; - PreparedStatement connectorConfigInputStatement = null; + PreparedStatement connectorLinkConfigFetchStatement = null; + PreparedStatement connectorLinkConfigInputStatement = null; try { - rsConnection = stmt.executeQuery(); - - // - connectorConfigFetchStatement = conn.prepareStatement(STMT_SELECT_CONFIG_FOR_CONFIGURABLE); - connectorConfigInputStatement = conn.prepareStatement(STMT_FETCH_LINK_INPUT); + rsConnection = linkFetchStmt.executeQuery(); + connectorLinkConfigFetchStatement = conn.prepareStatement(STMT_SELECT_CONFIG_FOR_CONFIGURABLE); + connectorLinkConfigInputStatement = conn.prepareStatement(STMT_FETCH_LINK_INPUT); while(rsConnection.next()) { long id = rsConnection.getLong(1); @@ -2179,16 +2197,16 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { String updateUser = rsConnection.getString(7); Date lastUpdateDate = rsConnection.getTimestamp(8); - connectorConfigFetchStatement.setLong(1, connectorId); - connectorConfigInputStatement.setLong(1, id); - connectorConfigInputStatement.setLong(3, id); + connectorLinkConfigFetchStatement.setLong(1, connectorId); + connectorLinkConfigInputStatement.setLong(1, id); + connectorLinkConfigInputStatement.setLong(3, id); List<MConfig> connectorLinkConfig = new ArrayList<MConfig>(); List<MConfig> fromConfig = new ArrayList<MConfig>(); List<MConfig> toConfig = new ArrayList<MConfig>(); - loadConfigTypes(connectorLinkConfig, fromConfig, toConfig, connectorConfigFetchStatement, - connectorConfigInputStatement, 2, conn); + loadConnectorConfigTypes(connectorLinkConfig, fromConfig, toConfig, connectorLinkConfigFetchStatement, + connectorLinkConfigInputStatement, 2, conn); MLink link = new MLink(connectorId, new MLinkConfig(connectorLinkConfig)); link.setPersistenceId(id); @@ -2203,7 +2221,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { } } finally { closeResultSets(rsConnection); - closeStatements(connectorConfigFetchStatement, connectorConfigInputStatement); + closeStatements(connectorLinkConfigFetchStatement, connectorLinkConfigInputStatement); } return links; @@ -2254,7 +2272,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { List<MConfig> fromConnectorFromJobConfig = new ArrayList<MConfig>(); List<MConfig> fromConnectorToJobConfig = new ArrayList<MConfig>(); - loadConfigTypes(fromConnectorLinkConfig, fromConnectorFromJobConfig, fromConnectorToJobConfig, + loadConnectorConfigTypes(fromConnectorLinkConfig, fromConnectorFromJobConfig, fromConnectorToJobConfig, fromConfigFetchStmt, jobInputFetchStmt, 2, conn); // TO entity configs @@ -2265,7 +2283,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { // ?? dont we need 2 different driver configs for the from/to? List<MConfig> driverConfig = new ArrayList<MConfig>(); - loadConfigTypes(toConnectorLinkConfig, toConnectorFromJobConfig, toConnectorToJobConfig, + loadConnectorConfigTypes(toConnectorLinkConfig, toConnectorFromJobConfig, toConnectorToJobConfig, toConfigFetchStmt, jobInputFetchStmt, 2, conn); loadDriverConfigs(driverConfig, driverConfigfetchStmt, jobInputFetchStmt, 2); @@ -2592,7 +2610,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { } /** - * Load configs and corresponding inputs from Derby database. + * Load configs and corresponding inputs related to a connector * * Use given prepared statements to load all configs and corresponding inputs * from Derby. @@ -2605,7 +2623,7 @@ public class DerbyRepositoryHandler extends JdbcRepositoryHandler { * @param conn Connection object that is used to find config direction. * @throws SQLException In case of any failure on Derby side */ - public void loadConfigTypes(List<MConfig> linkConfig, List<MConfig> fromConfig, + public void loadConnectorConfigTypes(List<MConfig> linkConfig, List<MConfig> fromConfig, List<MConfig> toConfig, PreparedStatement configFetchStmt, PreparedStatement inputFetchStmt, int configPosition, Connection conn) throws SQLException { http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbySchemaInsertUpdateDeleteSelectQuery.java ---------------------------------------------------------------------- diff --git a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbySchemaInsertUpdateDeleteSelectQuery.java b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbySchemaInsertUpdateDeleteSelectQuery.java index 02b11fc..c894d06 100644 --- a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbySchemaInsertUpdateDeleteSelectQuery.java +++ b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbySchemaInsertUpdateDeleteSelectQuery.java @@ -304,6 +304,21 @@ public final class DerbySchemaInsertUpdateDeleteSelectQuery { + " FROM " + TABLE_SQ_LINK + " WHERE " + COLUMN_SQ_LNK_ID + " = ?"; + + // DML: Select one specific link by name + public static final String STMT_SELECT_LINK_SINGLE_BY_NAME = + "SELECT " + + COLUMN_SQ_LNK_ID + ", " + + COLUMN_SQ_LNK_NAME + ", " + + COLUMN_SQ_LNK_CONFIGURABLE + ", " + + COLUMN_SQ_LNK_ENABLED + ", " + + COLUMN_SQ_LNK_CREATION_USER + ", " + + COLUMN_SQ_LNK_CREATION_DATE + ", " + + COLUMN_SQ_LNK_UPDATE_USER + ", " + + COLUMN_SQ_LNK_UPDATE_DATE + + " FROM " + TABLE_SQ_LINK + + " WHERE " + COLUMN_SQ_LNK_NAME + " = ?"; + // DML: Select all links public static final String STMT_SELECT_LINK_ALL = "SELECT " http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/repository/repository-derby/src/test/java/org/apache/sqoop/repository/derby/TestLinkHandling.java ---------------------------------------------------------------------- diff --git a/repository/repository-derby/src/test/java/org/apache/sqoop/repository/derby/TestLinkHandling.java b/repository/repository-derby/src/test/java/org/apache/sqoop/repository/derby/TestLinkHandling.java index 37343d3..dabb08b 100644 --- a/repository/repository-derby/src/test/java/org/apache/sqoop/repository/derby/TestLinkHandling.java +++ b/repository/repository-derby/src/test/java/org/apache/sqoop/repository/derby/TestLinkHandling.java @@ -58,7 +58,7 @@ public class TestLinkHandling extends DerbyTestCase { try { handler.findLink(1, getDerbyDatabaseConnection()); fail(); - } catch(SqoopException ex) { + } catch (SqoopException ex) { assertEquals(DerbyRepoError.DERBYREPO_0024, ex.getErrorCode()); } @@ -81,6 +81,28 @@ public class TestLinkHandling extends DerbyTestCase { } @Test + public void testFindLinkByName() throws Exception { + // Let's try to find non existing link + assertNull(handler.findLink("non-existing", getDerbyDatabaseConnection())); + // Load prepared connections into database + loadLinksForLatestVersion(); + + MLink linkA = handler.findLink("CA", getDerbyDatabaseConnection()); + assertNotNull(linkA); + assertEquals(1, linkA.getPersistenceId()); + assertEquals("CA", linkA.getName()); + + List<MConfig> configs; + + // Check connector link config + configs = linkA.getConnectorLinkConfig().getConfigs(); + assertEquals("Value1", configs.get(0).getInputs().get(0).getValue()); + assertNull(configs.get(0).getInputs().get(1).getValue()); + assertEquals("Value3", configs.get(1).getInputs().get(0).getValue()); + assertNull(configs.get(1).getInputs().get(1).getValue()); + } + + @Test public void testFindLinks() throws Exception { List<MLink> list; @@ -146,7 +168,7 @@ public class TestLinkHandling extends DerbyTestCase { assertCountForTable("SQOOP.SQ_LINK_INPUT", 4); } - @Test(expected=SqoopException.class) + @Test(expected = SqoopException.class) public void testCreateDuplicateLink() throws Exception { MLink link = getLink(); fillLink(link); @@ -178,10 +200,10 @@ public class TestLinkHandling extends DerbyTestCase { List<MConfig> configs; configs = link.getConnectorLinkConfig().getConfigs(); - ((MStringInput)configs.get(0).getInputs().get(0)).setValue("Updated"); - ((MMapInput)configs.get(0).getInputs().get(1)).setValue(null); - ((MStringInput)configs.get(1).getInputs().get(0)).setValue("Updated"); - ((MMapInput)configs.get(1).getInputs().get(1)).setValue(null); + ((MStringInput) configs.get(0).getInputs().get(0)).setValue("Updated"); + ((MMapInput) configs.get(0).getInputs().get(1)).setValue(null); + ((MStringInput) configs.get(1).getInputs().get(0)).setValue("Updated"); + ((MMapInput) configs.get(1).getInputs().get(1)).setValue(null); link.setName("name"); http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java index fdb7c26..5547988 100644 --- a/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java +++ b/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java @@ -41,9 +41,7 @@ import org.apache.sqoop.repository.RepositoryManager; import org.apache.sqoop.server.RequestContext; import org.apache.sqoop.server.RequestHandler; import org.apache.sqoop.server.common.ServerError; -import org.apache.sqoop.utils.ClassUtils; import org.apache.sqoop.validation.ConfigValidationResult; -import org.apache.sqoop.validation.ConfigValidationRunner; import org.apache.sqoop.validation.Status; import org.json.simple.JSONObject; import org.json.simple.JSONValue; http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/handler/LinkRequestHandler.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/handler/LinkRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/LinkRequestHandler.java index 823426a..35a9635 100644 --- a/server/src/main/java/org/apache/sqoop/handler/LinkRequestHandler.java +++ b/server/src/main/java/org/apache/sqoop/handler/LinkRequestHandler.java @@ -18,6 +18,7 @@ package org.apache.sqoop.handler; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -28,6 +29,7 @@ import org.apache.sqoop.connector.ConnectorManager; import org.apache.sqoop.connector.spi.SqoopConnector; import org.apache.sqoop.json.JsonBean; import org.apache.sqoop.json.LinkBean; +import org.apache.sqoop.json.LinksBean; import org.apache.sqoop.json.ValidationResultBean; import org.apache.sqoop.model.ConfigUtils; import org.apache.sqoop.model.MLink; @@ -37,48 +39,19 @@ import org.apache.sqoop.repository.RepositoryManager; import org.apache.sqoop.server.RequestContext; import org.apache.sqoop.server.RequestHandler; import org.apache.sqoop.server.common.ServerError; -import org.apache.sqoop.utils.ClassUtils; -import org.apache.sqoop.validation.Status; import org.apache.sqoop.validation.ConfigValidationResult; -import org.apache.sqoop.validation.ConfigValidationRunner; import org.json.simple.JSONObject; import org.json.simple.JSONValue; -/** - * Connection request handler is supporting following resources: - * - * GET /v1/link/:xid - * Return details about one particular link with id :xid or about all of - * them if :xid equals to "all". - * - * POST /v1/link - * Create new link - * - * PUT /v1/link/:xid - * Update link with id :xid. - * - * PUT /v1/link/:xid/enable - * Enable link with id :xid - * - * PUT /v1/link/:xid/disable - * Disable link with id :xid - * - * DELETE /v1/link/:xid - * Remove link with id :xid - * - * Planned resources: - * - * GET /v1/link - * Get brief list of all links present in the system. - * - */ public class LinkRequestHandler implements RequestHandler { - private static final Logger LOG = - Logger.getLogger(LinkRequestHandler.class); + private static final Logger LOG = Logger.getLogger(LinkRequestHandler.class); - private static final String ENABLE = "enable"; - private static final String DISABLE = "disable"; + static final String ENABLE = "enable"; + static final String DISABLE = "disable"; + static final String LINKS_PATH = "links"; + static final String LINK_PATH = "link"; + static final String CONNECTOR_NAME_QUERY_PARAM = "cname"; public LinkRequestHandler() { LOG.info("LinkRequestHandler initialized"); @@ -87,163 +60,203 @@ public class LinkRequestHandler implements RequestHandler { @Override public JsonBean handleEvent(RequestContext ctx) { switch (ctx.getMethod()) { - case GET: - return getLink(ctx); - case POST: - return createUpdateLink(ctx, false); - case PUT: - if (ctx.getLastURLElement().equals(ENABLE)) { - return enableLink(ctx, true); - } else if (ctx.getLastURLElement().equals(DISABLE)) { - return enableLink(ctx, false); - } else { - return createUpdateLink(ctx, true); - } - case DELETE: - return deleteLink(ctx); + case GET: + return getLinks(ctx); + case POST: + return createUpdateLink(ctx, true); + case PUT: + if (ctx.getLastURLElement().equals(ENABLE)) { + return enableLink(ctx, true); + } else if (ctx.getLastURLElement().equals(DISABLE)) { + return enableLink(ctx, false); + } else { + return createUpdateLink(ctx, false); + } + case DELETE: + return deleteLink(ctx); } return null; } /** - * Delete link from thes repository. + * Delete link in the repository. * * @param ctx Context object * @return Empty bean */ private JsonBean deleteLink(RequestContext ctx) { - String sxid = ctx.getLastURLElement(); - long xid = Long.valueOf(sxid); - - AuditLoggerManager.getInstance() - .logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), - "delete", "link", sxid); - Repository repository = RepositoryManager.getInstance().getRepository(); - repository.deleteLink(xid); + String linkIdentifier = ctx.getLastURLElement(); + // support linkName or linkId for the api + long linkId = getLinkIdFromIdentifier(linkIdentifier, repository); + + AuditLoggerManager.getInstance().logAuditEvent(ctx.getUserName(), + ctx.getRequest().getRemoteAddr(), "delete", "link", linkIdentifier); + repository.deleteLink(linkId); return JsonBean.EMPTY_BEAN; } /** - * Update or create link in repository. + * Create or Update link in repository. * * @param ctx Context object * @return Validation bean object */ - private JsonBean createUpdateLink(RequestContext ctx, boolean update) { + private JsonBean createUpdateLink(RequestContext ctx, boolean create) { + + Repository repository = RepositoryManager.getInstance().getRepository(); String username = ctx.getUserName(); - LinkBean bean = new LinkBean(); + LinkBean linkBean = new LinkBean(); try { - JSONObject json = - (JSONObject) JSONValue.parse(ctx.getRequest().getReader()); - - bean.restore(json); + JSONObject postData = (JSONObject) JSONValue.parse(ctx.getRequest().getReader()); + linkBean.restore(postData); } catch (IOException e) { - throw new SqoopException(ServerError.SERVER_0003, - "Can't read request content", e); + throw new SqoopException(ServerError.SERVER_0003, "Can't read request content", e); } // Get link object - List<MLink> links = bean.getLinks(); - - if(links.size() != 1) { + List<MLink> links = linkBean.getLinks(); + if (links.size() != 1) { throw new SqoopException(ServerError.SERVER_0003, - "Expected one link but got " + links.size()); + "Expected one link while parsing JSON request but got " + links.size()); } MLink link = links.get(0); - - // Verify that user is not trying to spoof us - MLinkConfig linkConfig = - ConnectorManager.getInstance().getConnectorConfigurable(link.getConnectorId()) - .getLinkConfig(); - if(!linkConfig.equals(link.getConnectorLinkConfig())) { - throw new SqoopException(ServerError.SERVER_0003, - "Detected incorrect config structure"); + MLinkConfig linkConfig = ConnectorManager.getInstance() + .getConnectorConfigurable(link.getConnectorId()).getLinkConfig(); + if (!linkConfig.equals(link.getConnectorLinkConfig())) { + throw new SqoopException(ServerError.SERVER_0003, "Detected incorrect link config structure"); } + // if update get the link id from the request URI + if (!create) { + String linkIdentifier = ctx.getLastURLElement(); + // support linkName or linkId for the api + long linkId = getLinkIdFromIdentifier(linkIdentifier, repository); + MLink existingLink = repository.findLink(linkId); + link.setConnectorId(existingLink.getConnectorId()); + } + // Associated connector for this link + SqoopConnector connector = ConnectorManager.getInstance().getSqoopConnector( + link.getConnectorId()); - // Responsible connector for this session - SqoopConnector connector = ConnectorManager.getInstance().getSqoopConnector(link.getConnectorId()); - - // Validate user supplied data - ConfigValidationResult connectorLinkValidation = ConfigUtils.validateConfigs( - link.getConnectorLinkConfig().getConfigs(), - connector.getLinkConfigurationClass() - ); - - // Return back validations in all cases - ValidationResultBean outputBean = new ValidationResultBean(connectorLinkValidation); + // Validate user supplied config data + ConfigValidationResult connectorLinkConfigValidation = ConfigUtils.validateConfigs(link + .getConnectorLinkConfig().getConfigs(), connector.getLinkConfigurationClass()); + // Return back link validation result bean + ValidationResultBean linkValidationBean = new ValidationResultBean( + connectorLinkConfigValidation); // If we're good enough let's perform the action - if(connectorLinkValidation.getStatus().canProceed()) { - if(update) { - AuditLoggerManager.getInstance() - .logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), - "update", "link", String.valueOf(link.getPersistenceId())); - + if (connectorLinkConfigValidation.getStatus().canProceed()) { + if (create) { + AuditLoggerManager.getInstance().logAuditEvent(ctx.getUserName(), + ctx.getRequest().getRemoteAddr(), "create", "link", + String.valueOf(link.getPersistenceId())); + link.setCreationUser(username); link.setLastUpdateUser(username); - RepositoryManager.getInstance().getRepository().updateLink(link); + repository.createLink(link); + linkValidationBean.setId(link.getPersistenceId()); } else { - link.setCreationUser(username); + AuditLoggerManager.getInstance().logAuditEvent(ctx.getUserName(), + ctx.getRequest().getRemoteAddr(), "update", "link", + String.valueOf(link.getPersistenceId())); link.setLastUpdateUser(username); - RepositoryManager.getInstance().getRepository().createLink(link); - outputBean.setId(link.getPersistenceId()); - - AuditLoggerManager.getInstance() - .logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), - "create", "link", String.valueOf(link.getPersistenceId())); + repository.updateLink(link); } } - return outputBean; + return linkValidationBean; } - private JsonBean getLink(RequestContext ctx) { - String sxid = ctx.getLastURLElement(); - LinkBean bean; - - AuditLoggerManager.getInstance() - .logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), - "get", "link", sxid); - + private JsonBean getLinks(RequestContext ctx) { + String identifier = ctx.getLastURLElement(); + LinkBean linkBean; Locale locale = ctx.getAcceptLanguageHeader(); Repository repository = RepositoryManager.getInstance().getRepository(); - if (sxid.equals("all")) { - - List<MLink> links = repository.findLinks(); - bean = new LinkBean(links); - - // Add associated resources into the bean - for( MLink link : links) { - long connectorId = link.getConnectorId(); - if(!bean.hasConnectorConfigBundle(connectorId)) { - bean.addConnectorConfigBundle(connectorId, - ConnectorManager.getInstance().getResourceBundle(connectorId, locale)); - } + // links by connector + if (ctx.getParameterValue(CONNECTOR_NAME_QUERY_PARAM) != null) { + identifier = ctx.getParameterValue(CONNECTOR_NAME_QUERY_PARAM); + AuditLoggerManager.getInstance().logAuditEvent(ctx.getUserName(), + ctx.getRequest().getRemoteAddr(), "get", "linksByConnector", identifier); + if (repository.findConnector(identifier) != null) { + long connectorId = repository.findConnector(identifier).getPersistenceId(); + linkBean = createLinksBean(repository.findLinksForConnector(connectorId), locale); + } else { + // this means name nor Id existed + throw new SqoopException(ServerError.SERVER_0005, "Invalid connector: " + identifier + + " name for links given"); } + } else + // all links in the system + if (ctx.getPath().contains(LINKS_PATH) + || (ctx.getPath().contains(LINK_PATH) && identifier.equals("all"))) { + AuditLoggerManager.getInstance().logAuditEvent(ctx.getUserName(), + ctx.getRequest().getRemoteAddr(), "get", "links", "all"); + linkBean = createLinksBean(repository.findLinks(), locale); + } + // link by Id + else { + AuditLoggerManager.getInstance().logAuditEvent(ctx.getUserName(), + ctx.getRequest().getRemoteAddr(), "get", "link", identifier); + + long linkId = getLinkIdFromIdentifier(identifier, repository); + List<MLink> linkList = new ArrayList<MLink>(); + // a list of single element + linkList.add(repository.findLink(linkId)); + linkBean = createLinkBean(linkList, locale); + } + return linkBean; + } + + private long getLinkIdFromIdentifier(String identifier, Repository repository) { + // support linkName or linkId for the api + long linkId; + if (repository.findLink(identifier) != null) { + linkId = repository.findLink(identifier).getPersistenceId(); } else { - long xid = Long.valueOf(sxid); + try { + linkId = Long.valueOf(identifier); + } catch (NumberFormatException ex) { + // this means name nor Id existed + throw new SqoopException(ServerError.SERVER_0005, "Invalid link: " + identifier + + " requested"); + } + } + return linkId; + } - MLink link = repository.findLink(xid); - long connectorId = link.getConnectorId(); + private LinkBean createLinkBean(List<MLink> links, Locale locale) { + LinkBean linkBean = new LinkBean(links); + addLink(links, locale, linkBean); + return linkBean; + } - bean = new LinkBean(link); + private LinksBean createLinksBean(List<MLink> links, Locale locale) { + LinksBean linksBean = new LinksBean(links); + addLink(links, locale, linksBean); + return linksBean; + } - bean.addConnectorConfigBundle(connectorId, - ConnectorManager.getInstance().getResourceBundle(connectorId, locale)); + private void addLink(List<MLink> links, Locale locale, LinkBean bean) { + // Add associated resources into the bean + for (MLink link : links) { + long connectorId = link.getConnectorId(); + if (!bean.hasConnectorConfigBundle(connectorId)) { + bean.addConnectorConfigBundle(connectorId, ConnectorManager.getInstance() + .getResourceBundle(connectorId, locale)); + } } - return bean; } private JsonBean enableLink(RequestContext ctx, boolean enabled) { - String[] elements = ctx.getUrlElements(); - String sLinkId = elements[elements.length - 2]; - long linkId = Long.valueOf(sLinkId); Repository repository = RepositoryManager.getInstance().getRepository(); + String[] elements = ctx.getUrlElements(); + String linkIdentifier = elements[elements.length - 2]; + long linkId = getLinkIdFromIdentifier(linkIdentifier, repository); repository.enableLink(linkId, enabled); return JsonBean.EMPTY_BEAN; } http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/server/RequestContext.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/RequestContext.java b/server/src/main/java/org/apache/sqoop/server/RequestContext.java index b1a74fc..54e9cca 100644 --- a/server/src/main/java/org/apache/sqoop/server/RequestContext.java +++ b/server/src/main/java/org/apache/sqoop/server/RequestContext.java @@ -93,6 +93,14 @@ public class RequestContext { } /** + * Return a value for given query parameter name + */ + public String getParameterValue(String name) { + String[] values = getRequest().getParameterValues(name); + return values != null ? values[0] : null; + } + + /** * Get locale specified in accept-language HTTP header. * * @return First specified locale http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/server/common/ServerError.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/common/ServerError.java b/server/src/main/java/org/apache/sqoop/server/common/ServerError.java index 02d9174..c68ab57 100644 --- a/server/src/main/java/org/apache/sqoop/server/common/ServerError.java +++ b/server/src/main/java/org/apache/sqoop/server/common/ServerError.java @@ -36,6 +36,9 @@ public enum ServerError implements ErrorCode { /** Invalid argument in HTTP request */ SERVER_0004("Invalid argument in HTTP request"), + /** Invalid entity requested */ + SERVER_0005("Invalid entity requested"), + ; private final String message; http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/server/v1/ConnectorServlet.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/v1/ConnectorServlet.java b/server/src/main/java/org/apache/sqoop/server/v1/ConnectorServlet.java index 781abc3..2bc06ac 100644 --- a/server/src/main/java/org/apache/sqoop/server/v1/ConnectorServlet.java +++ b/server/src/main/java/org/apache/sqoop/server/v1/ConnectorServlet.java @@ -25,7 +25,7 @@ import org.apache.sqoop.server.SqoopProtocolServlet; /** - * Connector request handler is supporting following resources: + * Displays connector(s) registered in sqoop * * GET v1/connector/all (remains for backward compatibility) * Return all connectors registered in the sqoop system with their corresponding config params http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/server/v1/DriverServlet.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/v1/DriverServlet.java b/server/src/main/java/org/apache/sqoop/server/v1/DriverServlet.java index 43454fd..192d866 100644 --- a/server/src/main/java/org/apache/sqoop/server/v1/DriverServlet.java +++ b/server/src/main/java/org/apache/sqoop/server/v1/DriverServlet.java @@ -24,7 +24,7 @@ import org.apache.sqoop.server.RequestHandler; import org.apache.sqoop.server.SqoopProtocolServlet; /** - * Driver request handler is supporting following resources: + * Displays driver registered in sqoop * * GET /v1/driver/ * Return details about the registered driver and its configs http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/server/v1/LinkServlet.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/v1/LinkServlet.java b/server/src/main/java/org/apache/sqoop/server/v1/LinkServlet.java index 20e5009..127903a 100644 --- a/server/src/main/java/org/apache/sqoop/server/v1/LinkServlet.java +++ b/server/src/main/java/org/apache/sqoop/server/v1/LinkServlet.java @@ -24,6 +24,33 @@ import org.apache.sqoop.server.RequestHandler; import org.apache.sqoop.server.SqoopProtocolServlet; /** + * Provides operations for link resource + * + * GET /v1/link/{lid} + * Return details about one particular link with id :lid + * GET /v1/link/{lname} + * Return details about one particular link with name :lname + * + * POST /v1/link/ with {connector-id} and {link-config-id} in the post data + * Create link for connector with id connector-id + * PUT /v1/link/ with {connector-id} and {link-config-id} in the post data + * Edit/Update link for connector with id connector-id + + * PUT /v1/link/{lid} + * Edit/Update details about one particular link with id :lid + * PUT /v1/link/{lname} + * Edit/Update details about one particular link with name :lname + * + * DELETE /v1/link/{lid} + * Delete/Remove one particular link with id :lid + * DELETE /v1/link/{lname} + * Delete/Remove one particular link with name :lname + * + * PUT /v1/link/{lname}/enable + * Enable link with id :lname + * + * PUT /v1/link/{lname}/disable + * Disable link with id :lname * */ @SuppressWarnings("serial") http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/java/org/apache/sqoop/server/v1/LinksServlet.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/v1/LinksServlet.java b/server/src/main/java/org/apache/sqoop/server/v1/LinksServlet.java new file mode 100644 index 0000000..d249d6c --- /dev/null +++ b/server/src/main/java/org/apache/sqoop/server/v1/LinksServlet.java @@ -0,0 +1,48 @@ +/** + * 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.server.v1; + +import org.apache.sqoop.handler.LinkRequestHandler; +import org.apache.sqoop.json.JsonBean; +import org.apache.sqoop.server.RequestContext; +import org.apache.sqoop.server.RequestHandler; +import org.apache.sqoop.server.SqoopProtocolServlet; + +/** + * Displays all or links per connector in sqoop + * + * GET /v1/links + * Return details about every link that exists in the sqoop system + * GET /v1/links?cname= + * Return details about link(s) for a given connector name {cname} +*/ +@SuppressWarnings("serial") +public class LinksServlet extends SqoopProtocolServlet { + + private RequestHandler linkRequestHandler; + + public LinksServlet() { + linkRequestHandler = new LinkRequestHandler(); + } + + @Override + protected JsonBean handleGetRequest(RequestContext ctx) throws Exception { + return linkRequestHandler.handleEvent(ctx); + } + +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/server/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml index a6f7b0d..6ad90d2 100644 --- a/server/src/main/webapp/WEB-INF/web.xml +++ b/server/src/main/webapp/WEB-INF/web.xml @@ -99,6 +99,18 @@ limitations under the License. <url-pattern>/v1/link/*</url-pattern> </servlet-mapping> + <!-- Links servlet --> + <servlet> + <servlet-name>v1.LinksServlet</servlet-name> + <servlet-class>org.apache.sqoop.server.v1.LinksServlet</servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> + + <servlet-mapping> + <servlet-name>v1.LinksServlet</servlet-name> + <url-pattern>/v1/links/*</url-pattern> + </servlet-mapping> + <!-- Job servlet --> <servlet> <servlet-name>v1.JobServlet</servlet-name> http://git-wip-us.apache.org/repos/asf/sqoop/blob/eed2b3f5/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java b/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java index d5ead38..176833a 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java @@ -60,6 +60,7 @@ public class UpdateLinkFunction extends SqoopFunction { ConsoleReader reader = new ConsoleReader(); + // TODO: why do we need 2 http calls for update? MLink link = client.getLink(linkId); ResourceBundle connectorLinkConfigBundle = client.getConnectorConfigBundle(link.getConnectorId());
