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.util.ArrayList;
022    import java.util.Date;
023    import java.util.HashSet;
024    import java.util.List;
025    import java.util.Set;
026    
027    import org.apache.oozie.CoordinatorActionBean;
028    import org.apache.oozie.CoordinatorActionInfo;
029    import org.apache.oozie.ErrorCode;
030    import org.apache.oozie.XException;
031    import org.apache.oozie.command.PreconditionException;
032    import org.apache.oozie.executor.jpa.CoordJobGetActionsForDatesJPAExecutor;
033    import org.apache.oozie.executor.jpa.JPAExecutorException;
034    import org.apache.oozie.service.JPAService;
035    import org.apache.oozie.service.Services;
036    import org.apache.oozie.util.DateUtils;
037    import org.apache.oozie.util.ParamChecker;
038    /**
039     * This class provides the utility of listing
040     * coordinator actions that were executed between a certain
041     * date range. This is helpful in turn for retrieving the
042     * required logs in that date range.
043     */
044    public class CoordActionsInDateRange {
045    
046        /**
047         * Get the list of actions for given date ranges
048         *
049         * @param jobId coordinator job id
050         * @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 '::'
051         * @return the list of coordinator actions for the date range
052         *
053         * Internally involves a database operation by invoking method 'getActionIdsFromDateRange'.
054         */
055        public static List<CoordinatorActionBean> getCoordActionsFromDates(String jobId, String scope) throws XException {
056            ParamChecker.notEmpty(jobId, "jobId");
057            ParamChecker.notEmpty(scope, "scope");
058            Set<CoordinatorActionBean> actionSet = new HashSet<CoordinatorActionBean>();
059            String[] list = scope.split(",");
060            for (String s : list) {
061                s = s.trim();
062                // This block checks for errors in the format of specifying date range
063                if (s.contains("::")) {
064                    String[] dateRange = s.split("::");
065                    if (dateRange.length != 2) {
066                        throw new XException(ErrorCode.E0308, "'" + s + "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
067                    }
068                    Date start;
069                    Date end;
070                    try {
071                    start = DateUtils.parseDateUTC(dateRange[0].trim());
072                    end = DateUtils.parseDateUTC(dateRange[1].trim());
073                    }
074                    catch (Exception dx) {
075                        throw new XException(ErrorCode.E0308, "Error in parsing start or end date");
076                    }
077                    if (start.after(end)) {
078                        throw new XException(ErrorCode.E0308, "'" + s + "'. Start date '" + start + "' is older than end date: '" + end + "'");
079                    }
080                    List<CoordinatorActionBean> listOfActions = getActionIdsFromDateRange(jobId, start, end);
081                    actionSet.addAll(listOfActions);
082                }
083                else {
084                    throw new XException(ErrorCode.E0308, "'" + s + "'. Separator '::' is missing for start and end dates of range");
085                }
086            }
087            List<CoordinatorActionBean> coordActions = new ArrayList<CoordinatorActionBean>();
088            for (CoordinatorActionBean coordAction : actionSet) {
089                coordActions.add(coordAction);
090            }
091            return coordActions;
092        }
093    
094        /*
095         * Get coordinator action ids between given start and end time
096         *
097         * @param jobId coordinator job id
098         * @param start start time
099         * @param end end time
100         * @return a list of coordinator actions that correspond to the date range
101         */
102        private static List<CoordinatorActionBean> getActionIdsFromDateRange(String jobId, Date start, Date end) throws XException{
103            List<CoordinatorActionBean> list;
104            JPAService jpaService = Services.get().get(JPAService.class);
105            list = jpaService.execute(new CoordJobGetActionsForDatesJPAExecutor(jobId, start, end));
106            return list;
107        }
108    }