All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.aequologica.neo.serioulizer.jaxrs.service.Resource Maven / Gradle / Ivy

The newest version!
package net.aequologica.neo.serioulizer.jaxrs.service;

import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
import static javax.ws.rs.core.MediaType.valueOf;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.status;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;

import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Joiner;
import net.aequologica.neo.serioulizer.Serioulizer;

@Singleton
@javax.ws.rs.Path("v1")
public class Resource {
    
    @SuppressWarnings("unused")
    private static final Logger log = LoggerFactory.getLogger(Resource.class);

    @Inject 
    private Serioulizer serioulizer;

    @Context
    private ServletContext context;
    
    @GET
    @javax.ws.rs.Path("_ping_")
    @Produces(MediaType.TEXT_PLAIN)
    public Response ping() {
        return Response.ok().entity("api/serioulizer/v1 is here").build();
    }
    
    @GET
    @javax.ws.rs.Path("/list/{path : .*}")
    @Produces(MediaType.APPLICATION_JSON)
    public List _GET_list__path(
            @DefaultValue("")      @PathParam ("path") final String  path,
            @DefaultValue("false") @QueryParam("sort") final Boolean sort) throws IOException {

        List list = paths2strings(serioulizer.list( path.length() == 0 ? Paths.get("/") : Paths.get(path)));

        if (sort) {
            Collections.sort(list, Comparator.naturalOrder());
        }

        return list;
    }

    /*
     * read http://www.pixeldonor.com/2013/oct/12/concurrent-zip-compression-java-nio/
     */
    @GET
    @javax.ws.rs.Path("/zip/{path : .*}")
    @Produces("application/zip")
    public Response _GET_zip__path(
            @DefaultValue("") @PathParam ("path") final String  pathAsString,
                              @Context            final UriInfo uriInfo) throws IOException {

        final StreamingOutput streamingOutput = new StreamingOutput() {
            @Override
            public void write(OutputStream output) throws IOException, WebApplicationException {
                try {
                    final List list = serioulizer.list( pathAsString.length() == 0 ? Paths.get("/") : Paths.get(pathAsString));

                    try (ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(output))) {
                        zipOutputStream.setLevel(9);
                        for (Path path : list) {
                            // @TODO Path relativized = serioulizer.relativize(path);
                            Path relativized = path;

                            zipOutputStream.putNextEntry(new ZipEntry(relativized.toString()));

                            Serioulizer.Stream stream = serioulizer.getStream(relativized);
                            if (stream != null) {
                                pipe(stream.getInputStream(), zipOutputStream);
                            }
                            zipOutputStream.closeEntry();
                        }
                    }
                } catch (Exception e) {
                    throw new WebApplicationException(e);
                }
            }
        };

        String filenameWithoutExtension = Joiner.on('-')
                                                .skipNulls()
                                                .join( uriInfo.getBaseUri()
                                                              .getHost(),
                                                       "stnemucod",
                                                       com.google.common.base.Strings.emptyToNull( pathAsString.replace('/', ' ')
                                                                                        .replace('\\', ' ')
                                                                                        .trim()
                                                                                        .replace(' ', '_')));

        return ok(streamingOutput)
               .type("application/zip")
               .header("Content-Disposition",  "attachment; filename=\"" + filenameWithoutExtension + ".zip\"")
               .build();
    }

    @GET
    @javax.ws.rs.Path("/document/{path : .+}")
    public Response _GET_document__path(
            @DefaultValue("") @PathParam ("path") final String pathAsString) throws IOException {

        Serioulizer.Stream stream = null;
        try {
            stream = serioulizer.getStream(Paths.get(pathAsString));
        } catch (IOException ioe) {
            return status(NOT_FOUND).build();
        }
        return ok( stream.getInputStream(), 
                   pathAsString.endsWith("svg") ? "image/svg+xml" : 
                   pathAsString.endsWith("css") ? "text/css"      : 
                   stream.getMimeType()
               ).header( "Content-Length", stream.getLength() )
               .build();
    }

    @PUT
    @javax.ws.rs.Path("/document/{path : .+}")
    @Consumes(MediaType.TEXT_PLAIN)
    public Response _PUT_document__path(
            @DefaultValue("/") @PathParam("path") final String pathAsString,
            final InputStream content) throws IOException {
        serioulizer.write( Paths.get(pathAsString), Serioulizer.createStream(content, "text/plain; charset=UTF-8", -1));
        return noContent().build();
    }

    @POST
    @javax.ws.rs.Path("/upload/{path : .*}")
    @Consumes(MediaType.MULTIPART_FORM_DATA) // THIS REQUIRES register(MultiPartFeature.class) !!!!! 
    public Response _POST_document__path(
            @DefaultValue("/")     @PathParam     ("path")     final String                     pathAsString,
                                   @FormDataParam ("file")     final FormDataContentDisposition fileDetail,
                                   @FormDataParam ("file")     final FormDataBodyPart           body,
                                   @FormDataParam ("file")     final InputStream                inputStream,
            @DefaultValue("true")  @QueryParam    ("isUTF8")   final Boolean                    isUTF8,
            @DefaultValue("false") @QueryParam    ("doUnzip")  final Boolean                    doUnzip) throws IOException {

        if (null == fileDetail) {
            throw new IllegalArgumentException("@FormDataParam(\"file\") FormDataContentDisposition fileDetail is null");
        }

        if (null == inputStream) {
            throw new IllegalArgumentException("@FormDataParam(\"file\") InputStream inputStream is null");
        }

        final String filename = fileDetail.getParameters().get("filename");

        if (null == filename || filename.length() == 0) {
            throw new IllegalArgumentException("fileDetail.getParameters().get(\"filename\") is null or empty");
        }
        
        MediaType mediaType = body.getMediaType();
        if (mediaType.toString().startsWith(MediaType.APPLICATION_OCTET_STREAM.toString())) {
            // APPLICATION_OCTET_STREAM is default, try to ask servlet context for something more precise
            String mimeTypeFromServletContext = context.getMimeType(filename);
            if (mimeTypeFromServletContext != null) {
                mediaType = MediaType.valueOf(mimeTypeFromServletContext);
            }
        }
        if (isUTF8 != null && isUTF8) {
            mediaType = mediaType.withCharset(StandardCharsets.UTF_8.name());
        }
        final String mimeType = mediaType.toString();

        if (doUnzip && (mimeType.startsWith("application/zip") || 
                        mimeType.startsWith("application/x-zip"))) {
            try (final ZipInputStream zipInputStream = new ZipInputStream(inputStream)){
                for (ZipEntry zipEntry = zipInputStream.getNextEntry(); zipEntry != null ; zipEntry = zipInputStream.getNextEntry()) {
                    if (!zipEntry.isDirectory()) {
                        serioulizer.write(  Paths.get(zipEntry.getName()),
                                Serioulizer.createStream( zipInputStream, 
                                              guessMimeType(zipEntry.getName(), isUTF8, context),
                                              zipEntry.getSize()));
                    }
                    zipInputStream.closeEntry();
                }
            }
            return noContent().build();
        }

        serioulizer.write( Paths.get(pathAsString, filename),
                Serioulizer.createStream(inputStream, mimeType, fileDetail.getSize()));

        return noContent().build();
    }
    
    @DELETE
    @javax.ws.rs.Path("/document/{path : .+}")
    public Response _DELETE_document__path(@PathParam("path") String path) throws IOException {
        serioulizer.delete(Paths.get(path));
        return noContent().build();
    }

    static private List paths2strings(List paths) {
        if (paths == null) {
            return Collections.emptyList();
        }

        return paths.stream().map(p -> p.toString()).collect(Collectors.toList());
    }

    static private void pipe(final InputStream is, final OutputStream os) throws IOException {
        int n;
        byte[] buffer = new byte[1024];
        while ((n = is.read(buffer)) > -1) {
            os.write(buffer, 0, n);
        }
    }

    private static String guessMimeType(final String filename, final Boolean isUTF8, final ServletContext context) {
        MediaType mediaType = APPLICATION_OCTET_STREAM_TYPE;

        String guessedMimeType = context.getMimeType(filename.toString());
        if (guessedMimeType != null) {
            mediaType = valueOf(guessedMimeType);
        }

        if (isUTF8 != null && isUTF8) {
            mediaType = mediaType.withCharset(StandardCharsets.UTF_8.name());
        }

        return mediaType.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy