SQOOP-931: Integrate HCatalog with Sqoop
[sqoop.git] / src / java / org / apache / sqoop / tool / CodeGenTool.java
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.sqoop.tool;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.commons.cli.CommandLine;
26 import org.apache.commons.cli.OptionBuilder;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.util.StringUtils;
30
31 import com.cloudera.sqoop.Sqoop;
32 import com.cloudera.sqoop.SqoopOptions;
33 import com.cloudera.sqoop.SqoopOptions.InvalidOptionsException;
34 import com.cloudera.sqoop.cli.RelatedOptions;
35 import com.cloudera.sqoop.cli.ToolOptions;
36 import com.cloudera.sqoop.hive.HiveImport;
37 import com.cloudera.sqoop.orm.ClassWriter;
38 import com.cloudera.sqoop.orm.CompilationManager;
39
40 /**
41 * Tool that generates code from a database schema.
42 */
43 public class CodeGenTool extends com.cloudera.sqoop.tool.BaseSqoopTool {
44
45 public static final Log LOG = LogFactory.getLog(CodeGenTool.class.getName());
46
47 private List<String> generatedJarFiles;
48
49 public CodeGenTool() {
50 super("codegen");
51 generatedJarFiles = new ArrayList<String>();
52 }
53
54 /**
55 * @return a list of jar files generated as part of this import process
56 */
57 public List<String> getGeneratedJarFiles() {
58 ArrayList<String> out = new ArrayList<String>(generatedJarFiles);
59 return out;
60 }
61
62 /**
63 * Generate the .class and .jar files.
64 * @return the filename of the emitted jar file.
65 * @throws IOException
66 */
67 public String generateORM(SqoopOptions options, String tableName)
68 throws IOException {
69 String existingJar = options.getExistingJarName();
70 if (existingJar != null) {
71 // This code generator is being invoked as part of an import or export
72 // process, and the user has pre-specified a jar and class to use.
73 // Don't generate.
74 if (manager.isORMFacilitySelfManaged()) {
75 // No need to generated any ORM. Ignore any jar file given on
76 // command line also.
77 LOG.info("The connection manager declares that it self manages mapping"
78 + " between records & fields and rows & columns. The jar file "
79 + " provided will have no effect");
80 }
81 LOG.info("Using existing jar: " + existingJar);
82 return existingJar;
83 }
84 if (manager.isORMFacilitySelfManaged()) {
85 // No need to generated any ORM. Ignore any jar file given on
86 // command line also.
87 LOG.info("The connection manager declares that it self manages mapping"
88 + " between records & fields and rows & columns. No class will"
89 + " will be generated.");
90 return null;
91 }
92 LOG.info("Beginning code generation");
93 CompilationManager compileMgr = new CompilationManager(options);
94 ClassWriter classWriter = new ClassWriter(options, manager, tableName,
95 compileMgr);
96 classWriter.generate();
97 compileMgr.compile();
98 compileMgr.jar();
99 String jarFile = compileMgr.getJarFilename();
100 this.generatedJarFiles.add(jarFile);
101 return jarFile;
102 }
103
104
105 @Override
106 /** {@inheritDoc} */
107 public int run(SqoopOptions options) {
108 if (!init(options)) {
109 return 1;
110 }
111
112 try {
113 generateORM(options, options.getTableName());
114
115 // If the user has also specified Hive import code generation,
116 // use a HiveImport to generate the DDL statements and write
117 // them to files (but don't actually perform the import -- thus
118 // the generateOnly=true in the constructor).
119 if (options.doHiveImport()) {
120 HiveImport hiveImport = new HiveImport(options, manager,
121 options.getConf(), true);
122 hiveImport.importTable(options.getTableName(),
123 options.getHiveTableName(), true);
124 }
125
126 } catch (IOException ioe) {
127 LOG.error("Encountered IOException running codegen job: "
128 + StringUtils.stringifyException(ioe));
129 if (System.getProperty(Sqoop.SQOOP_RETHROW_PROPERTY) != null) {
130 throw new RuntimeException(ioe);
131 } else {
132 return 1;
133 }
134 } finally {
135 destroy(options);
136 }
137
138 return 0;
139 }
140
141 @Override
142 /** Configure the command-line arguments we expect to receive */
143 public void configureOptions(ToolOptions toolOptions) {
144
145 toolOptions.addUniqueOptions(getCommonOptions());
146
147 RelatedOptions codeGenOpts = getCodeGenOpts(false);
148 codeGenOpts.addOption(OptionBuilder.withArgName("table-name")
149 .hasArg()
150 .withDescription("Table to generate code for")
151 .withLongOpt(TABLE_ARG)
152 .create());
153 codeGenOpts.addOption(OptionBuilder.withArgName("statement")
154 .hasArg()
155 .withDescription("SQL 'statement' to generate code for")
156 .withLongOpt(SQL_QUERY_ARG)
157 .create(SQL_QUERY_SHORT_ARG));
158 toolOptions.addUniqueOptions(codeGenOpts);
159
160 toolOptions.addUniqueOptions(getOutputFormatOptions());
161 toolOptions.addUniqueOptions(getInputFormatOptions());
162 toolOptions.addUniqueOptions(getHiveOptions(true));
163 toolOptions.addUniqueOptions(getHCatalogOptions());
164 }
165
166 @Override
167 /** {@inheritDoc} */
168 public void printHelp(ToolOptions toolOptions) {
169 super.printHelp(toolOptions);
170 System.out.println("");
171 System.out.println(
172 "At minimum, you must specify --connect and --table");
173 }
174
175 @Override
176 /** {@inheritDoc} */
177 public void applyOptions(CommandLine in, SqoopOptions out)
178 throws InvalidOptionsException {
179
180 if (in.hasOption(TABLE_ARG)) {
181 out.setTableName(in.getOptionValue(TABLE_ARG));
182 }
183 if (in.hasOption(SQL_QUERY_ARG)) {
184 out.setSqlQuery(in.getOptionValue(SQL_QUERY_ARG));
185 }
186
187 applyCommonOptions(in, out);
188 applyOutputFormatOptions(in, out);
189 applyInputFormatOptions(in, out);
190 applyCodeGenOptions(in, out, false);
191 applyHiveOptions(in, out);
192 applyHCatOptions(in, out);
193 }
194
195 @Override
196 /** {@inheritDoc} */
197 public void validateOptions(SqoopOptions options)
198 throws InvalidOptionsException {
199
200 if (hasUnrecognizedArgs(extraArguments)) {
201 throw new InvalidOptionsException(HELP_STR);
202 }
203
204 validateCommonOptions(options);
205 validateCodeGenOptions(options);
206 validateOutputFormatOptions(options);
207 validateHiveOptions(options);
208 validateHCatalogOptions(options);
209
210 if (options.getTableName() == null
211 && options.getSqlQuery() == null) {
212 throw new InvalidOptionsException(
213 "--" + TABLE_ARG + " or --" + SQL_QUERY_ARG
214 + " is required for codegen. " + HELP_STR);
215 } else if (options.getTableName() != null
216 && options.getSqlQuery() != null) {
217 throw new InvalidOptionsException(
218 "Cannot specify --" + TABLE_ARG + " and --" + SQL_QUERY_ARG
219 + " together. " + HELP_STR);
220 }
221 }
222 }
223