implement gzip compression for unbundle command

This commit is contained in:
Sebastian Sdorra
2014-12-01 11:14:19 +01:00
parent 0cd09bf226
commit 34d05ef3a0
7 changed files with 241 additions and 27 deletions

View File

@@ -81,6 +81,17 @@ public class ImportBundleSubCommand extends ImportSubCommand
return name; return name;
} }
/**
* Method description
*
*
* @return
*/
public boolean isCompressed()
{
return compressed;
}
//~--- set methods ---------------------------------------------------------- //~--- set methods ----------------------------------------------------------
/** /**
@@ -94,6 +105,17 @@ public class ImportBundleSubCommand extends ImportSubCommand
this.bundle = bundle; this.bundle = bundle;
} }
/**
* Method description
*
*
* @param compressed
*/
public void setCompressed(boolean compressed)
{
this.compressed = compressed;
}
/** /**
* Method description * Method description
* *
@@ -122,9 +144,13 @@ public class ImportBundleSubCommand extends ImportSubCommand
{ {
ScmClientSession session = createSession(); ScmClientSession session = createSession();
Repository repository = session.getRepositoryHandler().importFromBundle( ImportBundleRequest req = new ImportBundleRequest(getType(), name,
new ImportBundleRequest( Files.asByteSource(bundle));
getType(), name, Files.asByteSource(bundle)));
req.setCompressed(compressed);
Repository repository =
session.getRepositoryHandler().importFromBundle(req);
printImportedRepository(repository); printImportedRepository(repository);
} }
@@ -141,6 +167,14 @@ public class ImportBundleSubCommand extends ImportSubCommand
) )
private File bundle; private File bundle;
/** Field description */
@Option(
name = "--compressed",
usage = "optionRepositoryBundleCompressed",
aliases = { "-c" }
)
private boolean compressed = false;
/** Field description */ /** Field description */
@Option( @Option(
name = "--name", name = "--name",

View File

@@ -53,6 +53,7 @@ optionRepositoryPublic = Repository public readable
optionRepositoryArchive = Repository archived optionRepositoryArchive = Repository archived
optionRemoteRepositoryUrl = Remote repository url optionRemoteRepositoryUrl = Remote repository url
optionRepositoryBundle = Import repository from a bundle file (e.g. svn dump) optionRepositoryBundle = Import repository from a bundle file (e.g. svn dump)
optionRepositoryBundleCompressed = Indicates that the bundle is gzip compressed
optionPermissionGroup = Group optionPermissionGroup = Group
optionPermissionName = Group or user name optionPermissionName = Group or user name

View File

@@ -26,8 +26,13 @@
* http://bitbucket.org/sdorra/scm-manager * http://bitbucket.org/sdorra/scm-manager
* *
*/ */
package sonia.scm.client; package sonia.scm.client;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.io.ByteSource; import com.google.common.io.ByteSource;
/** /**
@@ -37,14 +42,21 @@ import com.google.common.io.ByteSource;
*/ */
public class ImportBundleRequest public class ImportBundleRequest
{ {
private String type;
private String name;
private ByteSource bundle;
ImportBundleRequest() /**
{ * Constructs ...
} *
*/
ImportBundleRequest() {}
/**
* Constructs ...
*
*
* @param type
* @param name
* @param bundle
*/
public ImportBundleRequest(String type, String name, ByteSource bundle) public ImportBundleRequest(String type, String name, ByteSource bundle)
{ {
this.type = type; this.type = type;
@@ -52,19 +64,76 @@ public class ImportBundleRequest
this.bundle = bundle; this.bundle = bundle;
} }
public String getType() //~--- get methods ----------------------------------------------------------
{
return type;
}
public String getName()
{
return name;
}
/**
* Method description
*
*
* @return
*/
public ByteSource getBundle() public ByteSource getBundle()
{ {
return bundle; return bundle;
} }
/**
* Method description
*
*
* @return
*/
public String getName()
{
return name;
}
/**
* Method description
*
*
* @return
*/
public String getType()
{
return type;
}
/**
* Method description
*
*
* @return
*/
public boolean isCompressed()
{
return compressed;
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param compressed
*/
public void setCompressed(boolean compressed)
{
this.compressed = compressed;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private ByteSource bundle;
/** Field description */
private boolean compressed = false;
/** Field description */
private String name;
/** Field description */
private String type;
} }

View File

@@ -58,6 +58,7 @@ import java.io.InputStream;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
/** /**
@@ -80,6 +81,9 @@ public class JerseyRepositoryClientHandler
/** Field description */ /** Field description */
private static final String PARAM_BUNDLE = "bundle"; private static final String PARAM_BUNDLE = "bundle";
/** Field description */
private static final String PARAM_COMPRESSED = "compressed";
/** Field description */ /** Field description */
private static final String PARAM_NAME = "name"; private static final String PARAM_NAME = "name";
@@ -113,7 +117,8 @@ public class JerseyRepositoryClientHandler
public Repository importFromBundle(ImportBundleRequest request) public Repository importFromBundle(ImportBundleRequest request)
{ {
WebResource r = client.resource(getImportUrl(request.getType(), WebResource r = client.resource(getImportUrl(request.getType(),
IMPORT_TYPE_BUNDLE)); IMPORT_TYPE_BUNDLE)).queryParam(PARAM_COMPRESSED,
Boolean.toString(request.isCompressed()));
Repository repository = null; Repository repository = null;
InputStream stream = null; InputStream stream = null;

View File

@@ -56,6 +56,8 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.zip.GZIPInputStream;
/** /**
* The unbundle command can restore an empty repository from a bundle. The * The unbundle command can restore an empty repository from a bundle. The
* bundle can be created with the {@link BundleCommandBuilder}. * bundle can be created with the {@link BundleCommandBuilder}.
@@ -106,7 +108,7 @@ public final class UnbundleCommandBuilder
"existing file is required"); "existing file is required");
UnbundleCommandRequest request = UnbundleCommandRequest request =
new UnbundleCommandRequest(Files.asByteSource(inputFile)); createRequest(Files.asByteSource(inputFile));
logger.info("unbundle archive {} at {}", inputFile, repository.getId()); logger.info("unbundle archive {} at {}", inputFile, repository.getId());
@@ -130,8 +132,7 @@ public final class UnbundleCommandBuilder
checkNotNull(inputStream, "input stream is required"); checkNotNull(inputStream, "input stream is required");
logger.info("unbundle archive from stream"); logger.info("unbundle archive from stream");
return unbundleCommand.unbundle( return unbundleCommand.unbundle(createRequest(asByteSource(inputStream)));
new UnbundleCommandRequest(asByteSource(inputStream)));
} }
/** /**
@@ -151,9 +152,28 @@ public final class UnbundleCommandBuilder
checkNotNull(byteSource, "byte source is required"); checkNotNull(byteSource, "byte source is required");
logger.info("unbundle from byte source"); logger.info("unbundle from byte source");
return unbundleCommand.unbundle(new UnbundleCommandRequest(byteSource)); return unbundleCommand.unbundle(createRequest(byteSource));
} }
//~--- set methods ----------------------------------------------------------
/**
* Set to {@code true} if bundle is gzip compressed. Default is {@code false}.
*
*
* @param compressed {@code true} if bundle is gzip compressed
*
* @return {@code this}
*/
public UnbundleCommandBuilder setCompressed(boolean compressed)
{
this.compressed = compressed;
return this;
}
//~--- methods --------------------------------------------------------------
/** /**
* Converts an {@link InputStream} into a {@link ByteSource}. * Converts an {@link InputStream} into a {@link ByteSource}.
* *
@@ -175,6 +195,73 @@ public final class UnbundleCommandBuilder
}); });
} }
/**
* Creates the {@link UnbundleCommandRequest}.
*
*
* @param source byte source
*
* @return the create request
*/
private UnbundleCommandRequest createRequest(ByteSource source)
{
ByteSource bs;
if (compressed)
{
logger.debug("decode gzip stream for unbundle command");
bs = new CompressedByteSource(source);
}
else
{
bs = source;
}
return new UnbundleCommandRequest(bs);
}
//~--- inner classes --------------------------------------------------------
/**
* ByteSource which is able to handle gzip compressed resources.
*/
private static class CompressedByteSource extends ByteSource
{
/**
* Constructs ...
*
*
* @param wrapped
*/
public CompressedByteSource(ByteSource wrapped)
{
this.wrapped = wrapped;
}
//~--- methods ------------------------------------------------------------
/**
* Opens the stream for reading the compressed source.
*
*
* @return input stream
*
* @throws IOException
*/
@Override
public InputStream openStream() throws IOException
{
return new GZIPInputStream(wrapped.openStream());
}
//~--- fields -------------------------------------------------------------
/** Field description */
private final ByteSource wrapped;
}
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** repository */ /** repository */
@@ -182,4 +269,7 @@ public final class UnbundleCommandBuilder
/** unbundle command implementation */ /** unbundle command implementation */
private final UnbundleCommand unbundleCommand; private final UnbundleCommand unbundleCommand;
/** Field description */
private boolean compressed = false;
} }

View File

@@ -87,11 +87,13 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.GenericEntity;
@@ -156,6 +158,7 @@ public class RepositoryImportResource
* @param type repository type * @param type repository type
* @param name name of the repository * @param name name of the repository
* @param inputStream input bundle * @param inputStream input bundle
* @param compressed true if the bundle is gzip compressed
* *
* @return empty response with location header which points to the imported * @return empty response with location header which points to the imported
* repository * repository
@@ -166,9 +169,11 @@ public class RepositoryImportResource
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
public Response importFromBundle(@Context UriInfo uriInfo, public Response importFromBundle(@Context UriInfo uriInfo,
@PathParam("type") String type, @FormDataParam("name") String name, @PathParam("type") String type, @FormDataParam("name") String name,
@FormDataParam("bundle") InputStream inputStream) @FormDataParam("bundle") InputStream inputStream, @QueryParam("compressed")
@DefaultValue("false") boolean compressed)
{ {
Repository repository = doImportFromBundle(type, name, inputStream); Repository repository = doImportFromBundle(type, name, inputStream,
compressed);
return buildResponse(uriInfo, repository); return buildResponse(uriInfo, repository);
} }
@@ -193,6 +198,7 @@ public class RepositoryImportResource
* @param type repository type * @param type repository type
* @param name name of the repository * @param name name of the repository
* @param inputStream input bundle * @param inputStream input bundle
* @param compressed true if the bundle is gzip compressed
* *
* @return empty response with location header which points to the imported * @return empty response with location header which points to the imported
* repository * repository
@@ -204,13 +210,14 @@ public class RepositoryImportResource
@Produces(MediaType.TEXT_HTML) @Produces(MediaType.TEXT_HTML)
public Response importFromBundleUI(@PathParam("type") String type, public Response importFromBundleUI(@PathParam("type") String type,
@FormDataParam("name") String name, @FormDataParam("name") String name,
@FormDataParam("bundle") InputStream inputStream) @FormDataParam("bundle") InputStream inputStream, @QueryParam("compressed")
@DefaultValue("false") boolean compressed)
{ {
Response response; Response response;
try try
{ {
doImportFromBundle(type, name, inputStream); doImportFromBundle(type, name, inputStream, compressed);
response = Response.ok(new RestActionUploadResult(true)).build(); response = Response.ok(new RestActionUploadResult(true)).build();
} }
catch (WebApplicationException ex) catch (WebApplicationException ex)
@@ -569,11 +576,12 @@ public class RepositoryImportResource
* @param type repository type * @param type repository type
* @param name name of the repository * @param name name of the repository
* @param inputStream bundle stream * @param inputStream bundle stream
* @param compressed true if the bundle is gzip compressed
* *
* @return imported repository * @return imported repository
*/ */
private Repository doImportFromBundle(String type, String name, private Repository doImportFromBundle(String type, String name,
InputStream inputStream) InputStream inputStream, boolean compressed)
{ {
SecurityUtils.getSubject().checkRole(Role.ADMIN); SecurityUtils.getSubject().checkRole(Role.ADMIN);
@@ -601,7 +609,7 @@ public class RepositoryImportResource
logger.info("copied {} bytes to temp, start bundle import", length); logger.info("copied {} bytes to temp, start bundle import", length);
service = serviceFactory.create(repository); service = serviceFactory.create(repository);
service.getUnbundleCommand().unbundle(file); service.getUnbundleCommand().setCompressed(compressed).unbundle(file);
} }
catch (RepositoryException ex) catch (RepositoryException ex)
{ {

View File

@@ -91,6 +91,7 @@ Sonia.repository.ImportPanel = Ext.extend(Ext.Panel, {
importFileNameHelpText: 'The name of the repository in SCM-Manager.', importFileNameHelpText: 'The name of the repository in SCM-Manager.',
importFileHelpText: 'Choose the dump file you want to import to SCM-Manager.', importFileHelpText: 'Choose the dump file you want to import to SCM-Manager.',
importFileGZipCompressedHelpText: 'The file is gzip compressed.',
// tips // tips
tipRepositoryType: 'Choose your repository type for the import.', tipRepositoryType: 'Choose your repository type for the import.',
@@ -314,6 +315,11 @@ Sonia.repository.ImportPanel = Ext.extend(Ext.Panel, {
buttonCfg: { buttonCfg: {
iconCls: 'upload-icon' iconCls: 'upload-icon'
} }
},{
id: 'importFileGZipCompressed',
xtype: 'checkbox',
fieldLabel: 'GZip compressed',
helpText: this.importFileGZipCompressedHelpText
},{ },{
xtype: 'scmTip', xtype: 'scmTip',
content: 'Please insert name and upload the repository file.', content: 'Please insert name and upload the repository file.',
@@ -479,9 +485,10 @@ Sonia.repository.ImportPanel = Ext.extend(Ext.Panel, {
}, },
importFromFile: function(layout, form){ importFromFile: function(layout, form){
var compressed = Ext.getCmp('importFileGZipCompressed').getValue();
var lbox = this.showLoadingBox(); var lbox = this.showLoadingBox();
form.submit({ form.submit({
url: restUrl + 'import/repositories/' + this.repositoryType + '/bundle.html', url: restUrl + 'import/repositories/' + this.repositoryType + '/bundle.html?compressed=' + compressed,
scope: this, scope: this,
success: function(form){ success: function(form){
lbox.hide(); lbox.hide();