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