This project has retired. For details please refer to its
Attic page.
001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.oozie.client;
019
020 import java.io.BufferedReader;
021 import java.io.IOException;
022 import java.io.InputStream;
023 import java.io.InputStreamReader;
024 import java.io.OutputStream;
025 import java.io.PrintStream;
026 import java.io.Reader;
027 import java.net.HttpURLConnection;
028 import java.net.URL;
029 import java.net.URLEncoder;
030 import java.util.ArrayList;
031 import java.util.Collections;
032 import java.util.HashMap;
033 import java.util.Iterator;
034 import java.util.LinkedHashMap;
035 import java.util.List;
036 import java.util.Map;
037 import java.util.Properties;
038 import java.util.concurrent.Callable;
039
040 import javax.xml.parsers.DocumentBuilderFactory;
041 import javax.xml.transform.Transformer;
042 import javax.xml.transform.TransformerFactory;
043 import javax.xml.transform.dom.DOMSource;
044 import javax.xml.transform.stream.StreamResult;
045
046 import org.apache.oozie.BuildInfo;
047 import org.apache.oozie.client.rest.JsonTags;
048 import org.apache.oozie.client.rest.JsonToBean;
049 import org.apache.oozie.client.rest.RestConstants;
050 import org.json.simple.JSONArray;
051 import org.json.simple.JSONObject;
052 import org.json.simple.JSONValue;
053 import org.w3c.dom.Document;
054 import org.w3c.dom.Element;
055
056 /**
057 * Client API to submit and manage Oozie workflow jobs against an Oozie intance.
058 * <p/>
059 * This class is thread safe.
060 * <p/>
061 * Syntax for filter for the {@link #getJobsInfo(String)} {@link #getJobsInfo(String, int, int)} methods:
062 * <code>[NAME=VALUE][;NAME=VALUE]*</code>.
063 * <p/>
064 * Valid filter names are:
065 * <p/>
066 * <ul/>
067 * <li>name: the workflow application name from the workflow definition.</li>
068 * <li>user: the user that submitted the job.</li>
069 * <li>group: the group for the job.</li>
070 * <li>status: the status of the job.</li>
071 * </ul>
072 * <p/>
073 * The query will do an AND among all the filter names. The query will do an OR among all the filter values for the same
074 * name. Multiple values must be specified as different name value pairs.
075 */
076 public class OozieClient {
077
078 public static final long WS_PROTOCOL_VERSION_0 = 0;
079
080 public static final long WS_PROTOCOL_VERSION = 1;
081
082 public static final String USER_NAME = "user.name";
083
084 @Deprecated
085 public static final String GROUP_NAME = "group.name";
086
087 public static final String JOB_ACL = "oozie.job.acl";
088
089 public static final String APP_PATH = "oozie.wf.application.path";
090
091 public static final String COORDINATOR_APP_PATH = "oozie.coord.application.path";
092
093 public static final String BUNDLE_APP_PATH = "oozie.bundle.application.path";
094
095 public static final String BUNDLE_ID = "oozie.bundle.id";
096
097 public static final String EXTERNAL_ID = "oozie.wf.external.id";
098
099 public static final String WORKFLOW_NOTIFICATION_URL = "oozie.wf.workflow.notification.url";
100
101 public static final String ACTION_NOTIFICATION_URL = "oozie.wf.action.notification.url";
102
103 public static final String COORD_ACTION_NOTIFICATION_URL = "oozie.coord.action.notification.url";
104
105 public static final String RERUN_SKIP_NODES = "oozie.wf.rerun.skip.nodes";
106
107 public static final String RERUN_FAIL_NODES = "oozie.wf.rerun.failnodes";
108
109 public static final String LOG_TOKEN = "oozie.wf.log.token";
110
111 public static final String ACTION_MAX_RETRIES = "oozie.wf.action.max.retries";
112
113 public static final String ACTION_RETRY_INTERVAL = "oozie.wf.action.retry.interval";
114
115 public static final String FILTER_USER = "user";
116
117 public static final String FILTER_GROUP = "group";
118
119 public static final String FILTER_NAME = "name";
120
121 public static final String FILTER_STATUS = "status";
122
123 public static final String FILTER_FREQUENCY = "frequency";
124
125 public static final String FILTER_ID = "id";
126
127 public static final String FILTER_UNIT = "unit";
128
129 public static final String FILTER_JOBID = "jobid";
130
131 public static final String FILTER_APPNAME = "appname";
132
133 public static final String CHANGE_VALUE_ENDTIME = "endtime";
134
135 public static final String CHANGE_VALUE_PAUSETIME = "pausetime";
136
137 public static final String CHANGE_VALUE_CONCURRENCY = "concurrency";
138
139 public static final String LIBPATH = "oozie.libpath";
140
141 public static final String USE_SYSTEM_LIBPATH = "oozie.use.system.libpath";
142
143 public static enum SYSTEM_MODE {
144 NORMAL, NOWEBSERVICE, SAFEMODE
145 };
146
147 /**
148 * debugMode =0 means no debugging. > 0 means debugging on.
149 */
150 public int debugMode = 0;
151
152 private String baseUrl;
153 private String protocolUrl;
154 private boolean validatedVersion = false;
155 private final Map<String, String> headers = new HashMap<String, String>();
156
157 private static ThreadLocal<String> USER_NAME_TL = new ThreadLocal<String>();
158
159 /**
160 * Allows to impersonate other users in the Oozie server. The current user
161 * must be configured as a proxyuser in Oozie.
162 * <p/>
163 * IMPORTANT: impersonation happens only with Oozie client requests done within
164 * doAs() calls.
165 *
166 * @param userName user to impersonate.
167 * @param callable callable with {@link OozieClient} calls impersonating the specified user.
168 * @return any response returned by the {@link Callable#call()} method.
169 * @throws Exception thrown by the {@link Callable#call()} method.
170 */
171 public static <T> T doAs(String userName, Callable<T> callable) throws Exception {
172 notEmpty(userName, "userName");
173 notNull(callable, "callable");
174 try {
175 USER_NAME_TL.set(userName);
176 return callable.call();
177 }
178 finally {
179 USER_NAME_TL.remove();
180 }
181 }
182
183 protected OozieClient() {
184 }
185
186 /**
187 * Create a Workflow client instance.
188 *
189 * @param oozieUrl URL of the Oozie instance it will interact with.
190 */
191 public OozieClient(String oozieUrl) {
192 this.baseUrl = notEmpty(oozieUrl, "oozieUrl");
193 if (!this.baseUrl.endsWith("/")) {
194 this.baseUrl += "/";
195 }
196 }
197
198 /**
199 * Return the Oozie URL of the workflow client instance.
200 * <p/>
201 * This URL is the base URL fo the Oozie system, with not protocol versioning.
202 *
203 * @return the Oozie URL of the workflow client instance.
204 */
205 public String getOozieUrl() {
206 return baseUrl;
207 }
208
209 /**
210 * Return the Oozie URL used by the client and server for WS communications.
211 * <p/>
212 * This URL is the original URL plus the versioning element path.
213 *
214 * @return the Oozie URL used by the client and server for communication.
215 * @throws OozieClientException thrown in the client and the server are not protocol compatible.
216 */
217 public String getProtocolUrl() throws OozieClientException {
218 validateWSVersion();
219 return protocolUrl;
220 }
221
222 /**
223 * @return current debug Mode
224 */
225 public int getDebugMode() {
226 return debugMode;
227 }
228
229 /**
230 * Set debug mode.
231 *
232 * @param debugMode : 0 means no debugging. > 0 means debugging
233 */
234 public void setDebugMode(int debugMode) {
235 this.debugMode = debugMode;
236 }
237
238 /**
239 * Validate that the Oozie client and server instances are protocol compatible.
240 *
241 * @throws OozieClientException thrown in the client and the server are not protocol compatible.
242 */
243 public synchronized void validateWSVersion() throws OozieClientException {
244 if (!validatedVersion) {
245 try {
246 URL url = new URL(baseUrl + RestConstants.VERSIONS);
247 HttpURLConnection conn = createConnection(url, "GET");
248 if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
249 JSONArray array = (JSONArray) JSONValue.parse(new InputStreamReader(conn.getInputStream()));
250 if (array == null) {
251 throw new OozieClientException("HTTP error", "no response message");
252 }
253 if (!array.contains(WS_PROTOCOL_VERSION) && !array.contains(WS_PROTOCOL_VERSION_0)) {
254 StringBuilder msg = new StringBuilder();
255 msg.append("Supported version [").append(WS_PROTOCOL_VERSION).append(
256 "] or less, Unsupported versions[");
257 String separator = "";
258 for (Object version : array) {
259 msg.append(separator).append(version);
260 }
261 msg.append("]");
262 throw new OozieClientException(OozieClientException.UNSUPPORTED_VERSION, msg.toString());
263 }
264 if (array.contains(WS_PROTOCOL_VERSION)) {
265 protocolUrl = baseUrl + "v" + WS_PROTOCOL_VERSION + "/";
266 }
267 else {
268 if (array.contains(WS_PROTOCOL_VERSION_0)) {
269 protocolUrl = baseUrl + "v" + WS_PROTOCOL_VERSION_0 + "/";
270 }
271 }
272 }
273 else {
274 handleError(conn);
275 }
276 }
277 catch (IOException ex) {
278 throw new OozieClientException(OozieClientException.IO_ERROR, ex);
279 }
280 validatedVersion = true;
281 }
282 }
283
284 /**
285 * Create an empty configuration with just the {@link #USER_NAME} set to the JVM user name.
286 *
287 * @return an empty configuration.
288 */
289 public Properties createConfiguration() {
290 Properties conf = new Properties();
291 String userName = USER_NAME_TL.get();
292 if (userName == null) {
293 userName = System.getProperty("user.name");
294 }
295 conf.setProperty(USER_NAME, userName);
296 return conf;
297 }
298
299 /**
300 * Set a HTTP header to be used in the WS requests by the workflow instance.
301 *
302 * @param name header name.
303 * @param value header value.
304 */
305 public void setHeader(String name, String value) {
306 headers.put(notEmpty(name, "name"), notNull(value, "value"));
307 }
308
309 /**
310 * Get the value of a set HTTP header from the workflow instance.
311 *
312 * @param name header name.
313 * @return header value, <code>null</code> if not set.
314 */
315 public String getHeader(String name) {
316 return headers.get(notEmpty(name, "name"));
317 }
318
319 /**
320 * Get the set HTTP header
321 *
322 * @return map of header key and value
323 */
324 public Map<String, String> getHeaders() {
325 return headers;
326 }
327
328 /**
329 * Remove a HTTP header from the workflow client instance.
330 *
331 * @param name header name.
332 */
333 public void removeHeader(String name) {
334 headers.remove(notEmpty(name, "name"));
335 }
336
337 /**
338 * Return an iterator with all the header names set in the workflow instance.
339 *
340 * @return header names.
341 */
342 public Iterator<String> getHeaderNames() {
343 return Collections.unmodifiableMap(headers).keySet().iterator();
344 }
345
346 private URL createURL(String collection, String resource, Map<String, String> parameters) throws IOException,
347 OozieClientException {
348 validateWSVersion();
349 StringBuilder sb = new StringBuilder();
350 sb.append(protocolUrl).append(collection);
351 if (resource != null && resource.length() > 0) {
352 sb.append("/").append(resource);
353 }
354 if (parameters.size() > 0) {
355 String separator = "?";
356 for (Map.Entry<String, String> param : parameters.entrySet()) {
357 if (param.getValue() != null) {
358 sb.append(separator).append(URLEncoder.encode(param.getKey(), "UTF-8")).append("=").append(
359 URLEncoder.encode(param.getValue(), "UTF-8"));
360 separator = "&";
361 }
362 }
363 }
364 return new URL(sb.toString());
365 }
366
367 private boolean validateCommand(String url) {
368 {
369 if (protocolUrl.contains(baseUrl + "v0")) {
370 if (url.contains("dryrun") || url.contains("jobtype=c") || url.contains("systemmode")) {
371 return false;
372 }
373 }
374 }
375 return true;
376 }
377
378 /**
379 * Create http connection to oozie server.
380 *
381 * @param url
382 * @param method
383 * @return connection
384 * @throws IOException
385 * @throws OozieClientException
386 */
387 protected HttpURLConnection createConnection(URL url, String method) throws IOException, OozieClientException {
388 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
389 conn.setRequestMethod(method);
390 if (method.equals("POST") || method.equals("PUT")) {
391 conn.setDoOutput(true);
392 }
393 for (Map.Entry<String, String> header : headers.entrySet()) {
394 conn.setRequestProperty(header.getKey(), header.getValue());
395 }
396 return conn;
397 }
398
399 protected abstract class ClientCallable<T> implements Callable<T> {
400 private final String method;
401 private final String collection;
402 private final String resource;
403 private final Map<String, String> params;
404
405 public ClientCallable(String method, String collection, String resource, Map<String, String> params) {
406 this.method = method;
407 this.collection = collection;
408 this.resource = resource;
409 this.params = params;
410 }
411
412 public T call() throws OozieClientException {
413 try {
414 URL url = createURL(collection, resource, params);
415 if (validateCommand(url.toString())) {
416 if (getDebugMode() > 0) {
417 System.out.println("Connection URL:[" + url + "]");
418 }
419 HttpURLConnection conn = createConnection(url, method);
420 return call(conn);
421 }
422 else {
423 System.out.println("Option not supported in target server. Supported only on Oozie-2.0 or greater."
424 + " Use 'oozie help' for details");
425 throw new OozieClientException(OozieClientException.UNSUPPORTED_VERSION, new Exception());
426 }
427 }
428 catch (IOException ex) {
429 throw new OozieClientException(OozieClientException.IO_ERROR, ex);
430 }
431
432 }
433
434 protected abstract T call(HttpURLConnection conn) throws IOException, OozieClientException;
435 }
436
437 static void handleError(HttpURLConnection conn) throws IOException, OozieClientException {
438 int status = conn.getResponseCode();
439 String error = conn.getHeaderField(RestConstants.OOZIE_ERROR_CODE);
440 String message = conn.getHeaderField(RestConstants.OOZIE_ERROR_MESSAGE);
441
442 if (error == null) {
443 error = "HTTP error code: " + status;
444 }
445
446 if (message == null) {
447 message = conn.getResponseMessage();
448 }
449 throw new OozieClientException(error, message);
450 }
451
452 static Map<String, String> prepareParams(String... params) {
453 Map<String, String> map = new LinkedHashMap<String, String>();
454 for (int i = 0; i < params.length; i = i + 2) {
455 map.put(params[i], params[i + 1]);
456 }
457 String doAsUserName = USER_NAME_TL.get();
458 if (doAsUserName != null) {
459 map.put(RestConstants.DO_AS_PARAM, doAsUserName);
460 }
461 return map;
462 }
463
464 public void writeToXml(Properties props, OutputStream out) throws IOException {
465 try {
466 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
467 Element conf = doc.createElement("configuration");
468 doc.appendChild(conf);
469 conf.appendChild(doc.createTextNode("\n"));
470 for (String name : props.stringPropertyNames()) { // Properties whose key or value is not of type String are omitted.
471 String value = props.getProperty(name);
472 Element propNode = doc.createElement("property");
473 conf.appendChild(propNode);
474
475 Element nameNode = doc.createElement("name");
476 nameNode.appendChild(doc.createTextNode(name.trim()));
477 propNode.appendChild(nameNode);
478
479 Element valueNode = doc.createElement("value");
480 valueNode.appendChild(doc.createTextNode(value.trim()));
481 propNode.appendChild(valueNode);
482
483 conf.appendChild(doc.createTextNode("\n"));
484 }
485
486 DOMSource source = new DOMSource(doc);
487 StreamResult result = new StreamResult(out);
488 TransformerFactory transFactory = TransformerFactory.newInstance();
489 Transformer transformer = transFactory.newTransformer();
490 transformer.transform(source, result);
491 }
492 catch (Exception e) {
493 throw new IOException(e);
494 }
495 }
496
497 private class JobSubmit extends ClientCallable<String> {
498 private final Properties conf;
499
500 JobSubmit(Properties conf, boolean start) {
501 super("POST", RestConstants.JOBS, "", (start) ? prepareParams(RestConstants.ACTION_PARAM,
502 RestConstants.JOB_ACTION_START) : prepareParams());
503 this.conf = notNull(conf, "conf");
504 }
505
506 JobSubmit(String jobId, Properties conf) {
507 super("PUT", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.ACTION_PARAM,
508 RestConstants.JOB_ACTION_RERUN));
509 this.conf = notNull(conf, "conf");
510 }
511
512 public JobSubmit(Properties conf, String jobActionDryrun) {
513 super("POST", RestConstants.JOBS, "", prepareParams(RestConstants.ACTION_PARAM,
514 RestConstants.JOB_ACTION_DRYRUN));
515 this.conf = notNull(conf, "conf");
516 }
517
518 @Override
519 protected String call(HttpURLConnection conn) throws IOException, OozieClientException {
520 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
521 writeToXml(conf, conn.getOutputStream());
522 if (conn.getResponseCode() == HttpURLConnection.HTTP_CREATED) {
523 JSONObject json = (JSONObject) JSONValue.parse(new InputStreamReader(conn.getInputStream()));
524 return (String) json.get(JsonTags.JOB_ID);
525 }
526 if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
527 handleError(conn);
528 }
529 return null;
530 }
531 }
532
533 /**
534 * Submit a workflow job.
535 *
536 * @param conf job configuration.
537 * @return the job Id.
538 * @throws OozieClientException thrown if the job could not be submitted.
539 */
540 public String submit(Properties conf) throws OozieClientException {
541 return (new JobSubmit(conf, false)).call();
542 }
543
544 private class JobAction extends ClientCallable<Void> {
545
546 JobAction(String jobId, String action) {
547 super("PUT", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.ACTION_PARAM, action));
548 }
549
550 JobAction(String jobId, String action, String params) {
551 super("PUT", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.ACTION_PARAM, action,
552 RestConstants.JOB_CHANGE_VALUE, params));
553 }
554
555 @Override
556 protected Void call(HttpURLConnection conn) throws IOException, OozieClientException {
557 if (!(conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
558 handleError(conn);
559 }
560 return null;
561 }
562 }
563
564 /**
565 * dryrun for a given job
566 *
567 * @param conf Job configuration.
568 */
569 public String dryrun(Properties conf) throws OozieClientException {
570 return new JobSubmit(conf, RestConstants.JOB_ACTION_DRYRUN).call();
571 }
572
573 /**
574 * Start a workflow job.
575 *
576 * @param jobId job Id.
577 * @throws OozieClientException thrown if the job could not be started.
578 */
579 public void start(String jobId) throws OozieClientException {
580 new JobAction(jobId, RestConstants.JOB_ACTION_START).call();
581 }
582
583 /**
584 * Submit and start a workflow job.
585 *
586 * @param conf job configuration.
587 * @return the job Id.
588 * @throws OozieClientException thrown if the job could not be submitted.
589 */
590 public String run(Properties conf) throws OozieClientException {
591 return (new JobSubmit(conf, true)).call();
592 }
593
594 /**
595 * Rerun a workflow job.
596 *
597 * @param jobId job Id to rerun.
598 * @param conf configuration information for the rerun.
599 * @throws OozieClientException thrown if the job could not be started.
600 */
601 public void reRun(String jobId, Properties conf) throws OozieClientException {
602 new JobSubmit(jobId, conf).call();
603 }
604
605 /**
606 * Suspend a workflow job.
607 *
608 * @param jobId job Id.
609 * @throws OozieClientException thrown if the job could not be suspended.
610 */
611 public void suspend(String jobId) throws OozieClientException {
612 new JobAction(jobId, RestConstants.JOB_ACTION_SUSPEND).call();
613 }
614
615 /**
616 * Resume a workflow job.
617 *
618 * @param jobId job Id.
619 * @throws OozieClientException thrown if the job could not be resume.
620 */
621 public void resume(String jobId) throws OozieClientException {
622 new JobAction(jobId, RestConstants.JOB_ACTION_RESUME).call();
623 }
624
625 /**
626 * Kill a workflow job.
627 *
628 * @param jobId job Id.
629 * @throws OozieClientException thrown if the job could not be killed.
630 */
631 public void kill(String jobId) throws OozieClientException {
632 new JobAction(jobId, RestConstants.JOB_ACTION_KILL).call();
633 }
634
635 /**
636 * Change a coordinator job.
637 *
638 * @param jobId job Id.
639 * @param changeValue change value.
640 * @throws OozieClientException thrown if the job could not be changed.
641 */
642 public void change(String jobId, String changeValue) throws OozieClientException {
643 new JobAction(jobId, RestConstants.JOB_ACTION_CHANGE, changeValue).call();
644 }
645
646 private class JobInfo extends ClientCallable<WorkflowJob> {
647
648 JobInfo(String jobId, int start, int len) {
649 super("GET", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.JOB_SHOW_PARAM,
650 RestConstants.JOB_SHOW_INFO, RestConstants.OFFSET_PARAM, Integer.toString(start),
651 RestConstants.LEN_PARAM, Integer.toString(len)));
652 }
653
654 @Override
655 protected WorkflowJob call(HttpURLConnection conn) throws IOException, OozieClientException {
656 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
657 Reader reader = new InputStreamReader(conn.getInputStream());
658 JSONObject json = (JSONObject) JSONValue.parse(reader);
659 return JsonToBean.createWorkflowJob(json);
660 }
661 else {
662 handleError(conn);
663 }
664 return null;
665 }
666 }
667
668 private class WorkflowActionInfo extends ClientCallable<WorkflowAction> {
669 WorkflowActionInfo(String actionId) {
670 super("GET", RestConstants.JOB, notEmpty(actionId, "id"), prepareParams(RestConstants.JOB_SHOW_PARAM,
671 RestConstants.JOB_SHOW_INFO));
672 }
673
674 @Override
675 protected WorkflowAction call(HttpURLConnection conn) throws IOException, OozieClientException {
676 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
677 Reader reader = new InputStreamReader(conn.getInputStream());
678 JSONObject json = (JSONObject) JSONValue.parse(reader);
679 return JsonToBean.createWorkflowAction(json);
680 }
681 else {
682 handleError(conn);
683 }
684 return null;
685 }
686 }
687
688 /**
689 * Get the info of a workflow job.
690 *
691 * @param jobId job Id.
692 * @return the job info.
693 * @throws OozieClientException thrown if the job info could not be retrieved.
694 */
695 public WorkflowJob getJobInfo(String jobId) throws OozieClientException {
696 return getJobInfo(jobId, 0, 0);
697 }
698
699 /**
700 * Get the info of a workflow job and subset actions.
701 *
702 * @param jobId job Id.
703 * @param start starting index in the list of actions belonging to the job
704 * @param len number of actions to be returned
705 * @return the job info.
706 * @throws OozieClientException thrown if the job info could not be retrieved.
707 */
708 public WorkflowJob getJobInfo(String jobId, int start, int len) throws OozieClientException {
709 return new JobInfo(jobId, start, len).call();
710 }
711
712 /**
713 * Get the info of a workflow action.
714 *
715 * @param actionId Id.
716 * @return the workflow action info.
717 * @throws OozieClientException thrown if the job info could not be retrieved.
718 */
719 public WorkflowAction getWorkflowActionInfo(String actionId) throws OozieClientException {
720 return new WorkflowActionInfo(actionId).call();
721 }
722
723 /**
724 * Get the log of a workflow job.
725 *
726 * @param jobId job Id.
727 * @return the job log.
728 * @throws OozieClientException thrown if the job info could not be retrieved.
729 */
730 public String getJobLog(String jobId) throws OozieClientException {
731 return new JobLog(jobId).call();
732 }
733
734 /**
735 * Get the log of a job.
736 *
737 * @param jobId job Id.
738 * @param logRetrievalType Based on which filter criteria the log is retrieved
739 * @param logRetrievalScope Value for the retrieval type
740 * @param ps Printstream of command line interface
741 * @throws OozieClientException thrown if the job info could not be retrieved.
742 */
743 public void getJobLog(String jobId, String logRetrievalType, String logRetrievalScope, PrintStream ps)
744 throws OozieClientException {
745 new JobLog(jobId, logRetrievalType, logRetrievalScope, ps).call();
746 }
747
748 private class JobLog extends JobMetadata {
749 JobLog(String jobId) {
750 super(jobId, RestConstants.JOB_SHOW_LOG);
751 }
752
753 JobLog(String jobId, String logRetrievalType, String logRetrievalScope, PrintStream ps) {
754 super(jobId, logRetrievalType, logRetrievalScope, RestConstants.JOB_SHOW_LOG, ps);
755 }
756 }
757
758 /**
759 * Get the definition of a workflow job.
760 *
761 * @param jobId job Id.
762 * @return the job log.
763 * @throws OozieClientException thrown if the job info could not be retrieved.
764 */
765 public String getJobDefinition(String jobId) throws OozieClientException {
766 return new JobDefinition(jobId).call();
767 }
768
769 private class JobDefinition extends JobMetadata {
770
771 JobDefinition(String jobId) {
772 super(jobId, RestConstants.JOB_SHOW_DEFINITION);
773 }
774 }
775
776 private class JobMetadata extends ClientCallable<String> {
777 PrintStream printStream;
778
779 JobMetadata(String jobId, String metaType) {
780 super("GET", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.JOB_SHOW_PARAM,
781 metaType));
782 }
783
784 JobMetadata(String jobId, String logRetrievalType, String logRetrievalScope, String metaType, PrintStream ps) {
785 super("GET", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.JOB_SHOW_PARAM,
786 metaType, RestConstants.JOB_LOG_TYPE_PARAM, logRetrievalType, RestConstants.JOB_LOG_SCOPE_PARAM,
787 logRetrievalScope));
788 printStream = ps;
789 }
790
791 @Override
792 protected String call(HttpURLConnection conn) throws IOException, OozieClientException {
793 String returnVal = null;
794 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
795 InputStream is = conn.getInputStream();
796 InputStreamReader isr = new InputStreamReader(is);
797 try {
798 if (printStream != null) {
799 sendToOutputStream(isr, -1);
800 }
801 else {
802 returnVal = getReaderAsString(isr, -1);
803 }
804 }
805 finally {
806 isr.close();
807 }
808 }
809 else {
810 handleError(conn);
811 }
812 return returnVal;
813 }
814
815 /**
816 * Output the log to command line interface
817 *
818 * @param reader reader to read into a string.
819 * @param maxLen max content length allowed, if -1 there is no limit.
820 * @param ps Printstream of command line interface
821 * @throws IOException
822 */
823 private void sendToOutputStream(Reader reader, int maxLen) throws IOException {
824 if (reader == null) {
825 throw new IllegalArgumentException("reader cannot be null");
826 }
827 StringBuilder sb = new StringBuilder();
828 char[] buffer = new char[2048];
829 int read;
830 int count = 0;
831 int noOfCharstoFlush = 1024;
832 while ((read = reader.read(buffer)) > -1) {
833 count += read;
834 if ((maxLen > -1) && (count > maxLen)) {
835 break;
836 }
837 sb.append(buffer, 0, read);
838 if (sb.length() > noOfCharstoFlush) {
839 printStream.print(sb.toString());
840 sb = new StringBuilder("");
841 }
842 }
843 printStream.print(sb.toString());
844 }
845
846 /**
847 * Return a reader as string.
848 * <p/>
849 *
850 * @param reader reader to read into a string.
851 * @param maxLen max content length allowed, if -1 there is no limit.
852 * @return the reader content.
853 * @throws IOException thrown if the resource could not be read.
854 */
855 private String getReaderAsString(Reader reader, int maxLen) throws IOException {
856 if (reader == null) {
857 throw new IllegalArgumentException("reader cannot be null");
858 }
859 StringBuffer sb = new StringBuffer();
860 char[] buffer = new char[2048];
861 int read;
862 int count = 0;
863 while ((read = reader.read(buffer)) > -1) {
864 count += read;
865
866 // read up to maxLen chars;
867 if ((maxLen > -1) && (count > maxLen)) {
868 break;
869 }
870 sb.append(buffer, 0, read);
871 }
872 reader.close();
873 return sb.toString();
874 }
875 }
876
877 private class CoordJobInfo extends ClientCallable<CoordinatorJob> {
878
879 CoordJobInfo(String jobId, String filter, int start, int len) {
880 super("GET", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.JOB_SHOW_PARAM,
881 RestConstants.JOB_SHOW_INFO, RestConstants.JOB_FILTER_PARAM, filter, RestConstants.OFFSET_PARAM, Integer.toString(start),
882 RestConstants.LEN_PARAM, Integer.toString(len)));
883 }
884
885 @Override
886 protected CoordinatorJob call(HttpURLConnection conn) throws IOException, OozieClientException {
887 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
888 Reader reader = new InputStreamReader(conn.getInputStream());
889 JSONObject json = (JSONObject) JSONValue.parse(reader);
890 return JsonToBean.createCoordinatorJob(json);
891 }
892 else {
893 handleError(conn);
894 }
895 return null;
896 }
897 }
898
899 private class BundleJobInfo extends ClientCallable<BundleJob> {
900
901 BundleJobInfo(String jobId) {
902 super("GET", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.JOB_SHOW_PARAM,
903 RestConstants.JOB_SHOW_INFO));
904 }
905
906 @Override
907 protected BundleJob call(HttpURLConnection conn) throws IOException, OozieClientException {
908 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
909 Reader reader = new InputStreamReader(conn.getInputStream());
910 JSONObject json = (JSONObject) JSONValue.parse(reader);
911 return JsonToBean.createBundleJob(json);
912 }
913 else {
914 handleError(conn);
915 }
916 return null;
917 }
918 }
919
920 private class CoordActionInfo extends ClientCallable<CoordinatorAction> {
921 CoordActionInfo(String actionId) {
922 super("GET", RestConstants.JOB, notEmpty(actionId, "id"), prepareParams(RestConstants.JOB_SHOW_PARAM,
923 RestConstants.JOB_SHOW_INFO));
924 }
925
926 @Override
927 protected CoordinatorAction call(HttpURLConnection conn) throws IOException, OozieClientException {
928 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
929 Reader reader = new InputStreamReader(conn.getInputStream());
930 JSONObject json = (JSONObject) JSONValue.parse(reader);
931 return JsonToBean.createCoordinatorAction(json);
932 }
933 else {
934 handleError(conn);
935 }
936 return null;
937 }
938 }
939
940 /**
941 * Get the info of a bundle job.
942 *
943 * @param jobId job Id.
944 * @return the job info.
945 * @throws OozieClientException thrown if the job info could not be retrieved.
946 */
947 public BundleJob getBundleJobInfo(String jobId) throws OozieClientException {
948 return new BundleJobInfo(jobId).call();
949 }
950
951 /**
952 * Get the info of a coordinator job.
953 *
954 * @param jobId job Id.
955 * @return the job info.
956 * @throws OozieClientException thrown if the job info could not be retrieved.
957 */
958 public CoordinatorJob getCoordJobInfo(String jobId) throws OozieClientException {
959 return new CoordJobInfo(jobId, null, 0, 0).call();
960 }
961
962 /**
963 * Get the info of a coordinator job and subset actions.
964 *
965 * @param jobId job Id.
966 * @param filter filter the status filter
967 * @param start starting index in the list of actions belonging to the job
968 * @param len number of actions to be returned
969 * @return the job info.
970 * @throws OozieClientException thrown if the job info could not be retrieved.
971 */
972 public CoordinatorJob getCoordJobInfo(String jobId, String filter, int start, int len) throws OozieClientException {
973 return new CoordJobInfo(jobId, filter, start, len).call();
974 }
975
976 /**
977 * Get the info of a coordinator action.
978 *
979 * @param actionId Id.
980 * @return the coordinator action info.
981 * @throws OozieClientException thrown if the job info could not be retrieved.
982 */
983 public CoordinatorAction getCoordActionInfo(String actionId) throws OozieClientException {
984 return new CoordActionInfo(actionId).call();
985 }
986
987 private class JobsStatus extends ClientCallable<List<WorkflowJob>> {
988
989 JobsStatus(String filter, int start, int len) {
990 super("GET", RestConstants.JOBS, "", prepareParams(RestConstants.JOBS_FILTER_PARAM, filter,
991 RestConstants.JOBTYPE_PARAM, "wf", RestConstants.OFFSET_PARAM, Integer.toString(start),
992 RestConstants.LEN_PARAM, Integer.toString(len)));
993 }
994
995 @Override
996 @SuppressWarnings("unchecked")
997 protected List<WorkflowJob> call(HttpURLConnection conn) throws IOException, OozieClientException {
998 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
999 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1000 Reader reader = new InputStreamReader(conn.getInputStream());
1001 JSONObject json = (JSONObject) JSONValue.parse(reader);
1002 JSONArray workflows = (JSONArray) json.get(JsonTags.WORKFLOWS_JOBS);
1003 if (workflows == null) {
1004 workflows = new JSONArray();
1005 }
1006 return JsonToBean.createWorkflowJobList(workflows);
1007 }
1008 else {
1009 handleError(conn);
1010 }
1011 return null;
1012 }
1013 }
1014
1015 private class CoordJobsStatus extends ClientCallable<List<CoordinatorJob>> {
1016
1017 CoordJobsStatus(String filter, int start, int len) {
1018 super("GET", RestConstants.JOBS, "", prepareParams(RestConstants.JOBS_FILTER_PARAM, filter,
1019 RestConstants.JOBTYPE_PARAM, "coord", RestConstants.OFFSET_PARAM, Integer.toString(start),
1020 RestConstants.LEN_PARAM, Integer.toString(len)));
1021 }
1022
1023 @Override
1024 protected List<CoordinatorJob> call(HttpURLConnection conn) throws IOException, OozieClientException {
1025 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
1026 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1027 Reader reader = new InputStreamReader(conn.getInputStream());
1028 JSONObject json = (JSONObject) JSONValue.parse(reader);
1029 JSONArray jobs = (JSONArray) json.get(JsonTags.COORDINATOR_JOBS);
1030 if (jobs == null) {
1031 jobs = new JSONArray();
1032 }
1033 return JsonToBean.createCoordinatorJobList(jobs);
1034 }
1035 else {
1036 handleError(conn);
1037 }
1038 return null;
1039 }
1040 }
1041
1042 private class BundleJobsStatus extends ClientCallable<List<BundleJob>> {
1043
1044 BundleJobsStatus(String filter, int start, int len) {
1045 super("GET", RestConstants.JOBS, "", prepareParams(RestConstants.JOBS_FILTER_PARAM, filter,
1046 RestConstants.JOBTYPE_PARAM, "bundle", RestConstants.OFFSET_PARAM, Integer.toString(start),
1047 RestConstants.LEN_PARAM, Integer.toString(len)));
1048 }
1049
1050 @Override
1051 protected List<BundleJob> call(HttpURLConnection conn) throws IOException, OozieClientException {
1052 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
1053 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1054 Reader reader = new InputStreamReader(conn.getInputStream());
1055 JSONObject json = (JSONObject) JSONValue.parse(reader);
1056 JSONArray jobs = (JSONArray) json.get(JsonTags.BUNDLE_JOBS);
1057 if (jobs == null) {
1058 jobs = new JSONArray();
1059 }
1060 return JsonToBean.createBundleJobList(jobs);
1061 }
1062 else {
1063 handleError(conn);
1064 }
1065 return null;
1066 }
1067 }
1068
1069 private class BulkResponseStatus extends ClientCallable<List<BulkResponse>> {
1070
1071 BulkResponseStatus(String filter, int start, int len) {
1072 super("GET", RestConstants.JOBS, "", prepareParams(RestConstants.JOBS_BULK_PARAM, filter,
1073 RestConstants.OFFSET_PARAM, Integer.toString(start), RestConstants.LEN_PARAM, Integer.toString(len)));
1074 }
1075
1076 @Override
1077 protected List<BulkResponse> call(HttpURLConnection conn) throws IOException, OozieClientException {
1078 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
1079 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1080 Reader reader = new InputStreamReader(conn.getInputStream());
1081 JSONObject json = (JSONObject) JSONValue.parse(reader);
1082 JSONArray results = (JSONArray) json.get(JsonTags.BULK_RESPONSES);
1083 if (results == null) {
1084 results = new JSONArray();
1085 }
1086 return JsonToBean.createBulkResponseList(results);
1087 }
1088 else {
1089 handleError(conn);
1090 }
1091 return null;
1092 }
1093 }
1094
1095 private class CoordRerun extends ClientCallable<List<CoordinatorAction>> {
1096
1097 CoordRerun(String jobId, String rerunType, String scope, boolean refresh, boolean noCleanup) {
1098 super("PUT", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.ACTION_PARAM,
1099 RestConstants.JOB_COORD_ACTION_RERUN, RestConstants.JOB_COORD_RERUN_TYPE_PARAM, rerunType,
1100 RestConstants.JOB_COORD_RERUN_SCOPE_PARAM, scope, RestConstants.JOB_COORD_RERUN_REFRESH_PARAM,
1101 Boolean.toString(refresh), RestConstants.JOB_COORD_RERUN_NOCLEANUP_PARAM, Boolean
1102 .toString(noCleanup)));
1103 }
1104
1105 @Override
1106 protected List<CoordinatorAction> call(HttpURLConnection conn) throws IOException, OozieClientException {
1107 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
1108 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1109 Reader reader = new InputStreamReader(conn.getInputStream());
1110 JSONObject json = (JSONObject) JSONValue.parse(reader);
1111 JSONArray coordActions = (JSONArray) json.get(JsonTags.COORDINATOR_ACTIONS);
1112 return JsonToBean.createCoordinatorActionList(coordActions);
1113 }
1114 else {
1115 handleError(conn);
1116 }
1117 return null;
1118 }
1119 }
1120
1121 private class BundleRerun extends ClientCallable<Void> {
1122
1123 BundleRerun(String jobId, String coordScope, String dateScope, boolean refresh, boolean noCleanup) {
1124 super("PUT", RestConstants.JOB, notEmpty(jobId, "jobId"), prepareParams(RestConstants.ACTION_PARAM,
1125 RestConstants.JOB_BUNDLE_ACTION_RERUN, RestConstants.JOB_BUNDLE_RERUN_COORD_SCOPE_PARAM,
1126 coordScope, RestConstants.JOB_BUNDLE_RERUN_DATE_SCOPE_PARAM, dateScope,
1127 RestConstants.JOB_COORD_RERUN_REFRESH_PARAM, Boolean.toString(refresh),
1128 RestConstants.JOB_COORD_RERUN_NOCLEANUP_PARAM, Boolean.toString(noCleanup)));
1129 }
1130
1131 @Override
1132 protected Void call(HttpURLConnection conn) throws IOException, OozieClientException {
1133 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
1134 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1135 return null;
1136 }
1137 else {
1138 handleError(conn);
1139 }
1140 return null;
1141 }
1142 }
1143
1144 /**
1145 * Rerun coordinator actions.
1146 *
1147 * @param jobId coordinator jobId
1148 * @param rerunType rerun type 'date' if -date is used, 'action-id' if -action is used
1149 * @param scope rerun scope for date or actionIds
1150 * @param refresh true if -refresh is given in command option
1151 * @param noCleanup true if -nocleanup is given in command option
1152 * @throws OozieClientException
1153 */
1154 public List<CoordinatorAction> reRunCoord(String jobId, String rerunType, String scope, boolean refresh,
1155 boolean noCleanup) throws OozieClientException {
1156 return new CoordRerun(jobId, rerunType, scope, refresh, noCleanup).call();
1157 }
1158
1159 /**
1160 * Rerun bundle coordinators.
1161 *
1162 * @param jobId bundle jobId
1163 * @param coordScope rerun scope for coordinator jobs
1164 * @param dateScope rerun scope for date
1165 * @param refresh true if -refresh is given in command option
1166 * @param noCleanup true if -nocleanup is given in command option
1167 * @throws OozieClientException
1168 */
1169 public Void reRunBundle(String jobId, String coordScope, String dateScope, boolean refresh, boolean noCleanup)
1170 throws OozieClientException {
1171 return new BundleRerun(jobId, coordScope, dateScope, refresh, noCleanup).call();
1172 }
1173
1174 /**
1175 * Return the info of the workflow jobs that match the filter.
1176 *
1177 * @param filter job filter. Refer to the {@link OozieClient} for the filter syntax.
1178 * @param start jobs offset, base 1.
1179 * @param len number of jobs to return.
1180 * @return a list with the workflow jobs info, without node details.
1181 * @throws OozieClientException thrown if the jobs info could not be retrieved.
1182 */
1183 public List<WorkflowJob> getJobsInfo(String filter, int start, int len) throws OozieClientException {
1184 return new JobsStatus(filter, start, len).call();
1185 }
1186
1187 /**
1188 * Return the info of the workflow jobs that match the filter.
1189 * <p/>
1190 * It returns the first 100 jobs that match the filter.
1191 *
1192 * @param filter job filter. Refer to the {@link OozieClient} for the filter syntax.
1193 * @return a list with the workflow jobs info, without node details.
1194 * @throws OozieClientException thrown if the jobs info could not be retrieved.
1195 */
1196 public List<WorkflowJob> getJobsInfo(String filter) throws OozieClientException {
1197 return getJobsInfo(filter, 1, 50);
1198 }
1199
1200 /**
1201 * Print sla info about coordinator and workflow jobs and actions.
1202 *
1203 * @param start starting offset
1204 * @param len number of results
1205 * @throws OozieClientException
1206 */
1207 public void getSlaInfo(int start, int len, String filter) throws OozieClientException {
1208 new SlaInfo(start, len, filter).call();
1209 }
1210
1211 private class SlaInfo extends ClientCallable<Void> {
1212
1213 SlaInfo(int start, int len, String filter) {
1214 super("GET", RestConstants.SLA, "", prepareParams(RestConstants.SLA_GT_SEQUENCE_ID,
1215 Integer.toString(start), RestConstants.MAX_EVENTS, Integer.toString(len),
1216 RestConstants.JOBS_FILTER_PARAM, filter));
1217 }
1218
1219 @Override
1220 @SuppressWarnings("unchecked")
1221 protected Void call(HttpURLConnection conn) throws IOException, OozieClientException {
1222 conn.setRequestProperty("content-type", RestConstants.XML_CONTENT_TYPE);
1223 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1224 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
1225 String line = null;
1226 while ((line = br.readLine()) != null) {
1227 System.out.println(line);
1228 }
1229 }
1230 else {
1231 handleError(conn);
1232 }
1233 return null;
1234 }
1235 }
1236
1237 private class JobIdAction extends ClientCallable<String> {
1238
1239 JobIdAction(String externalId) {
1240 super("GET", RestConstants.JOBS, "", prepareParams(RestConstants.JOBTYPE_PARAM, "wf",
1241 RestConstants.JOBS_EXTERNAL_ID_PARAM, externalId));
1242 }
1243
1244 @Override
1245 @SuppressWarnings("unchecked")
1246 protected String call(HttpURLConnection conn) throws IOException, OozieClientException {
1247 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1248 Reader reader = new InputStreamReader(conn.getInputStream());
1249 JSONObject json = (JSONObject) JSONValue.parse(reader);
1250 return (String) json.get(JsonTags.JOB_ID);
1251 }
1252 else {
1253 handleError(conn);
1254 }
1255 return null;
1256 }
1257 }
1258
1259 /**
1260 * Return the workflow job Id for an external Id.
1261 * <p/>
1262 * The external Id must have provided at job creation time.
1263 *
1264 * @param externalId external Id given at job creation time.
1265 * @return the workflow job Id for an external Id, <code>null</code> if none.
1266 * @throws OozieClientException thrown if the operation could not be done.
1267 */
1268 public String getJobId(String externalId) throws OozieClientException {
1269 return new JobIdAction(externalId).call();
1270 }
1271
1272 private class SetSystemMode extends ClientCallable<Void> {
1273
1274 public SetSystemMode(SYSTEM_MODE status) {
1275 super("PUT", RestConstants.ADMIN, RestConstants.ADMIN_STATUS_RESOURCE, prepareParams(
1276 RestConstants.ADMIN_SYSTEM_MODE_PARAM, status + ""));
1277 }
1278
1279 @Override
1280 public Void call(HttpURLConnection conn) throws IOException, OozieClientException {
1281 if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
1282 handleError(conn);
1283 }
1284 return null;
1285 }
1286 }
1287
1288 /**
1289 * Enable or disable safe mode. Used by OozieCLI. In safe mode, Oozie would not accept any commands except status
1290 * command to change and view the safe mode status.
1291 *
1292 * @param status true to enable safe mode, false to disable safe mode.
1293 * @throws OozieClientException if it fails to set the safe mode status.
1294 */
1295 public void setSystemMode(SYSTEM_MODE status) throws OozieClientException {
1296 new SetSystemMode(status).call();
1297 }
1298
1299 private class GetSystemMode extends ClientCallable<SYSTEM_MODE> {
1300
1301 GetSystemMode() {
1302 super("GET", RestConstants.ADMIN, RestConstants.ADMIN_STATUS_RESOURCE, prepareParams());
1303 }
1304
1305 @Override
1306 protected SYSTEM_MODE call(HttpURLConnection conn) throws IOException, OozieClientException {
1307 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1308 Reader reader = new InputStreamReader(conn.getInputStream());
1309 JSONObject json = (JSONObject) JSONValue.parse(reader);
1310 return SYSTEM_MODE.valueOf((String) json.get(JsonTags.OOZIE_SYSTEM_MODE));
1311 }
1312 else {
1313 handleError(conn);
1314 }
1315 return SYSTEM_MODE.NORMAL;
1316 }
1317 }
1318
1319 /**
1320 * Returns if Oozie is in safe mode or not.
1321 *
1322 * @return true if safe mode is ON<br>
1323 * false if safe mode is OFF
1324 * @throws OozieClientException throw if it could not obtain the safe mode status.
1325 */
1326 /*
1327 * public boolean isInSafeMode() throws OozieClientException { return new GetSafeMode().call(); }
1328 */
1329 public SYSTEM_MODE getSystemMode() throws OozieClientException {
1330 return new GetSystemMode().call();
1331 }
1332
1333 private class GetBuildVersion extends ClientCallable<String> {
1334
1335 GetBuildVersion() {
1336 super("GET", RestConstants.ADMIN, RestConstants.ADMIN_BUILD_VERSION_RESOURCE, prepareParams());
1337 }
1338
1339 @Override
1340 protected String call(HttpURLConnection conn) throws IOException, OozieClientException {
1341 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1342 Reader reader = new InputStreamReader(conn.getInputStream());
1343 JSONObject json = (JSONObject) JSONValue.parse(reader);
1344 return (String) json.get(JsonTags.BUILD_VERSION);
1345 }
1346 else {
1347 handleError(conn);
1348 }
1349 return null;
1350 }
1351 }
1352
1353 /**
1354 * Return the Oozie server build version.
1355 *
1356 * @return the Oozie server build version.
1357 * @throws OozieClientException throw if it the server build version could not be retrieved.
1358 */
1359 public String getServerBuildVersion() throws OozieClientException {
1360 return new GetBuildVersion().call();
1361 }
1362
1363 /**
1364 * Return the Oozie client build version.
1365 *
1366 * @return the Oozie client build version.
1367 */
1368 public String getClientBuildVersion() {
1369 return BuildInfo.getBuildInfo().getProperty(BuildInfo.BUILD_VERSION);
1370 }
1371
1372 /**
1373 * Return the info of the coordinator jobs that match the filter.
1374 *
1375 * @param filter job filter. Refer to the {@link OozieClient} for the filter syntax.
1376 * @param start jobs offset, base 1.
1377 * @param len number of jobs to return.
1378 * @return a list with the coordinator jobs info
1379 * @throws OozieClientException thrown if the jobs info could not be retrieved.
1380 */
1381 public List<CoordinatorJob> getCoordJobsInfo(String filter, int start, int len) throws OozieClientException {
1382 return new CoordJobsStatus(filter, start, len).call();
1383 }
1384
1385 /**
1386 * Return the info of the bundle jobs that match the filter.
1387 *
1388 * @param filter job filter. Refer to the {@link OozieClient} for the filter syntax.
1389 * @param start jobs offset, base 1.
1390 * @param len number of jobs to return.
1391 * @return a list with the bundle jobs info
1392 * @throws OozieClientException thrown if the jobs info could not be retrieved.
1393 */
1394 public List<BundleJob> getBundleJobsInfo(String filter, int start, int len) throws OozieClientException {
1395 return new BundleJobsStatus(filter, start, len).call();
1396 }
1397
1398 public List<BulkResponse> getBulkInfo(String filter, int start, int len) throws OozieClientException {
1399 return new BulkResponseStatus(filter, start, len).call();
1400 }
1401
1402 private class GetQueueDump extends ClientCallable<List<String>> {
1403 GetQueueDump() {
1404 super("GET", RestConstants.ADMIN, RestConstants.ADMIN_QUEUE_DUMP_RESOURCE, prepareParams());
1405 }
1406
1407 @Override
1408 protected List<String> call(HttpURLConnection conn) throws IOException, OozieClientException {
1409 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) {
1410 Reader reader = new InputStreamReader(conn.getInputStream());
1411 JSONObject json = (JSONObject) JSONValue.parse(reader);
1412 JSONArray queueDumpArray = (JSONArray) json.get(JsonTags.QUEUE_DUMP);
1413
1414 List<String> list = new ArrayList<String>();
1415 list.add("[Server Queue Dump]:");
1416 for (Object o : queueDumpArray) {
1417 JSONObject entry = (JSONObject) o;
1418 if (entry.get(JsonTags.CALLABLE_DUMP) != null) {
1419 String value = (String) entry.get(JsonTags.CALLABLE_DUMP);
1420 list.add(value);
1421 }
1422 }
1423 if (queueDumpArray.size() == 0) {
1424 list.add("Queue dump is null!");
1425 }
1426
1427 list.add("******************************************");
1428 list.add("[Server Uniqueness Map Dump]:");
1429
1430 JSONArray uniqueDumpArray = (JSONArray) json.get(JsonTags.UNIQUE_MAP_DUMP);
1431 for (Object o : uniqueDumpArray) {
1432 JSONObject entry = (JSONObject) o;
1433 if (entry.get(JsonTags.UNIQUE_ENTRY_DUMP) != null) {
1434 String value = (String) entry.get(JsonTags.UNIQUE_ENTRY_DUMP);
1435 list.add(value);
1436 }
1437 }
1438 if (uniqueDumpArray.size() == 0) {
1439 list.add("Uniqueness dump is null!");
1440 }
1441 return list;
1442 }
1443 else {
1444 handleError(conn);
1445 }
1446 return null;
1447 }
1448 }
1449
1450 /**
1451 * Return the Oozie queue's commands' dump
1452 *
1453 * @return the list of strings of callable identification in queue
1454 * @throws OozieClientException throw if it the queue dump could not be retrieved.
1455 */
1456 public List<String> getQueueDump() throws OozieClientException {
1457 return new GetQueueDump().call();
1458 }
1459
1460 /**
1461 * Check if the string is not null or not empty.
1462 *
1463 * @param str
1464 * @param name
1465 * @return string
1466 */
1467 public static String notEmpty(String str, String name) {
1468 if (str == null) {
1469 throw new IllegalArgumentException(name + " cannot be null");
1470 }
1471 if (str.length() == 0) {
1472 throw new IllegalArgumentException(name + " cannot be empty");
1473 }
1474 return str;
1475 }
1476
1477 /**
1478 * Check if the object is not null.
1479 *
1480 * @param <T>
1481 * @param obj
1482 * @param name
1483 * @return string
1484 */
1485 public static <T> T notNull(T obj, String name) {
1486 if (obj == null) {
1487 throw new IllegalArgumentException(name + " cannot be null");
1488 }
1489 return obj;
1490 }
1491
1492 }