/*******************************************************************************
* Copyright (c) 2014, 2015 IBH SYSTEMS GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.packagedrone.repo.channel.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
import java.util.function.Function;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.packagedrone.repo.MetaKey;
import org.eclipse.packagedrone.repo.channel.ArtifactInformation;
import org.eclipse.packagedrone.repo.channel.ChannelArtifactInformation;
import org.eclipse.packagedrone.repo.channel.ChannelNotFoundException;
import org.eclipse.packagedrone.repo.channel.ChannelService;
import org.eclipse.packagedrone.repo.channel.ReadableChannel;
import org.eclipse.packagedrone.repo.channel.ChannelService.By;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.io.ByteStreams;
public final class DownloadHelper
{
private static final MetaKey KEY_MIME_TYPE = new MetaKey ( "mime", "type" );
private final static Logger logger = LoggerFactory.getLogger ( DownloadHelper.class );
private DownloadHelper ()
{
}
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
public static void streamArtifact ( final HttpServletResponse response, final ChannelService service, final String channelId, final String artifactId, final String mimetype, final boolean download ) throws IOException
{
streamArtifact ( response, service, channelId, artifactId, mimetype, download, ArtifactInformation::getName );
}
public static void streamArtifact ( final HttpServletResponse response, final ChannelService service, final String channelId, final String artifactId, final Optional<String> mimetype, final boolean download, final Function<ArtifactInformation, String> nameFunc ) throws IOException
{
try
{
service.accessRun ( By.id ( channelId ), ReadableChannel.class, channel -> {
final ArtifactInformation artifact = channel.getContext ().getArtifacts ().get ( artifactId );
if ( artifact == null )
{
response.setStatus ( HttpServletResponse.SC_NOT_FOUND );
response.setContentType ( "text/plain" );
response.getWriter ().format ( "Artifact '%s' in channel '%s' could not be found", artifact, channelId );
return;
}
streamArtifact ( response, artifact, mimetype, download, channel, nameFunc );
} );
}
catch ( final ChannelNotFoundException e )
{
response.setStatus ( HttpServletResponse.SC_NOT_FOUND );
response.setContentType ( "text/plain" );
response.getWriter ().format ( "Channel '%s' could not be found", channelId );
}
}
public static void streamArtifact ( final HttpServletResponse response, final ChannelService service, final String channelId, final String artifactId, final String mimetype, final boolean download, final Function<ArtifactInformation, String> nameFunc ) throws IOException
{
streamArtifact ( response, service, channelId, artifactId, Optional.ofNullable ( mimetype ), download, nameFunc );
}
public static boolean streamArtifact ( final HttpServletResponse response, final String artifactId, final Optional<String> mimetype, final boolean download, final ReadableChannel channel, final Function<ArtifactInformation, String> nameFunc ) throws IOException
{
final Optional<ChannelArtifactInformation> artifact = channel.getArtifact ( artifactId );
if ( !artifact.isPresent () )
{
return false;
}
return channel.getContext ().stream ( artifactId, stream -> {
streamArtifact ( response, artifact.get (), stream, mimetype, download, nameFunc );
} );
}
public static boolean streamArtifact ( final HttpServletResponse response, final ArtifactInformation artifact, final Optional<String> mimetype, final boolean download, final ReadableChannel channel, final Function<ArtifactInformation, String> nameFunc ) throws IOException
{
return channel.getContext ().stream ( artifact.getId (), stream -> {
streamArtifact ( response, artifact, stream, mimetype, download, nameFunc );
} );
}
public static void streamArtifact ( final HttpServletResponse response, final ArtifactInformation artifact, final InputStream stream, final Optional<String> mimetype, final boolean download, final Function<ArtifactInformation, String> nameFunc ) throws IOException
{
final String mt = mimetype.orElseGet ( () -> evalMimeType ( artifact ) );
response.setStatus ( HttpServletResponse.SC_OK );
response.setContentType ( mt );
response.setDateHeader ( "Last-Modified", artifact.getCreationInstant ().toEpochMilli () );
response.setContentLengthLong ( artifact.getSize () );
if ( download )
{
if ( nameFunc != null )
{
response.setHeader ( "Content-Disposition", String.format ( "attachment; filename=%s", nameFunc.apply ( artifact ) ) );
}
else
{
response.setHeader ( "Content-Disposition", String.format ( "attachment; filename=%s", artifact.getName () ) );
}
}
final long size = ByteStreams.copy ( stream, response.getOutputStream () );
logger.debug ( "Copyied {} bytes", size );
}
private static String evalMimeType ( final ArtifactInformation artifact )
{
final String mimetype = artifact.getMetaData ().get ( KEY_MIME_TYPE );
return mimetype == null ? APPLICATION_OCTET_STREAM : mimetype;
}
}