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