Package ru.aristar.jnuget

Source Code of ru.aristar.jnuget.MainUrlResource

package ru.aristar.jnuget;

import com.sun.jersey.multipart.FormDataParam;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
import javax.security.auth.login.LoginException;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.aristar.jnuget.files.NugetFormatException;
import ru.aristar.jnuget.files.Nupkg;
import ru.aristar.jnuget.files.TempNupkgFile;
import ru.aristar.jnuget.rss.MainUrl;
import ru.aristar.jnuget.rss.NuPkgToRssTransformer;
import ru.aristar.jnuget.rss.PackageFeed;
import ru.aristar.jnuget.security.Role;
import ru.aristar.jnuget.sources.PackageSource;
import ru.aristar.jnuget.sources.PackageSourceFactory;

/**
* Сервис управления пакетами
*
* @author sviridov
*/
@Path("{storageName}")
public class MainUrlResource {

    /**
     * Логгер
     */
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * Контекст публикации сервиса
     */
    @Context
    private UriInfo context;
    /**
     * Имя хранилища
     */
    @PathParam("storageName")
    private String storageName;

    /**
     * Конструктор по умолчанию (требование JAX-RS)
     */
    public MainUrlResource() {
    }

    /**
     * Возвращает XML корневого узла хранилища
     *
     * @return XML
     */
    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("")
    public Response getXml() {
        MainUrl mainUrl = new MainUrl(context.getAbsolutePath().toString());
        XmlStreamingOutput streamingOutput = new XmlStreamingOutput(mainUrl);
        return Response.ok(streamingOutput, MediaType.APPLICATION_XML).build();
    }

    /**
     * @return метаданные хранилища
     * @throws IOException ошибка чтения предсохранненных метаданных
     */
    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("{metadata : [$]metadata}")
    public Response getMetadata() throws IOException {
        InputStream inputStream = MainUrlResource.class.getResourceAsStream("/metadata.xml");
        ResponseBuilder response = Response.ok((Object) inputStream);
        return response.build();
    }

    /**
     * Возвращает HTML ответ с RSS содержащей информацию о пакетах
     *
     * @param filter условие выборки пакетов
     * @param orderBy порядок сортировки пакетов (по умолчанию по дате
     * публикации)
     * @param skip количество пакетов, которое необходимо пропустить (по
     * умолчанию 0)
     * @param top количество пакетов в выборке
     * @param searchTerm условие поиска
     * @param targetFramework фрейморк, для которого предназначен пакет
     * @return HTML c RSS
     */
    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("{packages : (Packages)[(]?[)]?|(Search)[(][)]}")
    public Response getPackages(@QueryParam("$filter") String filter,
            @QueryParam("$orderby") @DefaultValue("updated") String orderBy,
            @QueryParam("$skip") @DefaultValue("0") int skip,
            @QueryParam("$top") @DefaultValue("-1") int top,
            @QueryParam("searchTerm") String searchTerm,
            @QueryParam("targetFramework") String targetFramework) {
        try {
            logger.debug("Запрос пакетов из хранилища {}: filter={}, orderBy={}, skip={}, "
                    + "top={}, searchTerm={}, targetFramework={}",
                    new Object[]{storageName, filter, orderBy, skip, top, searchTerm, targetFramework});
            PackageSource<Nupkg> packageSource = getPackageSource();
            if (packageSource == null) {
                return Response.status(Response.Status.NOT_FOUND).build();
            }
            PackageFeed feed = getPackageFeed(packageSource, filter, searchTerm, targetFramework, orderBy, skip, top);
            XmlStreamingOutput streamingOutput = new XmlStreamingOutput(feed);
            return Response.ok(streamingOutput, MediaType.APPLICATION_ATOM_XML_TYPE).build();
        } catch (Exception e) {
            final String errorMessage = "Ошибка получения списка пакетов";
            logger.error(errorMessage, e);
            return Response.serverError().entity(errorMessage).build();
        }
    }

    /**
     * Возвращает количество пакетов
     *
     * @param filter условие выборки пакетов
     * @param searchTerm условие поиска
     * @param targetFramework фрейморк, для которого предназначен пакет
     * @return TEXT c числом пакетов
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("{packages : (Packages)[(]?[)]?|(Search)[(][)]}/{count : [$]count}")
    public Response getPackageCount(@QueryParam("$filter") String filter,
            @QueryParam("searchTerm") String searchTerm,
            @QueryParam("targetFramework") String targetFramework) {
        try {
            logger.debug("Запрос количества пакетов из хранилища {}: filter={}, searchTerm={}, targetFramework={}",
                    new Object[]{storageName, filter, searchTerm, targetFramework});
            PackageSource<Nupkg> packageSource = getPackageSource();
            if (packageSource == null) {
                return Response.status(Response.Status.NOT_FOUND).build();
            }
            Collection<? extends Nupkg> files = getPackages(packageSource, filter, searchTerm, targetFramework);
            final int count = files.size();
            logger.debug("Получено {} пакетов", new Object[]{count});
            return Response.ok(Integer.toString(count), MediaType.TEXT_PLAIN).build();
        } catch (Exception e) {
            final String errorMessage = "Ошибка получения списка пакетов";
            logger.error(errorMessage, e);
            return Response.serverError().entity(errorMessage).build();
        }
    }

    /**
     * Получения потока с данными пакета
     *
     * @param id идентификатор пакета
     * @param versionString строка версии пакета
     * @return поток с файлом пакета
     */
    @GET
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    @Path("download/{id}/{version}")
    public Response getPackage(@PathParam("id") String id,
            @PathParam("version") String versionString) {
        try {
            Version version = Version.parse(versionString);
            PackageSource packageSource = getPackageSource();
            if (packageSource == null) {
                return Response.status(Response.Status.NOT_FOUND).build();
            }
            Nupkg nupkg = packageSource.getPackage(id, version);
            if (nupkg == null) {
                logger.warn("Пакет " + id + ":" + versionString + " не найден");
                return Response.status(Response.Status.NOT_FOUND).build();
            }
            InputStream inputStream = nupkg.getStream();
            ResponseBuilder response = Response.ok((Object) inputStream);
            response.header(HttpHeaders.CONTENT_LENGTH, nupkg.getSize());
            response.type(MediaType.APPLICATION_OCTET_STREAM);
            String fileName = nupkg.getFileName();
            response.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            return response.build();
        } catch (Exception e) {
            final String errorMessage = "Ошибка получения пакета " + id + " " + versionString;
            logger.error(errorMessage, e);
            return Response.serverError().entity(errorMessage).build();
        }
    }

    @GET
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    @Path("downloadPart/{storage}/{id}/{version}")
    public Response getPackagePart(
            @PathParam("storage") int storageId,
            @PathParam("id") String id,
            @PathParam("version") String versionString) {
        return Response.serverError().entity("Не реализовано").build();
    }

    /**
     * Метод помещения пакета в хранилище для версии NuGet старше 1.6
     *
     * @param apiKey ключ доступа
     * @param inputStream поток данных
     * @return ответ сервера (CREATED или FORBIDDEN)
     */
    @PUT
    @Path("")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response putPackage(@HeaderParam(API_KEY_HEADER_NAME) String apiKey,
            @FormDataParam("package") InputStream inputStream) {
        return pushPackage(apiKey, inputStream, Response.Status.CREATED);
    }

    /**
     * Метод помещения в хранилище для версии NuGet младше 1.6
     *
     * @param apiKey ключ доступа
     * @param inputStream поток данных
     * @return ответ сервера (OK или FORBIDDEN)
     */
    @POST
    @Path("PackageFiles/{apiKey}/nupkg")
    @Consumes(MediaType.APPLICATION_OCTET_STREAM)
    public Response postPackage(@PathParam("apiKey") String apiKey, InputStream inputStream) {
        return pushPackage(apiKey, inputStream, Response.Status.OK);
    }

    @POST
    @Path("PublishedPackages/Publish")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response postPackageMetadata(InputStream inputStream) {
        //JSONJAXBContext context = JSONJAXBContext.newInstance(classesToBeBound);
        //TODO необходимо обработать запрос
        //{"id":"Neolant.IOT.EventBus","key":"4003d786-cc37-4004-bfdf-c4f3e8ef9b3a","version":"0.0.2.557"}
        ResponseBuilder response = Response.ok();
        return response.build();
    }

    /**
     * Удаление пакета из хранилища для NuGet версии младше 1.6
     *
     * @param apiKey ключ доступа
     * @param packageId идентификатор пакета
     * @param versionString версия пакета
     * @return ответ сервера
     */
    @DELETE
    @Path("Packages/{apiKey}/{packageId}/{versionString}")
    public Response deletePackageOld(
            @PathParam("apiKey") String apiKey,
            @PathParam("packageId") String packageId,
            @PathParam("versionString") String versionString) {
        return deletePackage(apiKey, packageId, versionString);
    }

    /**
     * Удаление пакета из хранилища для NuGet версии 1.6 и старше
     *
     * @param apiKey ключ доступа
     * @param packageId идентификатор пакета
     * @param versionString версия пакета
     * @return ответ сервера
     */
    @DELETE
    @Path("{packageId}/{versionString}")
    public Response deletePackageNew(
            @HeaderParam(API_KEY_HEADER_NAME) String apiKey,
            @PathParam("packageId") String packageId,
            @PathParam("versionString") String versionString) {

        return deletePackage(apiKey, packageId, versionString);

    }

    /**
     * Удаление пакета из хранилища
     *
     * @param apiKey ключ доступа
     * @param packageId идентификатор пакета
     * @param versionString версия пакета
     * @return результат удаления
     */
    private Response deletePackage(String apiKey,
            String packageId,
            String versionString) {
        NugetContext nugetContext = new NugetContext(getCurrentStorageURI());
        try {
            nugetContext.login(apiKey);
            try {
                if (nugetContext.isUserInRole(Role.Delete)) {
                    Version version = Version.parse(versionString);
                    PackageSource<Nupkg> packageSource = getPackageSource();
                    if (packageSource == null) {
                        return Response.status(Response.Status.NOT_FOUND).build();
                    }
                    Nupkg nupkg = packageSource.getPackage(packageId, version);
                    if (nupkg == null) {
                        return Response.status(Response.Status.NOT_FOUND).build();
                    }
                    packageSource.removePackage(nupkg);
                    return Response.status(Response.Status.OK).build();
                } else {
                    return Response.status(Response.Status.FORBIDDEN).build();
                }
            } finally {
                nugetContext.logout();
            }
        } catch (LoginException e) {
            logger.warn("Не достаточно прав на удаление пакета " + e.getLocalizedMessage());
            return Response.status(Response.Status.FORBIDDEN).build();
        } catch (NugetFormatException e) {
            logger.warn("Не корректная версия пакета " + e.getLocalizedMessage());
            return Response.status(Response.Status.BAD_REQUEST).build();
        }
    }

    /**
     * @return источник пакетов
     */
    private PackageSource<Nupkg> getPackageSource() {
        return PackageSourceFactory.getInstance().getPublicPackageSource(storageName);
    }

    /**
     * Помещает пакет в хранилище
     *
     * @param apiKey ключ доступа
     * @param inputStream поток данных
     * @param correctStatus статус, ожидаемый в случае удачного помещения пакета
     * @return FORBIDDEN или "correctStatus"
     */
    private Response pushPackage(String apiKey, InputStream inputStream, Response.Status correctStatus) {
        try {
            logger.debug("Получен пакет ApiKey={}", new Object[]{apiKey});
            NugetContext nugetContext = new NugetContext(getCurrentStorageURI());
            nugetContext.login(apiKey);
            if (nugetContext.isUserInRole(Role.Push)) {
                ResponseBuilder response;
                try (TempNupkgFile nupkgFile = new TempNupkgFile(inputStream)) {
                    logger.debug("Помещение пакета {} версии {} в хранилище",
                            new Object[]{nupkgFile.getId(), nupkgFile.getVersion()});
                    final PackageSource<Nupkg> packageSource = getPackageSource();
                    if (packageSource == null) {
                        return Response.status(Response.Status.NOT_FOUND).build();
                    }
                    boolean pushed = packageSource.pushPackage(nupkgFile);

                    if (pushed) {
                        response = Response.status(correctStatus);
                    } else {
                        logger.debug("Публикация пакета в хранилище не произведена ApiKey={}", new Object[]{apiKey});
                        response = Response.status(Response.Status.FORBIDDEN);
                    }
                } finally {
                    nugetContext.logout();
                }
                return response.build();
            } else {
                return Response.status(Response.Status.FORBIDDEN).build();
            }
        } catch (LoginException e) {
            final String errorMessage = "Недостаточно прав для помещения пакета в хранилище";
            logger.warn(errorMessage + " " + e.getLocalizedMessage());
            return Response.status(Response.Status.UNAUTHORIZED).entity(errorMessage).build();
        } catch (Exception e) {
            final String errorMessage = "Ошибка помещения пакета в хранилище";
            logger.error(errorMessage, e);
            return Response.serverError().entity(errorMessage).build();
        }

    }

    /**
     * Возвращает объектную реализацию RSS рассылки с пакетами
     *
     * @param packageSource источник пакетов
     * @param filter условие фильтрации
     * @param searchTerm условие поиска
     * @param targetFramework список фреймворков, для которых предназначен пакет
     * @param orderBy условие упорядочивания
     * @param skip количество пропускаемых записей
     * @param top количество возвращаемых записей
     * @return объектное представление RSS
     */
    private PackageFeed getPackageFeed(PackageSource<Nupkg> packageSource, String filter, String searchTerm, String targetFramework, String orderBy, int skip, int top) {
        //Получить пакеты
        Collection<? extends Nupkg> files = getPackages(packageSource, filter, searchTerm, targetFramework);
        logger.debug("Получено {} пакетов", new Object[]{files.size()});
        //Преобразовать пакеты в RSS
        NugetContext nugetContext = new NugetContext(getCurrentStorageURI());
        NuPkgToRssTransformer toRssTransformer = nugetContext.createToRssTransformer();
        PackageFeed feed = toRssTransformer.transform(files, orderBy, skip, top);
        return feed;
    }

    /**
     * Возвращает коллекцию пакетов, соответствующую условиям поиска
     *
     * @param packageSource источник пакетов
     * @param filter условие фильтрации
     * @param searchTerm условие поиска
     * @param targetFramework список фреймворков, для которых предназначен пакет
     * @return коллекция пакетов
     */
    private Collection<? extends Nupkg> getPackages(PackageSource<Nupkg> packageSource, String filter, String searchTerm, String targetFramework) {
        //Выбрать пакеты по запросу
        QueryExecutor queryExecutor = new QueryExecutor();
        Collection<? extends Nupkg> files = queryExecutor.execQuery(packageSource, filter, searchTerm, targetFramework);
        return files;
    }

    /**
     * @return URI текущего хранилища
     */
    private URI getCurrentStorageURI() {
        return URI.create(context.getBaseUri().toString() + storageName + "/");
    }
    /**
     * Имя заголовка запроса с ключем доступа
     */
    public static final String API_KEY_HEADER_NAME = "X-NuGet-ApiKey";
}
TOP

Related Classes of ru.aristar.jnuget.MainUrlResource

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.