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 */
018package org.apache.oozie.coord;
019
020import java.text.ParseException;
021import java.util.ArrayList;
022import java.util.Date;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Set;
026
027import org.apache.hadoop.conf.Configuration;
028import org.apache.oozie.CoordinatorActionBean;
029import org.apache.oozie.ErrorCode;
030import org.apache.oozie.XException;
031import org.apache.oozie.client.OozieClient;
032import org.apache.oozie.command.CommandException;
033import org.apache.oozie.executor.jpa.CoordActionGetJPAExecutor;
034import org.apache.oozie.executor.jpa.CoordJobGetActionForNominalTimeJPAExecutor;
035import org.apache.oozie.executor.jpa.JPAExecutorException;
036import org.apache.oozie.service.JPAService;
037import org.apache.oozie.service.Services;
038import org.apache.oozie.util.CoordActionsInDateRange;
039import org.apache.oozie.util.DateUtils;
040import org.apache.oozie.util.ParamChecker;
041import org.jdom.Element;
042
043public class CoordUtils {
044    public static final String HADOOP_USER = "user.name";
045
046    public static String getDoneFlag(Element doneFlagElement) {
047        if (doneFlagElement != null) {
048            return doneFlagElement.getTextTrim();
049        }
050        else {
051            return CoordELConstants.DEFAULT_DONE_FLAG;
052        }
053    }
054
055    public static Configuration getHadoopConf(Configuration jobConf) {
056        Configuration conf = new Configuration();
057        ParamChecker.notNull(jobConf, "Configuration to be used for hadoop setup ");
058        String user = ParamChecker.notEmpty(jobConf.get(OozieClient.USER_NAME), OozieClient.USER_NAME);
059        conf.set(HADOOP_USER, user);
060        return conf;
061    }
062
063    /**
064     * Get the list of actions for given date ranges
065     *
066     * @param jobId coordinator job id
067     * @param scope a comma-separated list of date ranges. Each date range element is specified with two dates separated by '::'
068     * @return the list of Coordinator actions for the date range
069     * @throws CommandException thrown if failed to get coordinator actions by given date range
070     */
071    public static List<CoordinatorActionBean> getCoordActionsFromDates(String jobId, String scope) throws CommandException {
072        JPAService jpaService = Services.get().get(JPAService.class);
073        ParamChecker.notEmpty(jobId, "jobId");
074        ParamChecker.notEmpty(scope, "scope");
075
076        Set<CoordinatorActionBean> actionSet = new HashSet<CoordinatorActionBean>();
077        String[] list = scope.split(",");
078        for (String s : list) {
079            s = s.trim();
080            // A date range is specified with two dates separated by '::'
081            if (s.contains("::")) {
082            List<CoordinatorActionBean> listOfActions;
083            try {
084                // Get list of actions within the range of date
085                listOfActions = CoordActionsInDateRange.getCoordActionsFromDateRange(jobId, s);
086            }
087            catch (XException e) {
088                throw new CommandException(e);
089            }
090            actionSet.addAll(listOfActions);
091            }
092            else {
093                try {
094                    // Get action for the nominal time
095                    Date date = DateUtils.parseDateOozieTZ(s.trim());
096                    CoordinatorActionBean coordAction = jpaService
097                            .execute(new CoordJobGetActionForNominalTimeJPAExecutor(jobId, date));
098
099                    if (coordAction != null) {
100                        actionSet.add(coordAction);
101                    }
102                    else {
103                        throw new RuntimeException("This should never happen, Coordinator Action shouldn't be null");
104                    }
105                }
106                catch (ParseException e) {
107                    throw new CommandException(ErrorCode.E0302, s.trim(), e);
108                }
109                catch (JPAExecutorException e) {
110                    throw new CommandException(e);
111                }
112
113            }
114        }
115
116        List<CoordinatorActionBean> coordActions = new ArrayList<CoordinatorActionBean>();
117        for (CoordinatorActionBean coordAction : actionSet) {
118            coordActions.add(coordAction);
119        }
120        return coordActions;
121    }
122
123    /**
124     * Get the list of actions for given id ranges
125     *
126     * @param jobId coordinator job id
127     * @param scope a comma-separated list of action ranges. The action range is specified with two action numbers separated by '-'
128     * @return the list of all Coordinator actions for action range
129     * @throws CommandException thrown if failed to get coordinator actions by given id range
130     */
131     public static List<CoordinatorActionBean> getCoordActionsFromIds(String jobId, String scope) throws CommandException {
132        JPAService jpaService = Services.get().get(JPAService.class);
133        ParamChecker.notEmpty(jobId, "jobId");
134        ParamChecker.notEmpty(scope, "scope");
135
136        Set<String> actions = new HashSet<String>();
137        String[] list = scope.split(",");
138        for (String s : list) {
139            s = s.trim();
140            // An action range is specified with two actions separated by '-'
141            if (s.contains("-")) {
142                String[] range = s.split("-");
143                // Check the format for action's range
144                if (range.length != 2) {
145                    throw new CommandException(ErrorCode.E0302, "format is wrong for action's range '" + s + "', an example of correct format is 1-5");
146                }
147                int start;
148                int end;
149                //Get the starting and ending action numbers
150                try {
151                    start = Integer.parseInt(range[0].trim());
152                } catch (NumberFormatException ne) {
153                    throw new CommandException(ErrorCode.E0302, "could not parse " + range[0].trim() + "into an integer", ne);
154                }
155                try {
156                    end = Integer.parseInt(range[1].trim());
157                } catch (NumberFormatException ne) {
158                    throw new CommandException(ErrorCode.E0302, "could not parse " + range[1].trim() + "into an integer", ne);
159                }
160                if (start > end) {
161                    throw new CommandException(ErrorCode.E0302, "format is wrong for action's range '" + s + "', starting action"
162                            + "number of the range should be less than ending action number, an example will be 1-4");
163                }
164                // Add the actionIds
165                for (int i = start; i <= end; i++) {
166                    actions.add(jobId + "@" + i);
167                }
168            }
169            else {
170                try {
171                    Integer.parseInt(s);
172                }
173                catch (NumberFormatException ne) {
174                    throw new CommandException(ErrorCode.E0302, "format is wrong for action id'" + s
175                            + "'. Integer only.");
176                }
177                actions.add(jobId + "@" + s);
178            }
179        }
180        // Retrieve the actions using the corresponding actionIds
181        List<CoordinatorActionBean> coordActions = new ArrayList<CoordinatorActionBean>();
182        for (String id : actions) {
183            CoordinatorActionBean coordAction;
184            try {
185                coordAction = jpaService.execute(new CoordActionGetJPAExecutor(id));
186            }
187            catch (JPAExecutorException je) {
188                throw new CommandException(je);
189            }
190            coordActions.add(coordAction);
191        }
192        return coordActions;
193    }
194
195}