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