com.cloudera.nav.plugin.client.NavApiCient.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudera.nav.plugin.client.NavApiCient.java

Source

/*
 * Copyright (c) 2015 Cloudera, Inc.
 *
 * Licensed 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 com.cloudera.nav.plugin.client;

import com.cloudera.nav.plugin.model.Source;
import com.cloudera.nav.plugin.model.SourceType;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

/**
 * An API client to communicate with Navigator to register and validate
 * metadata models
 */
public class NavApiCient {

    private static final Logger LOG = LoggerFactory.getLogger(NavApiCient.class);
    private static final String SOURCE_QUERY = "type:SOURCE";

    private final PluginConfigurations config;
    private final Cache<String, Source> sourceCacheByUrl;
    private final Cache<SourceType, Collection<Source>> sourceCacheByType;

    public NavApiCient(PluginConfigurations config) {
        this.config = config;
        sourceCacheByUrl = CacheBuilder.newBuilder().build();
        sourceCacheByType = CacheBuilder.newBuilder().build();
    }

    /**
     * Registers a given set of metadata models
     * @param models
     */
    public void registerModels(Collection<Object> models) {
        throw new UnsupportedOperationException("no yet implemented");
    }

    /**
     * Call the Navigator API and retrieve all available sources
     *
     * @return a collection of available sources
     */
    public Collection<Source> getAllSources() {
        RestTemplate restTemplate = new RestTemplate();
        String url = getSourceUrl();
        HttpHeaders headers = getAuthHeaders();
        HttpEntity<String> request = new HttpEntity<String>(headers);
        ResponseEntity<SourceAttrs[]> response = restTemplate.exchange(url, HttpMethod.GET, request,
                SourceAttrs[].class);
        Collection<Source> sources = Lists.newArrayList();
        for (SourceAttrs info : response.getBody()) {
            sources.add(info.createSource());
        }
        return sources;
    }

    /**
     * Get the Source corresponding to the Hadoop service Url from Navigator.
     * A NoSuchElementException is thrown if the url does not correspond to
     * any known Source
     *
     * @param serviceUrl
     * @return
     */
    public Source getSourceForUrl(String serviceUrl) {
        Source source = sourceCacheByUrl.getIfPresent(serviceUrl);
        if (source == null) {
            loadAllSources();
        }
        source = sourceCacheByUrl.getIfPresent(serviceUrl);
        Preconditions.checkArgument(source != null, "Could not find Source at " + serviceUrl);
        return source;
    }

    /**
     * Return the only Source of the given type, throw exception if more than
     * one is found.
     *
     * @param sourceType
     * @return
     */
    public Source getOnlySource(SourceType sourceType) {
        Collection<Source> sources = getSourcesForType(sourceType);
        Preconditions.checkNotNull(sources, "Could not find sources for " + "source type " + sourceType.name());
        return Iterables.getOnlyElement(sources);
    }

    public Collection<Source> getSourcesForType(SourceType sourceType) {
        Collection<Source> sources = sourceCacheByType.getIfPresent(sourceType);
        if (sources == null) {
            loadAllSources();
            sources = sourceCacheByType.getIfPresent(sourceType);
        }
        return sources;
    }

    /**
     * Clear the cache of Sources that have been previously loaded.
     */
    public void resetSources() {
        sourceCacheByUrl.invalidateAll();
        sourceCacheByType.invalidateAll();
    }

    private HttpHeaders getAuthHeaders() {
        // basic authentication with base64 encoding
        String plainCreds = String.format("%s:%s", config.getUsername(), config.getPassword());
        byte[] plainCredsBytes = plainCreds.getBytes();
        byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
        String base64Creds = new String(base64CredsBytes);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + base64Creds);
        return headers;
    }

    private String getSourceUrl() {
        // form the url string to request all entities with type equal to SOURCE
        String baseNavigatorUrl = config.getNavigatorUrl();
        String entities = joinUrlPath(baseNavigatorUrl, "entities");
        return String.format("%s?query=%s", entities, SOURCE_QUERY);
    }

    private String joinUrlPath(String base, String component) {
        return base + (base.endsWith("/") ? "" : "/") + component;
    }

    private void loadAllSources() {
        Collection<Source> allSources = getAllSources();
        for (Source source : allSources) {
            if (source.getSourceUrl() == null) {
                LOG.warn(String.format("Source %s did not have a source url",
                        source.getName() != null ? source.getName() : source.getIdentity()));
                continue;
            }
            sourceCacheByUrl.put(source.getSourceUrl(), source);
            try {
                Collection<Source> forType = sourceCacheByType.get(source.getSourceType(),
                        new Callable<Collection<Source>>() {
                            @Override
                            public Collection<Source> call() throws Exception {
                                return Sets.newHashSet();
                            }
                        });
                forType.add(source);
            } catch (ExecutionException e) {
                throw Throwables.propagate(e);
            }
        }
    }
}