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    package org.apache.oozie.coord;
019    
020    import java.text.ParseException;
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.hadoop.conf.Configuration;
028    import org.apache.oozie.CoordinatorActionBean;
029    import org.apache.oozie.ErrorCode;
030    import org.apache.oozie.XException;
031    import org.apache.oozie.client.OozieClient;
032    import org.apache.oozie.command.CommandException;
033    import org.apache.oozie.executor.jpa.CoordActionGetJPAExecutor;
034    import org.apache.oozie.executor.jpa.CoordJobGetActionForNominalTimeJPAExecutor;
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.CoordActionsInDateRange;
039    import org.apache.oozie.util.DateUtils;
040    import org.apache.oozie.util.ParamChecker;
041    import org.jdom.Element;
042    
043    public 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.parseDateUTC(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, 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                    try {
150                        //Get the starting and ending action numbers
151                        start = Integer.parseInt(range[0].trim());
152                        end = Integer.parseInt(range[1].trim());
153                        if (start > end) {
154                            throw new CommandException(ErrorCode.E0302, "format is wrong for action's range '" + s
155                                    + "', starting action number of the range should be less than ending action number, an example will be 1-4");
156                        }
157                    }
158                    catch (NumberFormatException ne) {
159                        throw new CommandException(ErrorCode.E0302, ne);
160                    }
161                    // Add the actionIds
162                    for (int i = start; i <= end; i++) {
163                        actions.add(jobId + "@" + i);
164                    }
165                }
166                else {
167                    try {
168                        Integer.parseInt(s);
169                    }
170                    catch (NumberFormatException ne) {
171                        throw new CommandException(ErrorCode.E0302, "format is wrong for action id'" + s
172                                + "'. Integer only.");
173                    }
174                    actions.add(jobId + "@" + s);
175                }
176            }
177            // Retrieve the actions using the corresponding actionIds
178            List<CoordinatorActionBean> coordActions = new ArrayList<CoordinatorActionBean>();
179            for (String id : actions) {
180                CoordinatorActionBean coordAction;
181                try {
182                    coordAction = jpaService.execute(new CoordActionGetJPAExecutor(id));
183                }
184                catch (JPAExecutorException je) {
185                    throw new CommandException(je);
186                }
187                coordActions.add(coordAction);
188            }
189            return coordActions;
190        }
191    
192    }