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