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    
019    package org.apache.oozie.util;
020    
021    import java.text.ParseException;
022    import java.util.ArrayList;
023    import java.util.Date;
024    import java.util.HashSet;
025    import java.util.List;
026    import java.util.Set;
027    
028    import org.apache.oozie.CoordinatorActionBean;
029    import org.apache.oozie.ErrorCode;
030    import org.apache.oozie.XException;
031    import org.apache.oozie.executor.jpa.CoordJobGetActionIdsForDateRangeJPAExecutor;
032    import org.apache.oozie.executor.jpa.CoordJobGetActionsForDatesJPAExecutor;
033    import org.apache.oozie.service.JPAService;
034    import org.apache.oozie.service.Services;
035    
036    /**
037     * This class provides the utility of listing
038     * coordinator actions that were executed between a certain
039     * date range. This is helpful in turn for retrieving the
040     * required logs in that date range.
041     */
042    public class CoordActionsInDateRange {
043    
044        /**
045         * Get the list of Coordinator action Ids for given date ranges
046         *
047         * @param jobId coordinator job id
048         * @param scope the date range for log. format is comma-separated list of date ranges. Each date range element is specified with two dates separated by '::'
049         * @return the list of coordinator action Ids for the date range
050         *
051         * Internally involves a database operation by invoking method 'getActionIdsFromDateRange'.
052         */
053        public static List<String> getCoordActionIdsFromDates(String jobId, String scope) throws XException {
054            ParamChecker.notEmpty(jobId, "jobId");
055            ParamChecker.notEmpty(scope, "scope");
056            Set<String> actionSet = new HashSet<String>();
057            String[] list = scope.split(",");
058            for (String s : list) {
059                s = s.trim();
060                if (s.contains("::")) {
061                    List<String> listOfActions = getCoordActionIdsFromDateRange(jobId, s);
062                    actionSet.addAll(listOfActions);
063                }
064                else {
065                    throw new XException(ErrorCode.E0308, "'" + s + "'. Separator '::' is missing for start and end dates of range");
066                }
067            }
068            return new ArrayList<String>(actionSet);
069        }
070    
071        /**
072         * Get the coordinator actions for a given date range
073         * @param jobId the coordinator job id
074         * @param range the date range separated by '::'
075         * @return the list of Coordinator actions for the date range
076         * @throws XException
077         */
078        public static List<CoordinatorActionBean> getCoordActionsFromDateRange(String jobId, String range) throws XException{
079                String[] dateRange = range.split("::");
080                // This block checks for errors in the format of specifying date range
081                if (dateRange.length != 2) {
082                    throw new XException(ErrorCode.E0308, "'" + range + "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
083                }
084                Date start;
085                Date end;
086                try {
087                // Get the start and end dates for the range
088                    start = DateUtils.parseDateOozieTZ(dateRange[0].trim());
089                    end = DateUtils.parseDateOozieTZ(dateRange[1].trim());
090                }
091                catch (ParseException dx) {
092                    throw new XException(ErrorCode.E0308, "Error in parsing start or end date. " + dx);
093                }
094                if (start.after(end)) {
095                    throw new XException(ErrorCode.E0308, "'" + range + "'. Start date '" + start + "' is older than end date: '" + end + "'");
096                }
097                List<CoordinatorActionBean> listOfActions = getActionsFromDateRange(jobId, start, end);
098                return listOfActions;
099        }
100    
101        /**
102         * Get the coordinator actions for a given date range
103         * @param jobId the coordinator job id
104         * @param range the date range separated by '::'
105         * @return the list of Coordinator actions for the date range
106         * @throws XException
107         */
108        public static List<String> getCoordActionIdsFromDateRange(String jobId, String range) throws XException{
109                String[] dateRange = range.split("::");
110                // This block checks for errors in the format of specifying date range
111                if (dateRange.length != 2) {
112                    throw new XException(ErrorCode.E0308, "'" + range + "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
113                }
114                Date start;
115                Date end;
116                try {
117                // Get the start and end dates for the range
118                    start = DateUtils.parseDateOozieTZ(dateRange[0].trim());
119                    end = DateUtils.parseDateOozieTZ(dateRange[1].trim());
120                }
121                catch (ParseException dx) {
122                    throw new XException(ErrorCode.E0308, "Error in parsing start or end date. " + dx);
123                }
124                if (start.after(end)) {
125                    throw new XException(ErrorCode.E0308, "'" + range + "'. Start date '" + start + "' is older than end date: '" + end + "'");
126                }
127                List<String> list = null;
128                JPAService jpaService = Services.get().get(JPAService.class);
129                list = jpaService.execute(new CoordJobGetActionIdsForDateRangeJPAExecutor(jobId, start, end));
130                return list;
131        }
132    
133        /*
134         * Get coordinator action ids between given start and end time
135         *
136         * @param jobId coordinator job id
137         * @param start start time
138         * @param end end time
139         * @return a list of coordinator actions that correspond to the date range
140         */
141        private static List<CoordinatorActionBean> getActionsFromDateRange(String jobId, Date start, Date end) throws XException{
142            List<CoordinatorActionBean> list;
143            JPAService jpaService = Services.get().get(JPAService.class);
144            list = jpaService.execute(new CoordJobGetActionsForDatesJPAExecutor(jobId, start, end));
145            return list;
146        }
147    }