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