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 019package org.apache.oozie.executor.jpa; 020 021import java.sql.Timestamp; 022import java.util.ArrayList; 023import java.util.Date; 024import java.util.List; 025 026import javax.persistence.EntityManager; 027import javax.persistence.Query; 028 029import org.apache.oozie.CoordinatorActionBean; 030import org.apache.oozie.CoordinatorJobBean; 031import org.apache.oozie.ErrorCode; 032import org.apache.oozie.StringBlob; 033import org.apache.oozie.service.JPAService; 034import org.apache.oozie.service.Services; 035import org.apache.oozie.util.DateUtils; 036 037/** 038 * Query Executor that provides API to run query for Coordinator Job 039 */ 040 041public class CoordJobQueryExecutor extends QueryExecutor<CoordinatorJobBean, CoordJobQueryExecutor.CoordJobQuery> { 042 043 public enum CoordJobQuery { 044 UPDATE_COORD_JOB, 045 UPDATE_COORD_JOB_STATUS, 046 UPDATE_COORD_JOB_BUNDLEID, 047 UPDATE_COORD_JOB_APPNAMESPACE, 048 UPDATE_COORD_JOB_STATUS_PENDING, 049 UPDATE_COORD_JOB_BUNDLEID_APPNAMESPACE_PAUSETIME, 050 UPDATE_COORD_JOB_STATUS_MODTIME, 051 UPDATE_COORD_JOB_STATUS_PENDING_MODTIME, 052 UPDATE_COORD_JOB_LAST_MODIFIED_TIME, 053 UPDATE_COORD_JOB_STATUS_PENDING_TIME, 054 UPDATE_COORD_JOB_MATERIALIZE, 055 UPDATE_COORD_JOB_CHANGE, 056 GET_COORD_JOB, 057 GET_COORD_JOB_USER_APPNAME, 058 GET_COORD_JOB_INPUT_CHECK, 059 GET_COORD_JOB_ACTION_READY, 060 GET_COORD_JOB_ACTION_KILL, 061 GET_COORD_JOB_MATERIALIZE, 062 GET_COORD_JOB_SUSPEND_KILL, 063 GET_COORD_JOB_STATUS, 064 GET_COORD_JOB_STATUS_PARENTID, 065 GET_COORD_JOBS_CHANGED, 066 GET_COORD_JOBS_OLDER_FOR_MATERILZATION, 067 GET_COORD_FOR_ABANDONEDCHECK, 068 GET_COORD_IDS_FOR_STATUS_TRANSIT 069 }; 070 071 private static CoordJobQueryExecutor instance = new CoordJobQueryExecutor(); 072 073 private CoordJobQueryExecutor() { 074 } 075 076 public static CoordJobQueryExecutor getInstance() { 077 return CoordJobQueryExecutor.instance; 078 } 079 080 @Override 081 public Query getUpdateQuery(CoordJobQuery namedQuery, CoordinatorJobBean cjBean, EntityManager em) 082 throws JPAExecutorException { 083 Query query = em.createNamedQuery(namedQuery.name()); 084 switch (namedQuery) { 085 case UPDATE_COORD_JOB: 086 query.setParameter("appName", cjBean.getAppName()); 087 query.setParameter("appPath", cjBean.getAppPath()); 088 query.setParameter("concurrency", cjBean.getConcurrency()); 089 query.setParameter("conf", cjBean.getConfBlob()); 090 query.setParameter("externalId", cjBean.getExternalId()); 091 query.setParameter("frequency", cjBean.getFrequency()); 092 query.setParameter("lastActionNumber", cjBean.getLastActionNumber()); 093 query.setParameter("timeOut", cjBean.getTimeout()); 094 query.setParameter("timeZone", cjBean.getTimeZone()); 095 query.setParameter("createdTime", cjBean.getCreatedTimestamp()); 096 query.setParameter("endTime", cjBean.getEndTimestamp()); 097 query.setParameter("execution", cjBean.getExecution()); 098 query.setParameter("jobXml", cjBean.getJobXmlBlob()); 099 query.setParameter("lastAction", cjBean.getLastActionTimestamp()); 100 query.setParameter("lastModifiedTime", cjBean.getLastModifiedTimestamp()); 101 query.setParameter("nextMaterializedTime", cjBean.getNextMaterializedTimestamp()); 102 query.setParameter("origJobXml", cjBean.getOrigJobXmlBlob()); 103 query.setParameter("slaXml", cjBean.getSlaXmlBlob()); 104 query.setParameter("startTime", cjBean.getStartTimestamp()); 105 query.setParameter("status", cjBean.getStatus().toString()); 106 query.setParameter("timeUnit", cjBean.getTimeUnitStr()); 107 query.setParameter("appNamespace", cjBean.getAppNamespace()); 108 query.setParameter("bundleId", cjBean.getBundleId()); 109 query.setParameter("matThrottling", cjBean.getMatThrottling()); 110 query.setParameter("id", cjBean.getId()); 111 break; 112 case UPDATE_COORD_JOB_STATUS: 113 query.setParameter("status", cjBean.getStatus().toString()); 114 query.setParameter("id", cjBean.getId()); 115 break; 116 case UPDATE_COORD_JOB_BUNDLEID: 117 query.setParameter("bundleId", cjBean.getBundleId()); 118 query.setParameter("id", cjBean.getId()); 119 break; 120 case UPDATE_COORD_JOB_APPNAMESPACE: 121 query.setParameter("appNamespace", cjBean.getAppNamespace()); 122 query.setParameter("id", cjBean.getId()); 123 break; 124 case UPDATE_COORD_JOB_STATUS_PENDING: 125 query.setParameter("status", cjBean.getStatus().toString()); 126 query.setParameter("pending", cjBean.isPending() ? 1 : 0); 127 query.setParameter("id", cjBean.getId()); 128 break; 129 case UPDATE_COORD_JOB_BUNDLEID_APPNAMESPACE_PAUSETIME: 130 query.setParameter("bundleId", cjBean.getBundleId()); 131 query.setParameter("appNamespace", cjBean.getAppNamespace()); 132 query.setParameter("pauseTime", cjBean.getPauseTimestamp()); 133 query.setParameter("id", cjBean.getId()); 134 break; 135 case UPDATE_COORD_JOB_STATUS_MODTIME: 136 query.setParameter("status", cjBean.getStatus().toString()); 137 query.setParameter("lastModifiedTime", cjBean.getLastModifiedTimestamp()); 138 query.setParameter("id", cjBean.getId()); 139 break; 140 case UPDATE_COORD_JOB_STATUS_PENDING_MODTIME: 141 query.setParameter("status", cjBean.getStatus().toString()); 142 query.setParameter("pending", cjBean.isPending() ? 1 : 0); 143 query.setParameter("lastModifiedTime", cjBean.getLastModifiedTimestamp()); 144 query.setParameter("id", cjBean.getId()); 145 break; 146 case UPDATE_COORD_JOB_LAST_MODIFIED_TIME: 147 query.setParameter("lastModifiedTime", cjBean.getLastModifiedTimestamp()); 148 query.setParameter("id", cjBean.getId()); 149 break; 150 case UPDATE_COORD_JOB_STATUS_PENDING_TIME: 151 query.setParameter("status", cjBean.getStatus().toString()); 152 query.setParameter("pending", cjBean.isPending() ? 1 : 0); 153 query.setParameter("doneMaterialization", cjBean.isDoneMaterialization() ? 1 : 0); 154 query.setParameter("lastModifiedTime", cjBean.getLastModifiedTimestamp()); 155 query.setParameter("suspendedTime", cjBean.getSuspendedTimestamp()); 156 query.setParameter("id", cjBean.getId()); 157 break; 158 case UPDATE_COORD_JOB_MATERIALIZE: 159 query.setParameter("status", cjBean.getStatus().toString()); 160 query.setParameter("pending", cjBean.isPending() ? 1 : 0); 161 query.setParameter("doneMaterialization", cjBean.isDoneMaterialization() ? 1 : 0); 162 query.setParameter("lastActionTime", cjBean.getLastActionTimestamp()); 163 query.setParameter("lastActionNumber", cjBean.getLastActionNumber()); 164 query.setParameter("nextMatdTime", cjBean.getNextMaterializedTimestamp()); 165 query.setParameter("id", cjBean.getId()); 166 break; 167 case UPDATE_COORD_JOB_CHANGE: 168 query.setParameter("endTime", cjBean.getEndTimestamp()); 169 query.setParameter("status", cjBean.getStatus().toString()); 170 query.setParameter("pending", cjBean.isPending() ? 1 : 0); 171 query.setParameter("doneMaterialization", cjBean.isDoneMaterialization() ? 1 : 0); 172 query.setParameter("concurrency", cjBean.getConcurrency()); 173 query.setParameter("pauseTime", cjBean.getPauseTimestamp()); 174 query.setParameter("lastActionNumber", cjBean.getLastActionNumber()); 175 query.setParameter("lastActionTime", cjBean.getLastActionTimestamp()); 176 query.setParameter("nextMatdTime", cjBean.getNextMaterializedTimestamp()); 177 query.setParameter("lastModifiedTime", cjBean.getLastModifiedTimestamp()); 178 query.setParameter("id", cjBean.getId()); 179 break; 180 default: 181 throw new JPAExecutorException(ErrorCode.E0603, "QueryExecutor cannot set parameters for " 182 + namedQuery.name()); 183 } 184 return query; 185 } 186 187 @Override 188 public Query getSelectQuery(CoordJobQuery namedQuery, EntityManager em, Object... parameters) 189 throws JPAExecutorException { 190 Query query = em.createNamedQuery(namedQuery.name()); 191 switch (namedQuery) { 192 case GET_COORD_JOB: 193 case GET_COORD_JOB_USER_APPNAME: 194 case GET_COORD_JOB_INPUT_CHECK: 195 case GET_COORD_JOB_ACTION_READY: 196 case GET_COORD_JOB_ACTION_KILL: 197 case GET_COORD_JOB_MATERIALIZE: 198 case GET_COORD_JOB_SUSPEND_KILL: 199 case GET_COORD_JOB_STATUS: 200 case GET_COORD_JOB_STATUS_PARENTID: 201 query.setParameter("id", parameters[0]); 202 break; 203 case GET_COORD_JOBS_CHANGED: 204 query.setParameter("lastModifiedTime", new Timestamp(((Date)parameters[0]).getTime())); 205 break; 206 case GET_COORD_JOBS_OLDER_FOR_MATERILZATION: 207 query.setParameter("matTime", new Timestamp(((Date)parameters[0]).getTime())); 208 int limit = (Integer) parameters[1]; 209 if (limit > 0) { 210 query.setMaxResults(limit); 211 } 212 break; 213 case GET_COORD_FOR_ABANDONEDCHECK: 214 query.setParameter(1, (Integer) parameters[0]); 215 query.setParameter(2, (Timestamp) parameters[1]); 216 break; 217 218 case GET_COORD_IDS_FOR_STATUS_TRANSIT: 219 query.setParameter("lastModifiedTime", new Timestamp(((Date) parameters[0]).getTime())); 220 break; 221 222 default: 223 throw new JPAExecutorException(ErrorCode.E0603, "QueryExecutor cannot set parameters for " 224 + namedQuery.name()); 225 } 226 return query; 227 } 228 229 @Override 230 public int executeUpdate(CoordJobQuery namedQuery, CoordinatorJobBean jobBean) throws JPAExecutorException { 231 JPAService jpaService = Services.get().get(JPAService.class); 232 EntityManager em = jpaService.getEntityManager(); 233 Query query = getUpdateQuery(namedQuery, jobBean, em); 234 int ret = jpaService.executeUpdate(namedQuery.name(), query, em); 235 return ret; 236 } 237 238 private CoordinatorJobBean constructBean(CoordJobQuery namedQuery, Object ret, Object... parameters) 239 throws JPAExecutorException { 240 CoordinatorJobBean bean; 241 Object[] arr; 242 switch (namedQuery) { 243 case GET_COORD_JOB: 244 bean = (CoordinatorJobBean) ret; 245 break; 246 case GET_COORD_JOB_USER_APPNAME: 247 bean = new CoordinatorJobBean(); 248 arr = (Object[]) ret; 249 bean.setUser((String) arr[0]); 250 bean.setAppName((String) arr[1]); 251 break; 252 case GET_COORD_JOB_INPUT_CHECK: 253 bean = new CoordinatorJobBean(); 254 arr = (Object[]) ret; 255 bean.setUser((String) arr[0]); 256 bean.setAppName((String) arr[1]); 257 bean.setStatusStr((String) arr[2]); 258 bean.setAppNamespace((String) arr[3]); 259 bean.setExecution((String) arr[4]); 260 bean.setFrequency((String) arr[5]); 261 bean.setTimeUnitStr((String) arr[6]); 262 bean.setTimeZone((String) arr[7]); 263 bean.setStartTime(DateUtils.toDate((Timestamp) arr[8])); 264 bean.setEndTime(DateUtils.toDate((Timestamp) arr[9])); 265 bean.setJobXmlBlob((StringBlob) arr[10]); 266 break; 267 case GET_COORD_JOB_ACTION_READY: 268 bean = new CoordinatorJobBean(); 269 arr = (Object[]) ret; 270 bean.setId((String) arr[0]); 271 bean.setUser((String) arr[1]); 272 bean.setGroup((String) arr[2]); 273 bean.setAppName((String) arr[3]); 274 bean.setStatusStr((String) arr[4]); 275 bean.setExecution((String) arr[5]); 276 bean.setConcurrency((Integer) arr[6]); 277 bean.setFrequency((String) arr[7]); 278 bean.setTimeUnitStr((String) arr[8]); 279 bean.setTimeZone((String) arr[9]); 280 bean.setStartTime(DateUtils.toDate((Timestamp) arr[10])); 281 bean.setEndTime(DateUtils.toDate((Timestamp) arr[11])); 282 bean.setJobXmlBlob((StringBlob) arr[12]); 283 break; 284 case GET_COORD_JOB_ACTION_KILL: 285 bean = new CoordinatorJobBean(); 286 arr = (Object[]) ret; 287 bean.setId((String) arr[0]); 288 bean.setUser((String) arr[1]); 289 bean.setGroup((String) arr[2]); 290 bean.setAppName((String) arr[3]); 291 bean.setStatusStr((String) arr[4]); 292 break; 293 case GET_COORD_JOB_MATERIALIZE: 294 bean = new CoordinatorJobBean(); 295 arr = (Object[]) ret; 296 bean.setId((String) arr[0]); 297 bean.setUser((String) arr[1]); 298 bean.setGroup((String) arr[2]); 299 bean.setAppName((String) arr[3]); 300 bean.setStatusStr((String) arr[4]); 301 bean.setFrequency((String) arr[5]); 302 bean.setMatThrottling((Integer) arr[6]); 303 bean.setTimeout((Integer) arr[7]); 304 bean.setTimeZone((String) arr[8]); 305 bean.setStartTime(DateUtils.toDate((Timestamp) arr[9])); 306 bean.setEndTime(DateUtils.toDate((Timestamp) arr[10])); 307 bean.setPauseTime(DateUtils.toDate((Timestamp) arr[11])); 308 bean.setNextMaterializedTime(DateUtils.toDate((Timestamp) arr[12])); 309 bean.setLastActionTime(DateUtils.toDate((Timestamp) arr[13])); 310 bean.setLastActionNumber((Integer) arr[14]); 311 bean.setDoneMaterialization((Integer) arr[15]); 312 bean.setBundleId((String) arr[16]); 313 bean.setConfBlob((StringBlob) arr[17]); 314 bean.setJobXmlBlob((StringBlob) arr[18]); 315 bean.setAppNamespace((String) arr[19]); 316 bean.setTimeUnitStr((String) arr[20]); 317 bean.setExecution((String) arr[21]); 318 break; 319 case GET_COORD_JOB_SUSPEND_KILL: 320 bean = new CoordinatorJobBean(); 321 arr = (Object[]) ret; 322 bean.setId((String) arr[0]); 323 bean.setUser((String) arr[1]); 324 bean.setGroup((String) arr[2]); 325 bean.setAppName((String) arr[3]); 326 bean.setStatusStr((String) arr[4]); 327 bean.setBundleId((String) arr[5]); 328 bean.setAppNamespace((String) arr[6]); 329 bean.setDoneMaterialization((Integer) arr[7]); 330 break; 331 case GET_COORD_JOB_STATUS: 332 bean = new CoordinatorJobBean(); 333 bean.setId((String) parameters[0]); 334 bean.setStatusStr((String) ret); 335 break; 336 case GET_COORD_JOB_STATUS_PARENTID: 337 bean = new CoordinatorJobBean(); 338 arr = (Object[]) ret; 339 bean.setId((String) parameters[0]); 340 bean.setStatusStr((String) arr[0]); 341 bean.setBundleId((String) arr[1]); 342 break; 343 case GET_COORD_JOBS_CHANGED: 344 bean = (CoordinatorJobBean) ret; 345 break; 346 case GET_COORD_JOBS_OLDER_FOR_MATERILZATION: 347 bean = new CoordinatorJobBean(); 348 bean.setId((String) ret); 349 break; 350 case GET_COORD_FOR_ABANDONEDCHECK: 351 bean = new CoordinatorJobBean(); 352 arr = (Object[]) ret; 353 bean.setId((String) arr[0]); 354 bean.setUser((String) arr[1]); 355 bean.setGroup((String) arr[2]); 356 bean.setAppName((String) arr[3]); 357 break; 358 359 case GET_COORD_IDS_FOR_STATUS_TRANSIT: 360 bean = new CoordinatorJobBean(); 361 bean.setId((String) ret); 362 break; 363 364 default: 365 throw new JPAExecutorException(ErrorCode.E0603, "QueryExecutor cannot construct job bean for " 366 + namedQuery.name()); 367 } 368 return bean; 369 } 370 371 @Override 372 public CoordinatorJobBean get(CoordJobQuery namedQuery, Object... parameters) throws JPAExecutorException { 373 JPAService jpaService = Services.get().get(JPAService.class); 374 EntityManager em = jpaService.getEntityManager(); 375 Query query = getSelectQuery(namedQuery, em, parameters); 376 Object ret = jpaService.executeGet(namedQuery.name(), query, em); 377 if (ret == null) { 378 throw new JPAExecutorException(ErrorCode.E0604, query.toString()); 379 } 380 CoordinatorJobBean bean = constructBean(namedQuery, ret, parameters); 381 return bean; 382 } 383 384 @Override 385 public List<CoordinatorJobBean> getList(CoordJobQuery namedQuery, Object... parameters) throws JPAExecutorException { 386 JPAService jpaService = Services.get().get(JPAService.class); 387 EntityManager em = jpaService.getEntityManager(); 388 Query query = getSelectQuery(namedQuery, em, parameters); 389 List<?> retList = (List<?>) jpaService.executeGetList(namedQuery.name(), query, em); 390 List<CoordinatorJobBean> beanList = new ArrayList<CoordinatorJobBean>(); 391 if (retList != null) { 392 for (Object ret : retList) { 393 beanList.add(constructBean(namedQuery, ret, parameters)); 394 } 395 } 396 return beanList; 397 } 398 399 @Override 400 public Object getSingleValue(CoordJobQuery namedQuery, Object... parameters) throws JPAExecutorException { 401 throw new UnsupportedOperationException(); 402 } 403}