001    /**
002     * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
003     * Licensed under the Apache License, Version 2.0 (the "License");
004     * you may not use this file except in compliance with the License.
005     * You may obtain a copy of the License at
006     *
007     *   http://www.apache.org/licenses/LICENSE-2.0
008     *
009     *  Unless required by applicable law or agreed to in writing, software
010     *  distributed under the License is distributed on an "AS IS" BASIS,
011     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012     *  See the License for the specific language governing permissions and
013     *  limitations under the License. See accompanying LICENSE file.
014     */
015    package org.apache.oozie.cli;
016    
017    import java.io.File;
018    import java.io.FileInputStream;
019    import java.io.FileReader;
020    import java.io.IOException;
021    import java.io.InputStream;
022    import java.text.SimpleDateFormat;
023    import java.util.ArrayList;
024    import java.util.Date;
025    import java.util.List;
026    import java.util.Locale;
027    import java.util.Map;
028    import java.util.Properties;
029    import java.util.TimeZone;
030    
031    import javax.xml.XMLConstants;
032    import javax.xml.parsers.DocumentBuilder;
033    import javax.xml.parsers.DocumentBuilderFactory;
034    import javax.xml.parsers.ParserConfigurationException;
035    import javax.xml.transform.stream.StreamSource;
036    import javax.xml.validation.Schema;
037    import javax.xml.validation.SchemaFactory;
038    import javax.xml.validation.Validator;
039    
040    import org.apache.commons.cli.CommandLine;
041    import org.apache.commons.cli.Option;
042    import org.apache.commons.cli.OptionGroup;
043    import org.apache.commons.cli.Options;
044    import org.apache.commons.cli.ParseException;
045    import org.apache.oozie.BuildInfo;
046    import org.apache.oozie.client.CoordinatorAction;
047    import org.apache.oozie.client.CoordinatorJob;
048    import org.apache.oozie.client.OozieClient;
049    import org.apache.oozie.client.OozieClientException;
050    import org.apache.oozie.client.WorkflowAction;
051    import org.apache.oozie.client.WorkflowJob;
052    import org.apache.oozie.client.XOozieClient;
053    import org.apache.oozie.client.OozieClient.SYSTEM_MODE;
054    import org.apache.oozie.client.rest.JsonCoordinatorAction;
055    import org.apache.oozie.client.rest.RestConstants;
056    import org.w3c.dom.DOMException;
057    import org.w3c.dom.Document;
058    import org.w3c.dom.Element;
059    import org.w3c.dom.Node;
060    import org.w3c.dom.NodeList;
061    import org.w3c.dom.Text;
062    import org.xml.sax.SAXException;
063    
064    /**
065     * Oozie command line utility.
066     */
067    public class OozieCLI {
068        public static final String ENV_OOZIE_URL = "OOZIE_URL";
069        public static final String WS_HEADER_PREFIX = "header:";
070    
071        public static final String HELP_CMD = "help";
072        public static final String VERSION_CMD = "version";
073        public static final String JOB_CMD = "job";
074        public static final String JOBS_CMD = "jobs";
075        public static final String ADMIN_CMD = "admin";
076        public static final String VALIDATE_CMD = "validate";
077        public static final String SLA_CMD = "sla";
078        public static final String PIG_CMD = "pig";
079    
080        public static final String OOZIE_OPTION = "oozie";
081        public static final String CONFIG_OPTION = "config";
082        public static final String SUBMIT_OPTION = "submit";
083        public static final String OFFSET_OPTION = "offset";
084        public static final String START_OPTION = "start";
085        public static final String RUN_OPTION = "run";
086        public static final String DRYRUN_OPTION = "dryrun";
087        public static final String SUSPEND_OPTION = "suspend";
088        public static final String RESUME_OPTION = "resume";
089        public static final String KILL_OPTION = "kill";
090        public static final String CHANGE_OPTION = "change";
091        public static final String CHANGE_VALUE_OPTION = "value";
092        public static final String RERUN_OPTION = "rerun";
093        public static final String INFO_OPTION = "info";
094        public static final String LOG_OPTION = "log";
095        public static final String DEFINITION_OPTION = "definition";
096    
097        public static final String LEN_OPTION = "len";
098        public static final String FILTER_OPTION = "filter";
099        public static final String JOBTYPE_OPTION = "jobtype";
100        public static final String SYSTEM_MODE_OPTION = "systemmode";
101        public static final String VERSION_OPTION = "version";
102        public static final String STATUS_OPTION = "status";
103        public static final String LOCAL_TIME_OPTION = "localtime";
104        public static final String QUEUE_DUMP_OPTION = "queuedump";
105        public static final String RERUN_ACTION_OPTION = "action";
106        public static final String RERUN_DATE_OPTION = "date";
107        public static final String RERUN_REFRESH_OPTION = "refresh";
108        public static final String RERUN_NOCLEANUP_OPTION = "nocleanup";
109    
110        public static final String VERBOSE_OPTION = "verbose";
111        public static final String VERBOSE_DELIMITER = "\t";
112    
113        public static final String PIGFILE_OPTION = "file";
114    
115        private static final String[] OOZIE_HELP = {
116                "the env variable '" + ENV_OOZIE_URL + "' is used as default value for the '-" + OOZIE_OPTION + "' option",
117                "custom headers for Oozie web services can be specified using '-D" + WS_HEADER_PREFIX + "NAME=VALUE'" };
118    
119        private static final String RULER;
120        private static final int LINE_WIDTH = 132;
121    
122        private boolean used;
123    
124        static {
125            StringBuilder sb = new StringBuilder();
126            for (int i = 0; i < LINE_WIDTH; i++) {
127                sb.append("-");
128            }
129            RULER = sb.toString();
130        }
131    
132        /**
133         * Entry point for the Oozie CLI when invoked from the command line.
134         * <p/>
135         * Upon completion this method exits the JVM with '0' (success) or '-1'
136         * (failure).
137         *
138         * @param args options and arguments for the Oozie CLI.
139         */
140        public static void main(String[] args) {
141            System.exit(new OozieCLI().run(args));
142        }
143    
144        /**
145         * Create an Oozie CLI instance.
146         */
147        public OozieCLI() {
148            used = false;
149        }
150    
151        /**
152         * Return Oozie CLI top help lines.
153         *
154         * @return help lines.
155         */
156        protected String[] getCLIHelp() {
157            return OOZIE_HELP;
158        }
159    
160        protected Options createAdminOptions() {
161            Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
162            Option system_mode = new Option(SYSTEM_MODE_OPTION, true,
163                    "Supported in Oozie-2.0 or later versions ONLY. Change oozie system mode [NORMAL|NOWEBSERVICE|SAFEMODE]");
164            Option status = new Option(STATUS_OPTION, false, "show the current system status");
165            Option version = new Option(VERSION_OPTION, false, "show Oozie server build version");
166            Option queuedump = new Option(QUEUE_DUMP_OPTION, false, "show Oozie server queue elements");
167            Options adminOptions = new Options();
168            adminOptions.addOption(oozie);
169            OptionGroup group = new OptionGroup();
170            group.addOption(system_mode);
171            group.addOption(status);
172            group.addOption(version);
173            group.addOption(queuedump);
174            adminOptions.addOptionGroup(group);
175            return adminOptions;
176        }
177    
178        protected Options createJobOptions() {
179            Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
180            Option config = new Option(CONFIG_OPTION, true, "job configuration file '.xml' or '.properties'");
181            Option submit = new Option(SUBMIT_OPTION, false, "submit a job (requires -config)");
182            Option run = new Option(RUN_OPTION, false, "run a job    (requires -config)");
183            Option rerun = new Option(RERUN_OPTION, true,
184                    "rerun a job  (workflow requires -config, coordinator requires -action or -date)");
185            Option dryrun = new Option(DRYRUN_OPTION, false,
186                    "Supported in Oozie-2.0 or later versions ONLY - dryrun or test run a coordinator job (requires -config) - job is not queued");
187            Option start = new Option(START_OPTION, true, "start a job");
188            Option suspend = new Option(SUSPEND_OPTION, true, "suspend a job");
189            Option resume = new Option(RESUME_OPTION, true, "resume a job");
190            Option kill = new Option(KILL_OPTION, true, "kill a job");
191            Option change = new Option(CHANGE_OPTION, true, "change a coordinator job");
192            Option changeValue = new Option(CHANGE_VALUE_OPTION, true, "new endtime/concurrency/pausetime value for changing a coordinator job");
193            Option info = new Option(INFO_OPTION, true, "info of a job");
194            Option offset = new Option(OFFSET_OPTION, true, "job info offset of actions (default '1', requires -info)");
195            Option len = new Option(LEN_OPTION, true, "number of actions (default TOTAL ACTIONS, requires -info)");
196            Option localtime = new Option(LOCAL_TIME_OPTION, false, "use local time (default GMT)");
197            Option log = new Option(LOG_OPTION, true, "job log");
198            Option definition = new Option(DEFINITION_OPTION, true, "job definition");
199            Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode");
200            Option rerun_action = new Option(RERUN_ACTION_OPTION, true, "coordinator rerun on action ids (requires -rerun)");
201            Option rerun_date = new Option(RERUN_DATE_OPTION, true, "coordinator rerun on action dates (requires -rerun)");
202            Option rerun_refresh = new Option(RERUN_REFRESH_OPTION, false,
203                    "re-materialize the coordinator rerun actions (requires -rerun)");
204            Option rerun_nocleanup = new Option(RERUN_NOCLEANUP_OPTION, false,
205                    "do not clean up output-events of the coordiantor rerun actions (requires -rerun)");
206    
207            OptionGroup actions = new OptionGroup();
208            actions.addOption(submit);
209            actions.addOption(start);
210            actions.addOption(run);
211            actions.addOption(dryrun);
212            actions.addOption(suspend);
213            actions.addOption(resume);
214            actions.addOption(kill);
215            actions.addOption(change);
216            actions.addOption(info);
217            actions.addOption(rerun);
218            actions.addOption(log);
219            actions.addOption(definition);
220            actions.setRequired(true);
221            Options jobOptions = new Options();
222            jobOptions.addOption(oozie);
223            jobOptions.addOption(config);
224            jobOptions.addOption(changeValue);
225            jobOptions.addOption(localtime);
226            jobOptions.addOption(verbose);
227            jobOptions.addOption(offset);
228            jobOptions.addOption(len);
229            jobOptions.addOption(rerun_action);
230            jobOptions.addOption(rerun_date);
231            jobOptions.addOption(rerun_refresh);
232            jobOptions.addOption(rerun_nocleanup);
233            jobOptions.addOptionGroup(actions);
234            return jobOptions;
235        }
236    
237        protected Options createJobsOptions() {
238            Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
239            Option start = new Option(OFFSET_OPTION, true, "jobs offset (default '1')");
240            Option jobtype = new Option(JOBTYPE_OPTION, true, "job type ('Supported in Oozie-2.0 or later versions ONLY - coordinator' or 'wf' (default))");
241            Option len = new Option(LEN_OPTION, true, "number of jobs (default '100')");
242            Option filter = new Option(FILTER_OPTION, true, "user=<U>;name=<N>;group=<G>;status=<S>;...");
243            Option localtime = new Option(LOCAL_TIME_OPTION, false, "use local time (default GMT)");
244            Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode");
245            start.setType(Integer.class);
246            len.setType(Integer.class);
247            Options jobsOptions = new Options();
248            jobsOptions.addOption(oozie);
249            jobsOptions.addOption(localtime);
250            jobsOptions.addOption(start);
251            jobsOptions.addOption(len);
252            jobsOptions.addOption(oozie);
253            jobsOptions.addOption(filter);
254            jobsOptions.addOption(jobtype);
255            jobsOptions.addOption(verbose);
256            return jobsOptions;
257        }
258    
259        protected Options createSlaOptions() {
260            Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
261            Option start = new Option(OFFSET_OPTION, true, "start offset (default '0')");
262            Option len = new Option(LEN_OPTION, true, "number of results (default '100')");
263            start.setType(Integer.class);
264            len.setType(Integer.class);
265            Options slaOptions = new Options();
266            slaOptions.addOption(start);
267            slaOptions.addOption(len);
268            slaOptions.addOption(oozie);
269            return slaOptions;
270        }
271    
272        protected Options createPigOptions() {
273            Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
274            Option config = new Option(CONFIG_OPTION, true, "job configuration file '.properties'");
275            Option pigFile = new Option(PIGFILE_OPTION, true, "Pig script");
276            Options pigOptions = new Options();
277            pigOptions.addOption(oozie);
278            pigOptions.addOption(config);
279            pigOptions.addOption(pigFile);
280            return pigOptions;
281        }
282    
283        /**
284         * Run a CLI programmatically.
285         * <p/>
286         * It does not exit the JVM.
287         * <p/>
288         * A CLI instance can be used only once.
289         *
290         * @param args options and arguments for the Oozie CLI.
291         * @return '0' (success), '-1' (failure).
292         */
293        public synchronized int run(String[] args) {
294            if (used) {
295                throw new IllegalStateException("CLI instance already used");
296            }
297            used = true;
298    
299            CLIParser parser = new CLIParser(OOZIE_OPTION, getCLIHelp());
300            parser.addCommand(HELP_CMD, "", "display usage", new Options(), false);
301            parser.addCommand(VERSION_CMD, "", "show client version", new Options(), false);
302            parser.addCommand(JOB_CMD, "", "job operations", createJobOptions(), false);
303            parser.addCommand(JOBS_CMD, "", "jobs status", createJobsOptions(), false);
304            parser.addCommand(ADMIN_CMD, "", "admin operations", createAdminOptions(), false);
305            parser.addCommand(VALIDATE_CMD, "", "validate a workflow XML file", new Options(), true);
306            parser.addCommand(SLA_CMD, "", "sla operations (Supported in Oozie-2.0 or later)", createSlaOptions(), false);
307            parser.addCommand(PIG_CMD, "-X ", "submit a pig job, everything after '-X' are pass-through parameters to pig",
308                              createPigOptions(), true);
309    
310            try {
311                CLIParser.Command command = parser.parse(args);
312                if (command.getName().equals(HELP_CMD)) {
313                    parser.showHelp();
314                }
315                else if (command.getName().equals(JOB_CMD)) {
316                    jobCommand(command.getCommandLine());
317                }
318                else if (command.getName().equals(JOBS_CMD)) {
319                    jobsCommand(command.getCommandLine());
320                }
321                else if (command.getName().equals(ADMIN_CMD)) {
322                    adminCommand(command.getCommandLine());
323                }
324                else if (command.getName().equals(VERSION_CMD)) {
325                    versionCommand();
326                }
327                else if (command.getName().equals(VALIDATE_CMD)) {
328                    validateCommand(command.getCommandLine());
329                }
330                else if (command.getName().equals(SLA_CMD)) {
331                    slaCommand(command.getCommandLine());
332                }
333                else if (command.getName().equals(PIG_CMD)) {
334                    pigCommand(command.getCommandLine());
335                }
336    
337                return 0;
338            }
339            catch (OozieCLIException ex) {
340                System.err.println("Error: " + ex.getMessage());
341                return -1;
342            }
343            catch (ParseException ex) {
344                System.err.println("Invalid sub-command: " + ex.getMessage());
345                System.err.println();
346                System.err.println(parser.shortHelp());
347                return -1;
348            }
349            catch (Exception ex) {
350                ex.printStackTrace();
351                System.err.println(ex.getMessage());
352                return -1;
353            }
354        }
355    
356        protected String getOozieUrl(CommandLine commandLine) {
357            String url = commandLine.getOptionValue(OOZIE_OPTION);
358            if (url == null) {
359                url = System.getenv(ENV_OOZIE_URL);
360                if (url == null) {
361                    throw new IllegalArgumentException(
362                            "Oozie URL is not available neither in command option or in the environment");
363                }
364            }
365            return url;
366        }
367    
368        // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
369        private Properties parse(InputStream is, Properties conf) throws IOException {
370            try {
371                DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
372                // ignore all comments inside the xml file
373                docBuilderFactory.setIgnoringComments(true);
374                DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
375                Document doc = builder.parse(is);
376                return parseDocument(doc, conf);
377            }
378            catch (SAXException e) {
379                throw new IOException(e);
380            }
381            catch (ParserConfigurationException e) {
382                throw new IOException(e);
383            }
384        }
385    
386        // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
387        private Properties parseDocument(Document doc, Properties conf) throws IOException {
388            try {
389                Element root = doc.getDocumentElement();
390                if (!"configuration".equals(root.getTagName())) {
391                    throw new RuntimeException("bad conf file: top-level element not <configuration>");
392                }
393                NodeList props = root.getChildNodes();
394                for (int i = 0; i < props.getLength(); i++) {
395                    Node propNode = props.item(i);
396                    if (!(propNode instanceof Element)) {
397                        continue;
398                    }
399                    Element prop = (Element) propNode;
400                    if (!"property".equals(prop.getTagName())) {
401                        throw new RuntimeException("bad conf file: element not <property>");
402                    }
403                    NodeList fields = prop.getChildNodes();
404                    String attr = null;
405                    String value = null;
406                    for (int j = 0; j < fields.getLength(); j++) {
407                        Node fieldNode = fields.item(j);
408                        if (!(fieldNode instanceof Element)) {
409                            continue;
410                        }
411                        Element field = (Element) fieldNode;
412                        if ("name".equals(field.getTagName()) && field.hasChildNodes()) {
413                            attr = ((Text) field.getFirstChild()).getData();
414                        }
415                        if ("value".equals(field.getTagName()) && field.hasChildNodes()) {
416                            value = ((Text) field.getFirstChild()).getData();
417                        }
418                    }
419    
420                    if (attr != null && value != null) {
421                        conf.setProperty(attr, value);
422                    }
423                }
424                return conf;
425            }
426            catch (DOMException e) {
427                throw new IOException(e);
428            }
429        }
430    
431        private Properties getConfiguration(CommandLine commandLine) throws IOException {
432            Properties conf = new Properties();
433            conf.setProperty("user.name", System.getProperty("user.name"));
434            String configFile = commandLine.getOptionValue(CONFIG_OPTION);
435            if (configFile == null) {
436                throw new IOException("configuration file not specified");
437            }
438            else {
439                File file = new File(configFile);
440                if (!file.exists()) {
441                    throw new IOException("configuration file [" + configFile + "] not found");
442                }
443                if (configFile.endsWith(".properties")) {
444                    conf.load(new FileReader(file));
445                }
446                else if (configFile.endsWith(".xml")) {
447                    parse(new FileInputStream(configFile), conf);
448                }
449                else {
450                    throw new IllegalArgumentException("configuration must be a '.properties' or a '.xml' file");
451                }
452            }
453            return conf;
454        }
455    
456        /**
457         * @param commandLine command line string.
458         * @return change value specified by -value.
459         * @throws OozieCLIException
460         */
461        private String getChangeValue(CommandLine commandLine) throws OozieCLIException {
462            String changeValue = commandLine.getOptionValue(CHANGE_VALUE_OPTION);
463    
464            if (changeValue == null) {
465                throw new OozieCLIException("-value option needs to be specified for -change option");
466            }
467    
468            return changeValue;
469        }
470    
471        private void addHeader(OozieClient wc) {
472            for (Map.Entry entry : System.getProperties().entrySet()) {
473                String key = (String) entry.getKey();
474                if (key.startsWith(WS_HEADER_PREFIX)) {
475                    String header = key.substring(WS_HEADER_PREFIX.length());
476                    wc.setHeader(header, (String) entry.getValue());
477                }
478            }
479        }
480    
481        /**
482         * Create a OozieClient. <p/> It injects any '-Dheader:' as header to the the {@link
483         * org.apache.oozie.client.OozieClient}.
484         *
485         * @param commandLine the parsed command line options.
486         * @return a pre configured eXtended workflow client.
487         * @throws OozieCLIException thrown if the OozieClient could not be
488         *         configured.
489         */
490        protected OozieClient createOozieClient(CommandLine commandLine) throws OozieCLIException {
491            OozieClient wc = new OozieClient(getOozieUrl(commandLine));
492            addHeader(wc);
493            return wc;
494        }
495    
496        /**
497         * Create a XOozieClient. <p/> It injects any '-Dheader:' as header to the the {@link
498         * org.apache.oozie.client.OozieClient}.
499         *
500         * @param commandLine the parsed command line options.
501         * @return a pre configured eXtended workflow client.
502         * @throws OozieCLIException thrown if the XOozieClient could not be
503         *         configured.
504         */
505        protected XOozieClient createXOozieClient(CommandLine commandLine) throws OozieCLIException {
506            XOozieClient wc = new XOozieClient(getOozieUrl(commandLine));
507            addHeader(wc);
508            return wc;
509        }
510    
511        private static String JOB_ID_PREFIX = "job: ";
512    
513        private void jobCommand(CommandLine commandLine) throws IOException, OozieCLIException {
514            XOozieClient wc = createXOozieClient(commandLine);
515    
516            List<String> options = new ArrayList<String>();
517            for (Option option : commandLine.getOptions()) {
518                options.add(option.getOpt());
519            }
520    
521            try {
522                if (options.contains(SUBMIT_OPTION)) {
523                    System.out.println(JOB_ID_PREFIX + wc.submit(getConfiguration(commandLine)));
524                }
525                else if (options.contains(START_OPTION)) {
526                    wc.start(commandLine.getOptionValue(START_OPTION));
527                }
528                else if (options.contains(DRYRUN_OPTION)) {
529                    String[] dryrunStr = wc.dryrun(getConfiguration(commandLine)).split("action for new instance");
530                    int arraysize = dryrunStr.length;
531                    System.out.println("***coordJob after parsing: ***");
532                    System.out.println(dryrunStr[0]);
533                    int aLen = dryrunStr.length - 1;
534                    if (aLen < 0) {
535                        aLen = 0;
536                    }
537                    System.out.println("***total coord actions is " + aLen + " ***");
538                    for (int i = 1; i <= arraysize - 1; i++) {
539                        System.out.println(RULER);
540                        System.out.println("coordAction instance: " + i + ":");
541                        System.out.println(dryrunStr[i]);
542                    }
543                }
544                else if (options.contains(SUSPEND_OPTION)) {
545                    wc.suspend(commandLine.getOptionValue(SUSPEND_OPTION));
546                }
547                else if (options.contains(RESUME_OPTION)) {
548                    wc.resume(commandLine.getOptionValue(RESUME_OPTION));
549                }
550                else if (options.contains(KILL_OPTION)) {
551                    wc.kill(commandLine.getOptionValue(KILL_OPTION));
552                }
553                else if (options.contains(CHANGE_OPTION)) {
554                    wc.change(commandLine.getOptionValue(CHANGE_OPTION), getChangeValue(commandLine));
555                }
556                else if (options.contains(RUN_OPTION)) {
557                    System.out.println(JOB_ID_PREFIX + wc.run(getConfiguration(commandLine)));
558                }
559                else if (options.contains(RERUN_OPTION)) {
560                    if (commandLine.getOptionValue(RERUN_OPTION).contains("-W")) {
561                        wc.reRun(commandLine.getOptionValue(RERUN_OPTION), getConfiguration(commandLine));
562                    } else {
563                        String coordJobId = commandLine.getOptionValue(RERUN_OPTION);
564                        String scope = null;
565                        String rerunType = null;
566                        boolean refresh = false;
567                        boolean noCleanup = false;
568                        if (options.contains(RERUN_DATE_OPTION) && options.contains(RERUN_ACTION_OPTION)) {
569                            throw new OozieCLIException("Invalid options provided for rerun: either" + RERUN_DATE_OPTION
570                                    + " or " + RERUN_ACTION_OPTION + " expected. Don't use both at the same time.");
571                        }
572                        if (options.contains(RERUN_DATE_OPTION)) {
573                            rerunType = RestConstants.JOB_COORD_RERUN_DATE;
574                            scope = commandLine.getOptionValue(RERUN_DATE_OPTION);
575                        } else if (options.contains(RERUN_ACTION_OPTION)){
576                            rerunType = RestConstants.JOB_COORD_RERUN_ACTION;
577                            scope = commandLine.getOptionValue(RERUN_ACTION_OPTION);
578                        }
579                        else {
580                            throw new OozieCLIException("Invalid options provided for rerun: " + RERUN_DATE_OPTION + " or "
581                                    + RERUN_ACTION_OPTION + " expected.");
582                        }
583                        if (options.contains(RERUN_REFRESH_OPTION)) {
584                            refresh = true;
585                        }
586                        if (options.contains(RERUN_NOCLEANUP_OPTION)) {
587                            noCleanup = true;
588                        }
589                        printRerunCoordActions(wc.reRunCoord(coordJobId, rerunType, scope, refresh, noCleanup));
590                    }
591                }
592                else if (options.contains(INFO_OPTION)) {
593                    if (commandLine.getOptionValue(INFO_OPTION).endsWith("-C")) {
594                        String s = commandLine.getOptionValue(OFFSET_OPTION);
595                        int start = Integer.parseInt((s != null) ? s : "0");
596                        s = commandLine.getOptionValue(LEN_OPTION);
597                        int len = Integer.parseInt((s != null) ? s : "0");
598                        printCoordJob(wc.getCoordJobInfo(commandLine.getOptionValue(INFO_OPTION), start, len), options
599                                .contains(LOCAL_TIME_OPTION), options.contains(VERBOSE_OPTION));
600                    }
601                    else if (commandLine.getOptionValue(INFO_OPTION).contains("-C@")) {
602                        printCoordAction(wc.getCoordActionInfo(commandLine.getOptionValue(INFO_OPTION)), options
603                                .contains(LOCAL_TIME_OPTION));
604                    }
605                    else if (commandLine.getOptionValue(INFO_OPTION).contains("-W@")) {
606                        printWorkflowAction(wc.getWorkflowActionInfo(commandLine.getOptionValue(INFO_OPTION)), options
607                                .contains(LOCAL_TIME_OPTION));
608                    }
609                    else {
610                        String s = commandLine.getOptionValue(OFFSET_OPTION);
611                        int start = Integer.parseInt((s != null) ? s : "0");
612                        s = commandLine.getOptionValue(LEN_OPTION);
613                        String jobtype = commandLine.getOptionValue(JOBTYPE_OPTION);
614                        jobtype = (jobtype != null) ? jobtype : "wf";
615                        int len = Integer.parseInt((s != null) ? s : "0");
616                        printJob(wc.getJobInfo(commandLine.getOptionValue(INFO_OPTION), start, len), options
617                                .contains(LOCAL_TIME_OPTION), options.contains(VERBOSE_OPTION));
618                    }
619                }
620                else if (options.contains(LOG_OPTION)) {
621                    System.out.println(wc.getJobLog(commandLine.getOptionValue(LOG_OPTION)));
622                }
623                else if (options.contains(DEFINITION_OPTION)) {
624                    System.out.println(wc.getJobDefinition(commandLine.getOptionValue(DEFINITION_OPTION)));
625                }
626            }
627            catch (OozieClientException ex) {
628                throw new OozieCLIException(ex.toString(), ex);
629            }
630        }
631    
632        private void printCoordJob(CoordinatorJob coordJob, boolean localtime, boolean verbose) {
633            System.out.println("Job ID : " + coordJob.getId());
634    
635            System.out.println(RULER);
636    
637            List<CoordinatorAction> actions = coordJob.getActions();
638            System.out.println("Job Name : " + maskIfNull(coordJob.getAppName()));
639            System.out.println("App Path : " + maskIfNull(coordJob.getAppPath()));
640            System.out.println("Status   : " + coordJob.getStatus());
641            System.out.println(RULER);
642    
643            if (verbose) {
644                System.out.println("ID" + VERBOSE_DELIMITER + "Action Number" + VERBOSE_DELIMITER + "Console URL"
645                        + VERBOSE_DELIMITER + "Error Code" + VERBOSE_DELIMITER + "Error Message" + VERBOSE_DELIMITER
646                        + "External ID" + VERBOSE_DELIMITER + "External Status" + VERBOSE_DELIMITER + "Job ID"
647                        + VERBOSE_DELIMITER + "Tracker URI" + VERBOSE_DELIMITER + "Created" + VERBOSE_DELIMITER
648                        + "Nominal Time" + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Last Modified" + VERBOSE_DELIMITER + "Missing Dependencies");
649                System.out.println(RULER);
650    
651                for (CoordinatorAction action : actions) {
652                    System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER + action.getActionNumber()
653                            + VERBOSE_DELIMITER + maskIfNull(action.getConsoleUrl()) + VERBOSE_DELIMITER
654                            + maskIfNull(action.getErrorCode()) + VERBOSE_DELIMITER + maskIfNull(action.getErrorMessage())
655                            + VERBOSE_DELIMITER + maskIfNull(action.getExternalId()) + VERBOSE_DELIMITER
656                            + maskIfNull(action.getExternalStatus()) + VERBOSE_DELIMITER + maskIfNull(action.getJobId())
657                            + VERBOSE_DELIMITER + maskIfNull(action.getTrackerUri()) + VERBOSE_DELIMITER
658                            + maskDate(action.getCreatedTime(), localtime) + VERBOSE_DELIMITER +  maskDate(action.getNominalTime(), localtime)
659                            + action.getStatus() + VERBOSE_DELIMITER + maskDate(action.getLastModifiedTime(), localtime) + VERBOSE_DELIMITER
660                            + maskIfNull(action.getMissingDependencies()));
661    
662                    System.out.println(RULER);
663                }
664            }
665            else {
666                System.out.println(String.format(COORD_ACTION_FORMATTER, "ID", "Status", "Ext ID", "Err Code", "Created",
667                        "Nominal Time", "Last Mod"));
668    
669                for (CoordinatorAction action : actions) {
670                    System.out.println(String
671                            .format(COORD_ACTION_FORMATTER, maskIfNull(action.getId()), action.getStatus(),
672                                    maskIfNull(action.getExternalId()), maskIfNull(action.getErrorCode()), maskDate(action
673                                            .getCreatedTime(), localtime), maskDate(action.getNominalTime(), localtime),
674                                    maskDate(action.getLastModifiedTime(), localtime)));
675    
676                    System.out.println(RULER);
677                }
678            }
679        }
680    
681        private void printCoordAction(CoordinatorAction coordAction, boolean contains) {
682            System.out.println("ID : " + maskIfNull(coordAction.getId()));
683    
684            System.out.println(RULER);
685    
686            System.out.println("Action Number        : " + coordAction.getActionNumber());
687            System.out.println("Console URL          : " + maskIfNull(coordAction.getConsoleUrl()));
688            System.out.println("Error Code           : " + maskIfNull(coordAction.getErrorCode()));
689            System.out.println("Error Message        : " + maskIfNull(coordAction.getErrorMessage()));
690            System.out.println("External ID          : " + maskIfNull(coordAction.getExternalId()));
691            System.out.println("External Status      : " + maskIfNull(coordAction.getExternalStatus()));
692            System.out.println("Job ID               : " + maskIfNull(coordAction.getJobId()));
693            System.out.println("Tracker URI          : " + maskIfNull(coordAction.getTrackerUri()));
694            System.out.println("Created              : " + maskDate(coordAction.getCreatedTime(), contains));
695            System.out.println("Nominal Time         : " + maskDate(coordAction.getNominalTime(), contains));
696            System.out.println("Status               : " + coordAction.getStatus());
697            System.out.println("Last Modified        : " + maskDate(coordAction.getLastModifiedTime(), contains));
698            System.out.println("Missing Dependencies : " + maskIfNull(coordAction.getMissingDependencies()));
699    
700            System.out.println(RULER);
701        }
702    
703        private void printRerunCoordActions(List<JsonCoordinatorAction> actions) {
704            if (actions != null && actions.size() > 0) {
705                System.out.println("Action ID" + VERBOSE_DELIMITER + "Nominal Time");
706                System.out.println(RULER);
707                for (CoordinatorAction action : actions) {
708                    System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER
709                            + maskDate(action.getNominalTime(), false));
710                }
711            }
712            else {
713                System.out.println("No Actions match your rerun criteria!");
714            }
715        }
716    
717        private void printWorkflowAction(WorkflowAction action, boolean contains) {
718            System.out.println("ID : " + maskIfNull(action.getId()));
719    
720            System.out.println(RULER);
721    
722            System.out.println("Console URL     : " + maskIfNull(action.getConsoleUrl()));
723            System.out.println("Error Code      : " + maskIfNull(action.getErrorCode()));
724            System.out.println("Error Message   : " + maskIfNull(action.getErrorMessage()));
725            System.out.println("External ID     : " + maskIfNull(action.getExternalId()));
726            System.out.println("External Status : " + maskIfNull(action.getExternalStatus()));
727            System.out.println("Name            : " + maskIfNull(action.getName()));
728            System.out.println("Retries         : " + action.getRetries());
729            System.out.println("Tracker URI     : " + maskIfNull(action.getTrackerUri()));
730            System.out.println("Type            : " + maskIfNull(action.getType()));
731            System.out.println("Started         : " + maskDate(action.getStartTime(), contains));
732            System.out.println("Status          : " + action.getStatus());
733            System.out.println("Ended           : " + maskDate(action.getEndTime(), contains));
734    
735            System.out.println(RULER);
736        }
737    
738        private static final String WORKFLOW_JOBS_FORMATTER = "%-41s%-13s%-10s%-10s%-10s%-24s%-24s";
739        private static final String COORD_JOBS_FORMATTER = "%-41s%-15s%-10s%-5s%-13s%-24s%-24s";
740    
741        private static final String WORKFLOW_ACTION_FORMATTER = "%-78s%-10s%-23s%-11s%-10s";
742        private static final String COORD_ACTION_FORMATTER = "%-41s%-10s%-37s%-10s%-17s%-17s";
743    
744        private void printJob(WorkflowJob job, boolean localtime, boolean verbose) throws IOException {
745            System.out.println("Job ID : " + maskIfNull(job.getId()));
746    
747            System.out.println(RULER);
748    
749            System.out.println("Workflow Name : " + maskIfNull(job.getAppName()));
750            System.out.println("App Path      : " + maskIfNull(job.getAppPath()));
751            System.out.println("Status        : " + job.getStatus());
752            System.out.println("Run           : " + job.getRun());
753            System.out.println("User          : " + maskIfNull(job.getUser()));
754            System.out.println("Group         : " + maskIfNull(job.getGroup()));
755            System.out.println("Created       : " + maskDate(job.getCreatedTime(), localtime));
756            System.out.println("Started       : " + maskDate(job.getStartTime(), localtime));
757            System.out.println("Last Modified : " + maskDate(job.getLastModifiedTime(), localtime));
758            System.out.println("Ended         : " + maskDate(job.getEndTime(), localtime));
759    
760            List<WorkflowAction> actions = job.getActions();
761    
762            if (actions != null && actions.size() > 0) {
763                System.out.println();
764                System.out.println("Actions");
765                System.out.println(RULER);
766    
767                if (verbose) {
768                    System.out.println("ID" + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "Error Code"
769                            + VERBOSE_DELIMITER + "Error Message" + VERBOSE_DELIMITER + "External ID" + VERBOSE_DELIMITER
770                            + "External Status" + VERBOSE_DELIMITER + "Name" + VERBOSE_DELIMITER + "Retries"
771                            + VERBOSE_DELIMITER + "Tracker URI" + VERBOSE_DELIMITER + "Type" + VERBOSE_DELIMITER
772                            + "Started" + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Ended");
773                    System.out.println(RULER);
774    
775                    for (WorkflowAction action : job.getActions()) {
776                        System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER
777                                + maskIfNull(action.getConsoleUrl()) + VERBOSE_DELIMITER
778                                + maskIfNull(action.getErrorCode()) + VERBOSE_DELIMITER
779                                + maskIfNull(action.getErrorMessage()) + VERBOSE_DELIMITER
780                                + maskIfNull(action.getExternalId()) + VERBOSE_DELIMITER
781                                + maskIfNull(action.getExternalStatus()) + VERBOSE_DELIMITER + maskIfNull(action.getName())
782                                + VERBOSE_DELIMITER + action.getRetries() + VERBOSE_DELIMITER
783                                + maskIfNull(action.getTrackerUri()) + VERBOSE_DELIMITER + maskIfNull(action.getType())
784                                + VERBOSE_DELIMITER + maskDate(action.getStartTime(), localtime) + VERBOSE_DELIMITER
785                                + action.getStatus() + VERBOSE_DELIMITER + maskDate(action.getEndTime(), localtime));
786    
787                        System.out.println(RULER);
788                    }
789                }
790                else {
791                    System.out.println(String.format(WORKFLOW_ACTION_FORMATTER, "ID", "Status", "Ext ID", "Ext Status",
792                            "Err Code"));
793    
794                    System.out.println(RULER);
795    
796                    for (WorkflowAction action : job.getActions()) {
797                        System.out.println(String.format(WORKFLOW_ACTION_FORMATTER, maskIfNull(action.getId()), action
798                                .getStatus(), maskIfNull(action.getExternalId()), maskIfNull(action.getExternalStatus()),
799                                maskIfNull(action.getErrorCode())));
800    
801                        System.out.println(RULER);
802                    }
803                }
804            }
805            else {
806                System.out.println(RULER);
807            }
808    
809            System.out.println();
810        }
811    
812        private void jobsCommand(CommandLine commandLine) throws IOException, OozieCLIException {
813            XOozieClient wc = createXOozieClient(commandLine);
814    
815            String filter = commandLine.getOptionValue(FILTER_OPTION);
816            String s = commandLine.getOptionValue(OFFSET_OPTION);
817            int start = Integer.parseInt((s != null) ? s : "0");
818            s = commandLine.getOptionValue(LEN_OPTION);
819            String jobtype = commandLine.getOptionValue(JOBTYPE_OPTION);
820            jobtype = (jobtype != null) ? jobtype : "wf";
821            int len = Integer.parseInt((s != null) ? s : "0");
822            try {
823                if (jobtype.contains("wf")) {
824                    printJobs(wc.getJobsInfo(filter, start, len), commandLine.hasOption(LOCAL_TIME_OPTION), commandLine
825                            .hasOption(VERBOSE_OPTION));
826                }
827                else {
828                    printCoordJobs(wc.getCoordJobsInfo(filter, start, len), commandLine.hasOption(LOCAL_TIME_OPTION),
829                            commandLine.hasOption(VERBOSE_OPTION));
830                }
831    
832            }
833            catch (OozieClientException ex) {
834                throw new OozieCLIException(ex.toString(), ex);
835            }
836        }
837    
838        private void printCoordJobs(List<CoordinatorJob> jobs, boolean localtime, boolean verbose) throws IOException {
839            if (jobs != null && jobs.size() > 0) {
840                if (verbose) {
841                    System.out.println("Job ID" + VERBOSE_DELIMITER + "App Name" + VERBOSE_DELIMITER + "App Path"
842                            + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group"
843                            + VERBOSE_DELIMITER + "Concurrency" + VERBOSE_DELIMITER + "Frequency" + VERBOSE_DELIMITER
844                            + "Time Unit" + VERBOSE_DELIMITER + "Time Zone" + VERBOSE_DELIMITER + "Time Out"
845                            + VERBOSE_DELIMITER + "Started" + VERBOSE_DELIMITER + "Next Materialize" + VERBOSE_DELIMITER
846                            + "Status" + VERBOSE_DELIMITER + "Last Action" + VERBOSE_DELIMITER + "Ended");
847                    System.out.println(RULER);
848    
849                    for (CoordinatorJob job : jobs) {
850                        System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName())
851                                + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER
852                                + maskIfNull(job.getConsoleUrl()) + VERBOSE_DELIMITER + maskIfNull(job.getUser())
853                                + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) + VERBOSE_DELIMITER + job.getConcurrency()
854                                + VERBOSE_DELIMITER + job.getFrequency() + VERBOSE_DELIMITER + job.getTimeUnit()
855                                + VERBOSE_DELIMITER + maskIfNull(job.getTimeZone()) + VERBOSE_DELIMITER + job.getTimeout()
856                                + VERBOSE_DELIMITER + maskDate(job.getStartTime(), localtime) + VERBOSE_DELIMITER
857                                + maskDate(job.getNextMaterializedTime(), localtime) + VERBOSE_DELIMITER + job.getStatus()
858                                + VERBOSE_DELIMITER + maskDate(job.getLastActionTime(), localtime) + VERBOSE_DELIMITER
859                                + maskDate(job.getEndTime(), localtime));
860    
861                        System.out.println(RULER);
862                    }
863                }
864                else {
865                    System.out.println(String.format(COORD_JOBS_FORMATTER, "Job ID", "App Name", "Status", "Freq", "Unit",
866                            "Started", "Next Materialized"));
867                    System.out.println(RULER);
868    
869                    for (CoordinatorJob job : jobs) {
870                        System.out.println(String.format(COORD_JOBS_FORMATTER, maskIfNull(job.getId()), maskIfNull(job
871                                .getAppName()), job.getStatus(), job.getFrequency(), job.getTimeUnit(), maskDate(job
872                                .getStartTime(), localtime), maskDate(job.getNextMaterializedTime(), localtime)));
873    
874                        System.out.println(RULER);
875                    }
876                }
877            }
878            else {
879                System.out.println("No Jobs match your criteria!");
880            }
881        }
882    
883        private void slaCommand(CommandLine commandLine) throws IOException, OozieCLIException {
884            XOozieClient wc = createXOozieClient(commandLine);
885            String s = commandLine.getOptionValue(OFFSET_OPTION);
886            int start = Integer.parseInt((s != null) ? s : "0");
887            s = commandLine.getOptionValue(LEN_OPTION);
888            int len = Integer.parseInt((s != null) ? s : "100");
889            try {
890                wc.getSlaInfo(start, len);
891            }
892            catch (OozieClientException ex) {
893                throw new OozieCLIException(ex.toString(), ex);
894            }
895        }
896    
897        private void adminCommand(CommandLine commandLine) throws OozieCLIException {
898            XOozieClient wc = createXOozieClient(commandLine);
899    
900            List<String> options = new ArrayList<String>();
901            for (Option option : commandLine.getOptions()) {
902                options.add(option.getOpt());
903            }
904    
905            try {
906                SYSTEM_MODE status = SYSTEM_MODE.NORMAL;
907                if (options.contains(VERSION_OPTION)) {
908                    System.out.println("Oozie server build version: " + wc.getServerBuildVersion());
909                }
910                else if (options.contains(SYSTEM_MODE_OPTION)) {
911                        String systemModeOption = commandLine.getOptionValue(SYSTEM_MODE_OPTION).toUpperCase();
912                        try {
913                            status = SYSTEM_MODE.valueOf(systemModeOption);
914                        }
915                        catch (Exception e) {
916                            throw new OozieCLIException("Invalid input provided for option: " + SYSTEM_MODE_OPTION
917                                    + " value given :" + systemModeOption
918                                    + " Expected values are: NORMAL/NOWEBSERVICE/SAFEMODE ");
919                        }
920                        wc.setSystemMode(status);
921                        System.out.println("System mode: " + status);
922                }
923                else if (options.contains(STATUS_OPTION)) {
924                        status = wc.getSystemMode();
925                        System.out.println("System mode: " + status);
926                }
927                else if (options.contains(QUEUE_DUMP_OPTION)) {
928                    System.out.println("[Server Queue Dump]:");
929                    List<String> list = wc.getQueueDump();
930                    if (list != null && list.size() != 0) {
931                        for (String str: list) {
932                            System.out.println(str);
933                        }
934                    }
935                    else {
936                        System.out.println("QueueDump is null!");
937                    }
938                }
939            }
940            catch (OozieClientException ex) {
941                throw new OozieCLIException(ex.toString(), ex);
942            }
943        }
944    
945        private void versionCommand() throws OozieCLIException {
946            System.out.println("Oozie client build version: "
947                    + BuildInfo.getBuildInfo().getProperty(BuildInfo.BUILD_VERSION));
948        }
949    
950        private void printJobs(List<WorkflowJob> jobs, boolean localtime, boolean verbose) throws IOException {
951            if (jobs != null && jobs.size() > 0) {
952                if (verbose) {
953                    System.out.println("Job ID" + VERBOSE_DELIMITER + "App Name" + VERBOSE_DELIMITER + "App Path"
954                            + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group"
955                            + VERBOSE_DELIMITER + "Run" + VERBOSE_DELIMITER + "Created" + VERBOSE_DELIMITER + "Started"
956                            + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Last Modified" + VERBOSE_DELIMITER
957                            + "Ended");
958                    System.out.println(RULER);
959    
960                    for (WorkflowJob job : jobs) {
961                        System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName())
962                                + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER
963                                + maskIfNull(job.getConsoleUrl()) + VERBOSE_DELIMITER + maskIfNull(job.getUser())
964                                + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) + VERBOSE_DELIMITER + job.getRun()
965                                + VERBOSE_DELIMITER + maskDate(job.getCreatedTime(), localtime) + VERBOSE_DELIMITER
966                                + maskDate(job.getStartTime(), localtime) + VERBOSE_DELIMITER + job.getStatus()
967                                + VERBOSE_DELIMITER + maskDate(job.getLastModifiedTime(), localtime) + VERBOSE_DELIMITER
968                                + maskDate(job.getEndTime(), localtime));
969    
970                        System.out.println(RULER);
971                    }
972                }
973                else {
974                    System.out.println(String.format(WORKFLOW_JOBS_FORMATTER, "Job ID", "App Name", "Status", "User",
975                            "Group", "Started", "Ended"));
976                    System.out.println(RULER);
977    
978                    for (WorkflowJob job : jobs) {
979                        System.out.println(String.format(WORKFLOW_JOBS_FORMATTER, maskIfNull(job.getId()), maskIfNull(job
980                                .getAppName()), job.getStatus(), maskIfNull(job.getUser()), maskIfNull(job.getGroup()),
981                                maskDate(job.getStartTime(), localtime), maskDate(job.getEndTime(), localtime)));
982    
983                        System.out.println(RULER);
984                    }
985                }
986            }
987            else {
988                System.out.println("No Jobs match your criteria!");
989            }
990        }
991    
992        private String maskIfNull(String value) {
993            if (value != null && value.length() > 0) {
994                return value;
995            }
996            return "-";
997        }
998    
999        private String maskDate(Date date, boolean isLocalTimeZone) {
1000            if (date == null) {
1001                return "-";
1002            }
1003    
1004            // SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd
1005            // HH:mm Z", Locale.US);
1006            SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
1007            if (!isLocalTimeZone) {
1008                dateFormater.setTimeZone(TimeZone.getTimeZone("GMT"));
1009            }
1010            return dateFormater.format(date);
1011        }
1012    
1013        private void validateCommand(CommandLine commandLine) throws OozieCLIException {
1014            String[] args = commandLine.getArgs();
1015            if (args.length != 1) {
1016                throw new OozieCLIException("One file must be specified");
1017            }
1018            File file = new File(args[0]);
1019            if (file.exists()) {
1020                try {
1021                    List<StreamSource> sources = new ArrayList<StreamSource>();
1022                    sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1023                            "oozie-workflow-0.1.xsd")));
1024                    sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1025                            "hive-action-0.1.xsd")));
1026                    sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1027                            "sqoop-action-0.1.xsd")));
1028                    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
1029                    Schema schema = factory.newSchema(sources.toArray(new StreamSource[sources.size()]));
1030                    Validator validator = schema.newValidator();
1031                    validator.validate(new StreamSource(new FileReader(file)));
1032                    System.out.println("Valid worflow-app");
1033                }
1034                catch (Exception ex) {
1035                    throw new OozieCLIException("Invalid workflow-app, " + ex.toString(), ex);
1036                }
1037            }
1038            else {
1039                throw new OozieCLIException("File does not exists");
1040            }
1041        }
1042    
1043        private void pigCommand(CommandLine commandLine) throws IOException, OozieCLIException {
1044            List<String> pigArgs = (List<String>) commandLine.getArgList();
1045            if (pigArgs.size() > 0) {
1046                // checking is a pigArgs starts with -X (because CLIParser cannot check this)
1047                if (!pigArgs.get(0).equals("-X")) {
1048                    throw new OozieCLIException("Unrecognized option: " + pigArgs.get(0) + " Expecting -X");
1049                }
1050                pigArgs.remove(0);
1051            }
1052    
1053            List<String> options = new ArrayList<String>();
1054            for (Option option : commandLine.getOptions()) {
1055                options.add(option.getOpt());
1056            }
1057    
1058            if (!options.contains(PIGFILE_OPTION)) {
1059                throw new OozieCLIException("Need to specify -file <scriptfile>");
1060            }
1061    
1062            if (!options.contains(CONFIG_OPTION)) {
1063                throw new OozieCLIException("Need to specify -config <configfile>");
1064            }
1065    
1066            Properties conf = getConfiguration(commandLine);
1067            String script = commandLine.getOptionValue(PIGFILE_OPTION);
1068    
1069            try {
1070                XOozieClient wc = createXOozieClient(commandLine);
1071                System.out.println(JOB_ID_PREFIX + wc.submitPig(conf, script, pigArgs.toArray(new String[pigArgs.size()])));
1072            }
1073            catch (OozieClientException ex) {
1074                throw new OozieCLIException(ex.toString(), ex);
1075            }
1076        }
1077    }