diff --git a/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java b/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java new file mode 100644 index 00000000..6e632d4f --- /dev/null +++ b/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java @@ -0,0 +1,91 @@ +/** + * 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.client.display; + +import org.apache.sqoop.model.MForm; +import org.apache.sqoop.model.MFramework; +import org.apache.sqoop.model.MInput; +import org.apache.sqoop.model.MInputType; +import org.apache.sqoop.model.MJobForms; +import org.apache.sqoop.model.MStringInput; +import org.codehaus.groovy.tools.shell.IO; + +import java.util.Iterator; +import java.util.List; + +/** + * Convenience static methods for displaying form related information + */ +public class FormDisplayer { + + public static void displayFormDetails(IO io, MFramework framework) { + io.out.print(" Supported job types: "); + io.out.println(framework.getAllJobsForms().keySet().toString()); + + displayForms(io, framework.getConnectionForms().getForms(), "Connection"); + + for (MJobForms jobForms : framework.getAllJobsForms().values()) { + io.out.print(" Forms for job type "); + io.out.print(jobForms.getType().name()); + io.out.println(":"); + + displayForms(io, jobForms.getForms(), "Job"); + } + } + + public static void displayForms(IO io, List forms, String type) { + Iterator fiter = forms.iterator(); + int findx = 1; + while (fiter.hasNext()) { + io.out.print(" "); + io.out.print(type); + io.out.print(" form "); + io.out.print(findx++); + io.out.println(":"); + + MForm form = fiter.next(); + io.out.print(" Name: "); + io.out.println(form.getName()); + + List> inputs = form.getInputs(); + Iterator> iiter = inputs.iterator(); + int iindx = 1; + while (iiter.hasNext()) { + io.out.print(" Input "); + io.out.print(iindx++); + io.out.println(":"); + + MInput input = iiter.next(); + io.out.print(" Name: "); + io.out.println(input.getName()); + io.out.print(" Type: "); + io.out.println(input.getType()); + if (input.getType() == MInputType.STRING) { + io.out.print(" Mask: "); + io.out.println(((MStringInput)input).isMasked()); + io.out.print(" Size: "); + io.out.println(((MStringInput)input).getMaxLength()); + } + } + } + } + + private FormDisplayer() { + // Do not instantiate + } +} diff --git a/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java b/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java new file mode 100644 index 00000000..c9ae901e --- /dev/null +++ b/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java @@ -0,0 +1,38 @@ +/** + * 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.client.request; + +import org.apache.sqoop.json.FrameworkBean; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; + +/** + * + */ +public class FrameworkRequest extends Request { + public FrameworkBean doGet(String serverUrl) { + String response = null; + response = super.get(serverUrl + "v1/framework"); + JSONObject jsonObject = (JSONObject) JSONValue.parse(response); + + FrameworkBean frameworkBean = new FrameworkBean(); + frameworkBean.restore(jsonObject); + + return frameworkBean; + } +} diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java new file mode 100644 index 00000000..bcb267e6 --- /dev/null +++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java @@ -0,0 +1,80 @@ +/** + * 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.client.shell; + +import org.apache.sqoop.client.core.Environment; +import org.apache.sqoop.client.request.FrameworkRequest; +import org.apache.sqoop.json.FrameworkBean; +import org.apache.sqoop.model.MFramework; +import org.apache.sqoop.model.MJobForms; +import org.codehaus.groovy.tools.shell.IO; + +import java.io.PrintWriter; +import java.util.List; + +import static org.apache.sqoop.client.display.FormDisplayer.*; + +/** + * + */ +public class ShowFrameworkFunction extends SqoopFunction { + + private IO io; + private FrameworkRequest frameworkRequest; + + @SuppressWarnings("static-access") + protected ShowFrameworkFunction(IO io) { + this.io = io; + } + + public void printHelp(PrintWriter out) { + out.println("Usage: show framework"); + super.printHelp(out); + } + + public Object execute(List args) { + if (args.size() != 1) { + printHelp(io.out); + io.out.println(); + return null; + } + + showFramework(); + + return null; + } + + private void showFramework() { + if (frameworkRequest == null) { + frameworkRequest = new FrameworkRequest(); + } + + FrameworkBean frameworkBean = + frameworkRequest.doGet(Environment.getServerUrl()); + MFramework framework = frameworkBean.getFramework(); + + io.out.println("@|bold Framework specific options: |@"); + + io.out.print("Persistent id: "); + io.out.println(framework.getPersistenceId()); + + displayFormDetails(io, framework); + + io.out.println(); + } +} diff --git a/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java b/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java new file mode 100644 index 00000000..47295e05 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java @@ -0,0 +1,99 @@ +/** + * 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 org.apache.sqoop.model.MConnectionForms; +import org.apache.sqoop.model.MForm; +import org.apache.sqoop.model.MFramework; +import org.apache.sqoop.model.MJob; +import org.apache.sqoop.model.MJobForms; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.sqoop.json.util.FormSerialization.*; + +/** + * + */ +public class FrameworkBean implements JsonBean { + + + private MFramework framework; + + // for "extract" + public FrameworkBean(MFramework framework) { + this.framework = framework; + } + + // for "restore" + public FrameworkBean() { + } + + public MFramework getFramework() { + return framework; + } + + @SuppressWarnings("unchecked") + @Override + public JSONObject extract() { + JSONArray conForms = + extractForms(framework.getConnectionForms().getForms()); + JSONObject jobForms = new JSONObject(); + + for (MJobForms job : framework.getAllJobsForms().values()) { + jobForms.put(job.getType().name(), extractForms(job.getForms())); + } + + JSONObject result = new JSONObject(); + result.put(ID, framework.getPersistenceId()); + result.put(CON_FORMS, conForms); + result.put(JOB_FORMS, jobForms); + return result; + } + + + @Override + @SuppressWarnings("unchecked") + public void restore(JSONObject jsonObject) { + long id = (Long) jsonObject.get(ID); + + List connForms = restoreForms((JSONArray) jsonObject.get(CON_FORMS)); + + JSONObject jobForms = (JSONObject) jsonObject.get(JOB_FORMS); + + List jobs = new ArrayList(); + for( Map.Entry entry : (Set) jobForms.entrySet()) { + //TODO(jarcec): Handle situation when server is supporting operation + // that client do not know (server do have newer version than client) + MJob.Type type = MJob.Type.valueOf((String) entry.getKey()); + + List job = restoreForms((JSONArray) entry.getValue()); + + jobs.add(new MJobForms(type, job)); + } + + framework = new MFramework(new MConnectionForms(connForms), jobs); + framework.setPersistenceId(id); + } + +} diff --git a/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java b/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java new file mode 100644 index 00000000..ba9cf022 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java @@ -0,0 +1,154 @@ +/** + * 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.util; + +import org.apache.sqoop.model.MForm; +import org.apache.sqoop.model.MFormType; +import org.apache.sqoop.model.MInput; +import org.apache.sqoop.model.MInputType; +import org.apache.sqoop.model.MMapInput; +import org.apache.sqoop.model.MStringInput; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Convenient static methods for serializing forms. + */ +public class FormSerialization { + + public static final String ID = "id"; + public static final String NAME = "name"; + public static final String CLASS = "class"; + public static final String CON_FORMS = "con_forms"; + public static final String JOB_FORMS = "job_forms"; + + public static final String FORM_NAME = "name"; + public static final String FORM_TYPE = "type"; + public static final String FORM_INPUTS = "inputs"; + public static final String FORM_INPUT_NAME = "name"; + public static final String FORM_INPUT_TYPE = "type"; + public static final String FORM_INPUT_MASK = "mask"; + public static final String FORM_INPUT_SIZE = "size"; + + /** + * Transform given list of forms to JSON Array object. + * + * @param mForms List of forms. + * @return JSON object with serialized form of the list. + */ + @SuppressWarnings("unchecked") + public static JSONArray extractForms(List mForms) { + JSONArray forms = new JSONArray(); + + for (MForm mForm : mForms) { + forms.add(extractForm(mForm)); + } + + return forms; + } + + /** + * Transform given form to JSON Object. + * + * @param mForm Given MForm instance + * @return Serialized JSON object. + */ + @SuppressWarnings("unchecked") + public static JSONObject extractForm(MForm mForm) { + JSONObject form = new JSONObject(); + form.put(FORM_NAME, mForm.getName()); + form.put(FORM_TYPE, MFormType.CONNECTION.toString()); + JSONArray mInputs = new JSONArray(); + form.put(FORM_INPUTS, mInputs); + + for (MInput mInput : mForm.getInputs()) { + JSONObject input = new JSONObject(); + mInputs.add(input); + + input.put(FORM_INPUT_NAME, mInput.getName()); + input.put(FORM_INPUT_TYPE, mInput.getType().toString()); + if (mInput.getType() == MInputType.STRING) { + input.put(FORM_INPUT_MASK, + ((MStringInput)mInput).isMasked()); + input.put(FORM_INPUT_SIZE, + ((MStringInput)mInput).getMaxLength()); + } + } + + return form; + } + + /** + * Restore List of MForms from JSON Array. + * + * @param forms JSON array representing list of MForms + * @return Restored list of MForms + */ + public static List restoreForms(JSONArray forms) { + List mForms = new ArrayList(); + + for (int i = 0; i < forms.size(); i++) { + mForms.add(restoreForm((JSONObject) forms.get(i))); + } + + return mForms; + } + + /** + * Restore one MForm from JSON Object. + * + * @param form JSON representation of the MForm. + * @return Restored MForm. + */ + public static MForm restoreForm(JSONObject form) { + JSONArray inputs = (JSONArray) form.get(FORM_INPUTS); + + List> mInputs = new ArrayList>(); + for (int i = 0; i < inputs.size(); i++) { + JSONObject input = (JSONObject) inputs.get(i); + MInputType type = + MInputType.valueOf((String) input.get(FORM_INPUT_TYPE)); + switch (type) { + case STRING: { + String name = (String) input.get(FORM_INPUT_NAME); + boolean mask = (Boolean) input.get(FORM_INPUT_MASK); + long size = (Long) input.get(FORM_INPUT_SIZE); + MInput mInput = new MStringInput(name, mask, (short) size); + mInputs.add(mInput); + break; + } + case MAP: { + String name = (String) input.get(FORM_INPUT_NAME); + MInput> mInput = new MMapInput(name); + mInputs.add(mInput); + break; + } + } + } + + return new MForm((String) form.get(FORM_NAME), mInputs); + } + + private FormSerialization() { + // Do not instantiate + } +} diff --git a/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java b/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java new file mode 100644 index 00000000..50044d93 --- /dev/null +++ b/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java @@ -0,0 +1,98 @@ +/** + * 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 org.apache.sqoop.model.MConnectionForms; +import org.apache.sqoop.model.MForm; +import org.apache.sqoop.model.MFramework; +import org.apache.sqoop.model.MInput; +import org.apache.sqoop.model.MJob; +import org.apache.sqoop.model.MJobForms; +import org.apache.sqoop.model.MMapInput; +import org.apache.sqoop.model.MStringInput; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +/** + * + */ +public class TestFrameworkBean { + + /** + * Test that by JSON serialization followed by deserialization we will get + * equal framework object. + */ + @Test + public void testSerialization() { + MFramework framework = getFramework("1"); + // Serialize it to JSON object + FrameworkBean bean = new FrameworkBean(framework); + JSONObject json = bean.extract(); + + // "Move" it across network in text form + String string = json.toJSONString(); + + // Retrieved transferred object + JSONObject retrievedJson = (JSONObject) JSONValue.parse(string); + FrameworkBean retrievedBean = new FrameworkBean(); + retrievedBean.restore(retrievedJson); + + assertEquals(framework, retrievedBean.getFramework()); + } + + public MFramework getFramework(String parameter) { + List> inputs; + + List connectionForms = new ArrayList(); + inputs = new ArrayList>(); + inputs.add(new MStringInput("url", false, (short) 10)); + inputs.add(new MStringInput("username", false, (short) 10)); + inputs.add(new MStringInput("password", false, (short) 10)); + connectionForms.add(new MForm("connection", inputs)); + + inputs = new ArrayList>(); + inputs.add(new MMapInput("properties")); + connectionForms.add(new MForm("properties", inputs)); + MConnectionForms connection = new MConnectionForms(connectionForms); + + List jobForms = new ArrayList(); + inputs = new ArrayList>(); + inputs.add(new MStringInput("A", false, (short) 10)); + inputs.add(new MStringInput("B", false, (short) 10)); + inputs.add(new MStringInput("C", false, (short) 10)); + jobForms.add((new MForm("D", inputs))); + + inputs = new ArrayList>(); + inputs.add(new MStringInput("Z", false, (short) 10)); + inputs.add(new MStringInput("X", false, (short) 10)); + inputs.add(new MStringInput("Y", false, (short) 10)); + jobForms.add(new MForm("D", inputs)); + + List jobs = new ArrayList(); + jobs.add(new MJobForms(MJob.Type.IMPORT, jobForms)); + + return new MFramework(connection, jobs); + } + +} diff --git a/server/src/main/java/org/apache/sqoop/handler/FrameworkRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/FrameworkRequestHandler.java new file mode 100644 index 00000000..1041e71c --- /dev/null +++ b/server/src/main/java/org/apache/sqoop/handler/FrameworkRequestHandler.java @@ -0,0 +1,44 @@ +/** + * 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.handler; + +import org.apache.log4j.Logger; +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.framework.FrameworkManager; +import org.apache.sqoop.json.FrameworkBean; +import org.apache.sqoop.json.JsonBean; +import org.apache.sqoop.server.RequestContext; +import org.apache.sqoop.server.RequestHandler; + +/** + * + */ +public class FrameworkRequestHandler implements RequestHandler { + + private static final Logger LOG = + Logger.getLogger(ConnectorRequestHandler.class); + + public FrameworkRequestHandler() { + LOG.info("FrameworkRequestHandler initialized"); + } + + @Override + public JsonBean handleEvent(RequestContext ctx) throws SqoopException { + return new FrameworkBean(FrameworkManager.getFramework()); + } +} diff --git a/server/src/main/java/org/apache/sqoop/server/v1/FrameworkServlet.java b/server/src/main/java/org/apache/sqoop/server/v1/FrameworkServlet.java new file mode 100644 index 00000000..9c997314 --- /dev/null +++ b/server/src/main/java/org/apache/sqoop/server/v1/FrameworkServlet.java @@ -0,0 +1,40 @@ +/** + * 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.FrameworkRequestHandler; +import org.apache.sqoop.json.JsonBean; +import org.apache.sqoop.server.RequestContext; +import org.apache.sqoop.server.RequestHandler; +import org.apache.sqoop.server.SqoopProtocolServlet; + +/** + * Get framework metadata + */ +public class FrameworkServlet extends SqoopProtocolServlet { + private RequestHandler frameworkRequestHandler; + + public FrameworkServlet() { + frameworkRequestHandler = new FrameworkRequestHandler(); + } + + @Override + protected JsonBean handleGetRequest(RequestContext ctx) throws Exception { + return frameworkRequestHandler.handleEvent(ctx); + } +}