org.jboss.jdf.stacks.client.StacksClient.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.jdf.stacks.client.StacksClient.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
 * contributors by the @authors tag. See the copyright.txt in the
 * distribution for a full listing of individual contributors.
 *
 * 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 org.jboss.jdf.stacks.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.jboss.jdf.stacks.client.messages.JBossLoggingMessages;
import org.jboss.jdf.stacks.client.messages.StacksMessages;
import org.jboss.jdf.stacks.model.Stacks;
import org.jboss.jdf.stacks.parser.Parser;

/**
 * @author <a href="mailto:benevides@redhat.com">Rafael Benevides</a>
 * 
 */
public class StacksClient {

    private StacksClientConfiguration actualConfiguration;

    private StacksMessages msg;

    public StacksClient() {
        this(new DefaultStacksClientConfiguration());
    }

    public StacksClient(StacksClientConfiguration configuration) {
        this(configuration, new JBossLoggingMessages());
    }

    public StacksClient(StacksClientConfiguration configuration, StacksMessages stacksMessagesImpl) {
        this.msg = stacksMessagesImpl;
        this.actualConfiguration = configuration;
    }

    private Stacks initializeStacks() {
        InputStream inputStream = null;
        try {
            // Retrieve inputStream (local cache or remote)
            inputStream = getStacksInputStream();
            Stacks stacks = null;
            if (inputStream != null) {
                stacks = new Parser().parse(inputStream);
            }
            return stacks;
        } catch (FileNotFoundException e) {
            msg.showErrorMessageWithCause("FileNotFoundException", e);
            return null;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    msg.showErrorMessageWithCause("Something bad happened when closing the inputstream", e);
                }
            }
        }
    }

    /**
     * @return the stacks
     */
    public Stacks getStacks() {
        return initializeStacks();
    }

    /**
     * @return the actualConfiguration
     */
    public StacksClientConfiguration getActualConfiguration() {
        return actualConfiguration;
    }

    /**
     * @return
     * @throws FileNotFoundException
     * 
     */
    private InputStream getStacksInputStream() throws FileNotFoundException {
        InputStream repoStream = getCachedRepoStream(false);
        URL url = actualConfiguration.getUrl();
        // if cache expired
        if (repoStream == null && actualConfiguration.isOnline()) {
            msg.showDebugMessage(
                    "Local cache file " + getLocalCacheFile() + " doesn't exist or cache has been expired");
            try {
                msg.showDebugMessage("Retrieving Stacks from Remote repository " + url);
                repoStream = retrieveStacksFromRemoteRepository(url);
                setCachedRepoStream(repoStream);
                msg.showDebugMessage(
                        "Forcing the use of local cache after download file without error from " + url);
                repoStream = getCachedRepoStream(true);
            } catch (Exception e) {
                msg.showWarnMessage(
                        "It was not possible to contact the repository at " + url + " . Cause " + e.getMessage());
                msg.showWarnMessage("Falling back to cache!");
                repoStream = getCachedRepoStream(true);
            }
        }
        // If the Repostream stills empty after falling back to cache
        if (repoStream == null) {
            msg.showWarnMessage("Cache empty. Falling back to embed file");
            return this.getClass().getResourceAsStream("/stacks.yaml");
        } else {
            return repoStream;
        }

    }

    private InputStream retrieveStacksFromRemoteRepository(final URL url) throws Exception {
        if (url.getProtocol().startsWith("http")) {
            HttpGet httpGet = new HttpGet(url.toURI());
            DefaultHttpClient client = new DefaultHttpClient();
            configureProxy(client);
            HttpResponse httpResponse = client.execute(httpGet);
            switch (httpResponse.getStatusLine().getStatusCode()) {
            case 200:
                msg.showDebugMessage("Connected to repository! Getting available Stacks");
                break;

            case 404:
                msg.showErrorMessage("Failed! (Stacks file not found: " + url + ")");
                return null;

            default:
                msg.showErrorMessage(
                        "Failed! (server returned status code: " + httpResponse.getStatusLine().getStatusCode());
                return null;
            }
            return httpResponse.getEntity().getContent();
        } else if (url.getProtocol().startsWith("file")) {
            return new FileInputStream(new File(url.toURI()));
        }
        return null;
    }

    private void configureProxy(DefaultHttpClient client) {
        if (actualConfiguration.getProxyHost() != null && !actualConfiguration.getProxyHost().isEmpty()) {
            String proxyHost = actualConfiguration.getProxyHost();
            int proxyPort = actualConfiguration.getProxyPort();
            HttpHost proxy = new HttpHost(proxyHost, proxyPort);
            client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
            String proxyUsername = actualConfiguration.getProxyUser();
            if (proxyUsername != null && !proxyUsername.isEmpty()) {
                String proxyPassword = actualConfiguration.getProxyPassword();
                AuthScope authScope = new AuthScope(proxyHost, proxyPort);
                UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(proxyUsername,
                        proxyPassword);
                client.getCredentialsProvider().setCredentials(authScope, credentials);
            }
        }
    }

    /**
     * Get the local file cache for each repository url
     * 
     * @return
     */
    public File getLocalCacheFile() {
        // Remove no word character from the repo url
        String repo = actualConfiguration.getUrl().toString().replaceAll("[^a-zA-Z_0-9]", "");
        return new File(System.getProperty("java.io.tmpdir"), repo + "stacks.yaml");
    }

    private InputStream getCachedRepoStream(final boolean force) throws FileNotFoundException {
        final String logmessage = "Local file %1s %2s used! Reason: Force:[%3b] - Online:[%4b] - LastModification: %5d/%6d";
        File localCacheFile = getLocalCacheFile();
        if (localCacheFile.exists()) {
            int cacheSeconds = actualConfiguration.getCacheRefreshPeriodInSeconds();
            boolean online = actualConfiguration.isOnline();
            long cachedvalidity = 1000 * cacheSeconds;
            long lastModified = localCacheFile.lastModified();
            long timeSinceLastModification = System.currentTimeMillis() - lastModified;
            // if online, consider the cache valid until it expires
            if (force || !online || timeSinceLastModification <= cachedvalidity) {
                msg.showDebugMessage(String.format(logmessage, localCacheFile, "was", force, online,
                        timeSinceLastModification, cachedvalidity));
                return new FileInputStream(localCacheFile);
            }
            msg.showDebugMessage(String.format(logmessage, localCacheFile, "was not", force, online,
                    timeSinceLastModification, cachedvalidity));
        }
        return null;
    }

    private void setCachedRepoStream(final InputStream stream) throws IOException {
        File localCacheFile = getLocalCacheFile();
        msg.showDebugMessage("Content stored at " + localCacheFile);
        if (!localCacheFile.exists()) {
            localCacheFile.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(localCacheFile);

        int i = 0;
        while ((i = stream.read()) != -1) {
            fos.write(i);
        }
        fos.close();
    }

    /**
     * This will drop the local cache to force an online update.
     */
    public void eraseRepositoryCache() {
        File localFile = getLocalCacheFile();
        localFile.delete();
        msg.showDebugMessage("Cache erased");
    }
}