org.apache.falcon.oozie.OozieBundleBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.falcon.oozie.OozieBundleBuilder.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.falcon.oozie;

import org.apache.commons.lang3.StringUtils;
import org.apache.falcon.FalconException;
import org.apache.falcon.entity.ClusterHelper;
import org.apache.falcon.entity.EntityUtil;
import org.apache.falcon.entity.HiveUtil;
import org.apache.falcon.entity.v0.Entity;
import org.apache.falcon.entity.v0.cluster.Cluster;
import org.apache.falcon.hadoop.HadoopClientFactory;
import org.apache.falcon.oozie.bundle.BUNDLEAPP;
import org.apache.falcon.oozie.bundle.CONFIGURATION;
import org.apache.falcon.oozie.bundle.CONFIGURATION.Property;
import org.apache.falcon.oozie.bundle.COORDINATOR;
import org.apache.falcon.security.CurrentUser;
import org.apache.falcon.util.OozieUtils;
import org.apache.falcon.workflow.engine.AbstractWorkflowEngine;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.oozie.client.OozieClient;
import org.apache.falcon.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import java.io.IOException;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;

/**
 * Base class for building oozie bundle - bundle is the entity that falcon tracks in oozie.
 * @param <T>
 */
public abstract class OozieBundleBuilder<T extends Entity> extends OozieEntityBuilder<T> {
    public static final Logger LOG = LoggerFactory.getLogger(OozieBundleBuilder.class);

    public OozieBundleBuilder(T entity) {
        super(entity);
    }

    @Override
    public Properties build(Cluster cluster, Path buildPath) throws FalconException {
        String clusterName = cluster.getName();
        if (EntityUtil.getStartTime(entity, clusterName)
                .compareTo(EntityUtil.getEndTime(entity, clusterName)) >= 0) {
            LOG.info("process validity start <= end for cluster {}. Skipping schedule", clusterName);
            return null;
        }

        List<Properties> coords = buildCoords(cluster, buildPath);
        if (coords == null || coords.isEmpty()) {
            return null;
        }

        BUNDLEAPP bundle = new BUNDLEAPP();
        bundle.setName(EntityUtil.getWorkflowName(entity).toString());
        // all the properties are set prior to bundle and coordinators creation

        for (Properties coordProps : coords) {
            // add the coordinator to the bundle
            COORDINATOR coord = new COORDINATOR();
            String coordPath = coordProps.getProperty(OozieEntityBuilder.ENTITY_PATH);
            final String coordName = coordProps.getProperty(OozieEntityBuilder.ENTITY_NAME);
            coord.setName(coordName);
            coord.setAppPath(getStoragePath(coordPath));
            coordProps.put(OozieClient.USER_NAME, CurrentUser.getUser());
            coordProps.setProperty(AbstractWorkflowEngine.NAME_NODE, ClusterHelper.getStorageUrl(cluster));
            if (EntityUtil.isTableStorageType(cluster, entity)) {
                Tag tag = EntityUtil.getWorkflowNameTag(coordName, entity);
                if (tag == Tag.REPLICATION) {
                    // todo: kludge send source hcat creds for coord dependency check to pass
                    String srcClusterName = EntityUtil.getWorkflowNameSuffix(coordName, entity);
                    coordProps.putAll(HiveUtil.getHiveCredentials(ClusterHelper.getCluster(srcClusterName)));
                } else {
                    coordProps.putAll(HiveUtil.getHiveCredentials(cluster));
                }
            }

            coord.setConfiguration(getConfig(coordProps));
            bundle.getCoordinator().add(coord);
        }

        Path marshalPath = marshal(cluster, bundle, buildPath); // write the bundle
        Properties properties = getProperties(marshalPath, entity.getName());
        properties.setProperty(OozieClient.BUNDLE_APP_PATH, getStoragePath(buildPath));
        properties.setProperty(AbstractWorkflowEngine.NAME_NODE, ClusterHelper.getStorageUrl(cluster));

        //Add libpath
        String libPath = getOozieLibPath(buildPath);
        if (StringUtils.isNotBlank(libPath)) {
            properties.put(OozieClient.LIBPATH, libPath);
        }

        return properties;
    }

    private String getOozieLibPath(final Path buildPath) {
        String path = getLibPath(buildPath);
        if (StringUtils.isBlank(path)) {
            return null;
        }
        StringBuilder storageLibPaths = new StringBuilder();
        String[] libPaths = path.split(EntityUtil.WF_LIB_SEPARATOR);
        for (String libPath : libPaths) {
            String tempPath = getStoragePath(libPath);
            if (StringUtils.isNotBlank(tempPath)) {
                if (StringUtils.isNotBlank(storageLibPaths)) {
                    storageLibPaths.append(EntityUtil.WF_LIB_SEPARATOR);
                }
                storageLibPaths.append(tempPath);
            }
        }
        return StringUtils.isBlank(storageLibPaths) ? null : storageLibPaths.toString();
    }

    protected CONFIGURATION getConfig(Properties props) {
        CONFIGURATION conf = new CONFIGURATION();
        for (Entry<Object, Object> prop : props.entrySet()) {
            Property confProp = new Property();
            confProp.setName((String) prop.getKey());
            confProp.setValue((String) prop.getValue());
            conf.getProperty().add(confProp);
        }
        return conf;
    }

    protected Path marshal(Cluster cluster, BUNDLEAPP bundle, Path outPath) throws FalconException {
        return marshal(cluster, new org.apache.falcon.oozie.bundle.ObjectFactory().createBundleApp(bundle),
                OozieUtils.BUNDLE_JAXB_CONTEXT, new Path(outPath, "bundle.xml"));
    }

    //Used by coordinator builders to return multiple coords
    //TODO Can avoid separate interface that returns list by building at lifecycle level
    protected abstract List<Properties> buildCoords(Cluster cluster, Path bundlePath) throws FalconException;

    public static BUNDLEAPP unmarshal(Cluster cluster, Path path) throws FalconException {
        try {
            FileSystem fs = HadoopClientFactory.get().createProxiedFileSystem(path.toUri(),
                    ClusterHelper.getConfiguration(cluster));
            Unmarshaller unmarshaller = OozieUtils.BUNDLE_JAXB_CONTEXT.createUnmarshaller();
            @SuppressWarnings("unchecked")
            JAXBElement<BUNDLEAPP> jaxbElement = unmarshaller.unmarshal(new StreamSource(fs.open(path)),
                    BUNDLEAPP.class);
            return jaxbElement.getValue();
        } catch (JAXBException e) {
            throw new FalconException(e);
        } catch (IOException e) {
            throw new FalconException(e);
        }
    }

    public abstract String getLibPath(Path buildPath);
}