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.dependency;
019
020import java.net.URI;
021import java.net.URISyntaxException;
022import java.util.ArrayList;
023import java.util.List;
024import org.apache.commons.lang.StringUtils;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.oozie.ErrorCode;
027import org.apache.oozie.client.OozieClient;
028import org.apache.oozie.command.CommandException;
029import org.apache.oozie.coord.CoordELFunctions;
030import org.apache.oozie.service.Services;
031import org.apache.oozie.service.URIHandlerService;
032import org.apache.oozie.util.ParamChecker;
033import org.apache.oozie.util.XLog;
034
035public class DependencyChecker {
036
037    /**
038     * Return a string of missing dependencies concatenated by CoordELFunctions.INSTANCE_SEPARATOR
039     *
040     * @param missingDependencies list of missing dependencies
041     * @return missing dependencies as a string
042     */
043    public static String dependenciesAsString(List<String> missingDependencies) {
044        return StringUtils.join(missingDependencies, CoordELFunctions.INSTANCE_SEPARATOR);
045    }
046
047    /**
048     * Return a array of missing dependencies
049     *
050     * @param missingDependencies missing dependencies concatenated by
051     *        CoordELFunctions.INSTANCE_SEPARATOR
052     * @return missing dependencies as a array
053     */
054    public static String[] dependenciesAsArray(String missingDependencies) {
055        return missingDependencies.split(CoordELFunctions.INSTANCE_SEPARATOR);
056    }
057
058    /**
059     * Get the currently missing and available dependencies after checking the list of known missing
060     * dependencies against the source.
061     *
062     * @param missingDependencies known missing dependencies
063     * @param actionConf Configuration for the action
064     * @param stopOnFirstMissing Does not continue check for the rest of list if there is a missing
065     *        dependency
066     * @return ActionDependency which has the list of missing and available dependencies
067     * @throws CommandException
068     */
069    public static ActionDependency checkForAvailability(String missingDependencies, Configuration actionConf,
070            boolean stopOnFirstMissing) throws CommandException {
071        return checkForAvailability(dependenciesAsArray(missingDependencies), actionConf, stopOnFirstMissing);
072    }
073
074    /**
075     * Get the currently missing and available dependencies after checking the list of known missing
076     * dependencies against the source.
077     *
078     * @param missingDependencies known missing dependencies
079     * @param actionConf Configuration for the action
080     * @param stopOnFirstMissing Does not continue check for the rest of list if there is a missing
081     *        dependency
082     * @return ActionDependency which has the list of missing and available dependencies
083     * @throws CommandException
084     */
085    public static ActionDependency checkForAvailability(String[] missingDependencies, Configuration actionConf,
086            boolean stopOnFirstMissing) throws CommandException {
087        final XLog LOG = XLog.getLog(DependencyChecker.class); //OOZIE-1251. Don't initialize as static variable.
088        String user = ParamChecker.notEmpty(actionConf.get(OozieClient.USER_NAME), OozieClient.USER_NAME);
089        List<String> missingDeps = new ArrayList<String>();
090        List<String> availableDeps = new ArrayList<String>();
091        URIHandlerService uriService = Services.get().get(URIHandlerService.class);
092        boolean continueChecking = true;
093        try {
094            for (int index = 0; index < missingDependencies.length; index++) {
095                if (continueChecking) {
096                    String dependency = missingDependencies[index];
097
098                    URI uri = new URI(dependency);
099                    URIHandler uriHandler = uriService.getURIHandler(uri);
100                    LOG.debug("Checking for the availability of dependency [{0}] ", dependency);
101                    if (uriHandler.exists(uri, actionConf, user)) {
102                        LOG.debug("Dependency [{0}] is available", dependency);
103                        availableDeps.add(dependency);
104                    }
105                    else {
106                        LOG.debug("Dependency [{0}] is missing", dependency);
107                        missingDeps.add(dependency);
108                        if (stopOnFirstMissing) {
109                            continueChecking = false;
110                        }
111                    }
112
113                }
114                else {
115                    missingDeps.add(missingDependencies[index]);
116                }
117            }
118        }
119        catch (URISyntaxException e) {
120            throw new CommandException(ErrorCode.E0906, e.getMessage(), e);
121        }
122        catch (URIHandlerException e) {
123            throw new CommandException(e);
124        }
125        return new ActionDependency(missingDeps, availableDeps);
126    }
127}