Package ru.aristar.jnuget.client

Source Code of ru.aristar.jnuget.client.NugetClient

package ru.aristar.jnuget.client;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import com.sun.jersey.client.apache4.config.ApacheHttpClient4Config;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import static java.text.MessageFormat.format;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.aristar.jnuget.MainUrlResource;
import ru.aristar.jnuget.Version;
import ru.aristar.jnuget.common.ProxyOptions;
import ru.aristar.jnuget.files.NugetFormatException;
import ru.aristar.jnuget.files.Nupkg;
import ru.aristar.jnuget.files.TempNupkgFile;
import ru.aristar.jnuget.query.AndExpression;
import ru.aristar.jnuget.query.IdEqIgnoreCase;
import ru.aristar.jnuget.query.VersionEq;
import ru.aristar.jnuget.rss.PackageFeed;
import ru.aristar.jnuget.sources.PackageSourceFactory;

/**
*
* @author sviridov
*/
public class NugetClient implements AutoCloseable {

    /**
     * Ресурс, к которому осуществляется подключение REST клиента
     */
    private WebResource webResource;
    /**
     * REST клиент
     */
    private Client client;
    /**
     * URL хранилища по умолчанию
     */
    private static final String DEFAULT_REMOTE_STORAGE_URL = "http://localhost:8080/resources";
    /**
     * Ключ доступа к удаленному хранилищу
     */
    private String apiKey;
    /**
     * Логгер
     */
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * Конструктор по умолчанию
     */
    public NugetClient() {
        final ProxyOptions proxyOptions = PackageSourceFactory.getInstance().getOptions().getProxyOptions();
        ClientConfig config = createClientConfig(proxyOptions);
        client = ApacheHttpClient4.create(config);
        client.setFollowRedirects(Boolean.TRUE);
        client.addFilter(new GZIPContentEncodingFilter());
        webResource = client.resource(DEFAULT_REMOTE_STORAGE_URL);
    }

    /**
     * @param url URL ресурса, к которому необходимо подключиться
     */
    public NugetClient(String url) {
        this();
        NugetClient.this.setUrl(url);
    }

    /**
     * @param url URL удаленного хранилища
     */
    public void setUrl(String url) {
        webResource = client.resource(url);
    }

    /**
     * @return URL удаленного хранилища
     */
    public String getUrl() {
        return webResource == null ? null : webResource.getURI().toString();
    }

    /**
     * @return ключ доступа к удаленному хранилищу
     */
    public String getApiKey() {
        return apiKey;
    }

    /**
     * @param apiKey ключ доступа к удаленному хранилищу
     */
    public void setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }

    /**
     * Возвращает список пакетов
     *
     * @param filter параметр фильтрации
     * @param searchTerm условие поиска
     * @param top количество запрашиваемых пакетов
     * @param targetFramework фреймворк, для которого собраны пакеты
     * @param skip пропустить пакетов
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    public PackageFeed getPackages(String filter, String searchTerm,
            Integer top, String targetFramework, Integer skip)
            throws IOException, URISyntaxException {
        Map<String, String> params = new HashMap<>(6);
        params.put("$orderby", "Id");
        params.put("$filter", filter);
        params.put("searchTerm", searchTerm);
        params.put("$top", top == null ? null : top.toString());
        params.put("targetFramework", targetFramework);
        params.put("$skip", skip == null ? null : skip.toString());

        MediaType[] accept = {MediaType.TEXT_HTML_TYPE,
            MediaType.APPLICATION_XHTML_XML_TYPE,
            MediaType.APPLICATION_XML_TYPE,
            MediaType.WILDCARD_TYPE};

        PackageFeed feed = null;
        int tryCount = 0;
        final URI storageURI = webResource.getURI();
        do {
            try {
                logger.debug("Получение пакетов из {} Top: {}, Skip: {}, попытка {}",
                        new Object[]{storageURI, top, skip, tryCount + 1});
                feed = get(client, storageURI, "Packages", params, accept, PackageFeed.class);
            } catch (IOException e) {
                logger.warn("Не удалось получить пакеты для хранилища {} "
                        + "Top: {} Skip: {} причина: {} попытка {}",
                        new Object[]{storageURI, top, skip, e.getMessage(), tryCount + 1});
                tryCount = tryCount + 1;
            }
        } while (feed == null && tryCount < MAX_TRY_COUNT);
        return feed;
    }

    /**
     * Получает пакет из удаленного хранилища NuGet
     *
     * @param id идентификатор пакета
     * @param version версия пакета
     * @return пакет
     * @throws IOException ошибка чтения потока с телом пакета
     * @throws URISyntaxException
     * @throws NugetFormatException ошибка вычисления HASH пакета
     */
    public TempNupkgFile getPackage(String id, Version version) throws IOException, URISyntaxException, NugetFormatException {
        IdEqIgnoreCase eqIgnoreCase = new IdEqIgnoreCase(id);
        VersionEq versionEq = new VersionEq(version);
        AndExpression andExpression = new AndExpression(eqIgnoreCase, versionEq);
        String filter = andExpression.toString();
        PackageFeed feed = getPackages(filter, null, 100, null, 0);
        if(feed.getEntries().isEmpty()) {
            return null;
        }
        URI uri = URI.create(feed.getEntries().get(0).getContent().getSrc());

        try (InputStream inputStream = get(client, uri, "", InputStream.class)) {
            TempNupkgFile nupkgFile = new TempNupkgFile(inputStream);
            return nupkgFile;
        }
    }

    /**
     * Возвращает количество пакетов в удаленном хранилище
     *
     * @param isLatestVersion только последние версии пакетов
     * @return количество пакетов
     * @throws IOException ошибка чтения пакетов из удаленного репозитория
     * @throws URISyntaxException ошибка URI
     */
    public int getPackageCount(final boolean isLatestVersion) throws IOException, URISyntaxException {
        URI uri = webResource.getURI();
        final String path = "Packages/$count";
        final MediaType[] mediaType = new MediaType[]{MediaType.TEXT_PLAIN_TYPE};
        if (isLatestVersion) {
            Map<String, String> params = new HashMap<>(1);
            params.put("$filter", "IsLatestVersion");
            final String response = get(client, uri, path, params, mediaType, String.class);
            return Integer.parseInt(response);
        }
        final String response = get(client, uri, path, null, mediaType, String.class);
        return Integer.parseInt(response);
    }

    /**
     * Отправляет пакет на сервер
     *
     * @param nupkg пакет
     * @return ответ сервера
     * @throws UniformInterfaceException
     * @throws IOException ошибка чтения локального пакета
     */
    public ClientResponse putPackage(Nupkg nupkg)
            throws UniformInterfaceException, IOException {
        webResource.header(MainUrlResource.API_KEY_HEADER_NAME, apiKey);
        return webResource.put(ClientResponse.class, nupkg.getStream());
    }

    @Override
    public void close() {
        client.destroy();
    }

    /**
     * Получить класс указанного типа с URI
     *
     * @param <T> тип
     * @param client клиент
     * @param uri URI ресурса
     * @param targetClass класс, который необходимо получить
     * @param querryParams параметры запроса
     * @param accept поддерживаемые типы
     * @param path относительный путь к объекту
     * @return объект из удаленного URI
     * @throws IOException ошибка чтения из сокета
     * @throws URISyntaxException URI имеет некорректный синтаксис
     */
    private <T> T get(Client client, URI uri, String path,
            Map<String, String> querryParams, MediaType[] accept, Class<T> targetClass)
            throws IOException, URISyntaxException {
        WebResource currentResource = client.resource(uri);
        //Относительный путь
        if (path != null) {
            currentResource = currentResource.path(path);
        }
        //Параметры запроса
        if (querryParams != null) {
            for (Map.Entry<String, String> entry : querryParams.entrySet()) {
                if (entry.getValue() != null) {
                    currentResource = currentResource.queryParam(entry.getKey(), entry.getValue());
                }
            }
        }
        try {
            ClientResponse response;
            //Заголовки запроса
            if (accept != null && accept.length != 0) {
                response = currentResource.accept(accept).get(ClientResponse.class);
            } else {
                response = currentResource.get(ClientResponse.class);
            }
            switch (response.getClientResponseStatus()) {
                case ACCEPTED:
                case OK: {
                    logger.trace("Получен ответ для типа {}", new Object[]{targetClass.getName()});
                    final T result = response.getEntity(targetClass);
                    if (!Closeable.class.isAssignableFrom(targetClass)) {
                        logger.trace("Принудительное закрытие потока от сервера.");
                        response.getEntityInputStream().close();
                    }
                    return result;
                }
                case FOUND:
                case MOVED_PERMANENTLY: {
                    String redirectUriString = response.getHeaders().get("Location").get(0);
                    URI redirectUri = new URI(redirectUriString);
                    response.getEntityInputStream().close();
                    return get(client, redirectUri, null, querryParams, accept, targetClass);
                }
                case BAD_REQUEST: {
                    response.getEntityInputStream().close();
                    return get(client, uri, null, querryParams, accept, targetClass);
                }
                case INTERNAL_SERVER_ERROR: {
                    response.getEntityInputStream().close();
                    throw new IOException("Ошибка на удаленном сервере код: "
                            + response.getClientResponseStatus().getStatusCode() + " "
                            + response.getClientResponseStatus().getReasonPhrase());
                }
                default:
                    throw new IOException("Статус сообщения " + response.getClientResponseStatus() + " не поддерживается");
            }
        } catch (ClientHandlerException e) {
            logger.warn(format("Ошибка получения данных с удаленного сервера по адресу {0}", currentResource.getURI()), e);
            throw e;
        }
    }

    /**
     * Получить класс указанного типа с URI
     *
     * @param <T> тип
     * @param client клиент
     * @param uri URI ресурса
     * @param targetClass класс, который необходимо получить
     * @param path относительный путь к объекту
     * @return объект из удаленного URI
     * @throws IOException ошибка чтения из сокета
     * @throws URISyntaxException URI имеет некорректный синтаксис
     */
    private <T> T get(Client client, URI uri, String path, Class<T> targetClass)
            throws IOException, URISyntaxException {
        return get(client, uri, path, null, null, targetClass);
    }

    /**
     * Создает настройки подключения к серверу NuGet
     *
     * @param proxyOptions настройки прокси
     * @return
     */
    private ClientConfig createClientConfig(ProxyOptions proxyOptions) {
        ClientConfig config = new DefaultClientConfig();
        if (proxyOptions.getUseSystemProxy() != null && proxyOptions.getUseSystemProxy()) {
            logger.info("Используется системный прокси");
            System.setProperty("java.net.useSystemProxies", "true");
        } else if (proxyOptions.getNoProxy() != null && proxyOptions.getNoProxy()) {
            logger.info("Прокси отключен");
            throw new UnsupportedOperationException("Отключение прокси не реализовано");
        } else {
            logger.info("Используется прокси {}:{}",
                    new Object[]{proxyOptions.getHost(), proxyOptions.getPort()});
            String host = proxyOptions.getHost();
            if (!host.toLowerCase().startsWith("http://")) {
                host = "http://" + host;
            }
            URI proxyUri = URI.create(host + ":" + proxyOptions.getPort());
            config.getProperties().put(ApacheHttpClient4Config.PROPERTY_PROXY_URI, proxyUri);
            config.getProperties().put(ApacheHttpClient4Config.PROPERTY_PROXY_USERNAME, proxyOptions.getLogin());
            config.getProperties().put(ApacheHttpClient4Config.PROPERTY_PROXY_PASSWORD, proxyOptions.getPassword());
        }
        return config;
    }

    /**
     * Получить класс указанного типа с URI
     *
     * @param <T> тип
     * @param uri URI ресурса
     * @param targetClass класс, который необходимо получить
     * @return объект из удаленного URI
     * @throws IOException ошибка чтения из сокета
     * @throws URISyntaxException URI имеет некорректный синтаксис
     */
    public <T> T get(URI uri, Class<T> targetClass)
            throws IOException, URISyntaxException {
        return get(client, uri, null, null, null, targetClass);
    }
    /**
     * Максимально допустимое число попыток получения информации из хранилища
     */
    public static final int MAX_TRY_COUNT = 3;
}
TOP

Related Classes of ru.aristar.jnuget.client.NugetClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.