From 32dc5354e2916387a2c62eadae0a4568023f1151 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 3 Jun 2014 16:47:36 +0200 Subject: Initial commit --- .../java/org/openslx/satserver/util/Archive.java | 217 +++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 src/main/java/org/openslx/satserver/util/Archive.java (limited to 'src/main/java/org/openslx/satserver/util/Archive.java') diff --git a/src/main/java/org/openslx/satserver/util/Archive.java b/src/main/java/org/openslx/satserver/util/Archive.java new file mode 100644 index 0000000..dcc1380 --- /dev/null +++ b/src/main/java/org/openslx/satserver/util/Archive.java @@ -0,0 +1,217 @@ +package org.openslx.satserver.util; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Calendar; +import java.util.GregorianCalendar; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveException; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.archivers.ar.ArArchiveEntry; +import org.apache.commons.compress.archivers.cpio.CpioArchiveEntry; +import org.apache.commons.compress.archivers.dump.DumpArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.compressors.CompressorStreamFactory; +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream; +import org.apache.commons.io.FileUtils; + +public class Archive +{ + + /** + * Create input stream from given archive file. The archive format will be guessed + * from the firt couple of bytes in the file, which should work for most archive + * formats (see apache commons-compress docs for detailed information) + * + * @param fileName archive to open for reading + * @return ArchiveInputStream stream to read archive from + * @throws FileNotFoundException + * @throws ArchiveException + * @throws IllegalArgumentException + */ + public static ArchiveInputStream getArchiveInputStream( String fileName ) + throws FileNotFoundException, ArchiveException, IllegalArgumentException + { + // Get an input stream for the archive handler + // 1) Get input stream from file + InputStream fileStream = new BufferedInputStream( new FileInputStream( fileName ) ); + // 2) Might be compressed, so try to get a decompressed stream + InputStream archiveStream; + try { + archiveStream = new BufferedInputStream( new CompressorStreamFactory().createCompressorInputStream( fileStream ) ); + } catch ( Exception e ) { + // Might be uncompressed archive, like tar - just try file input stream + archiveStream = fileStream; + } + // 3) Try to create archive input stream - if it succeeds we can read the archive :) + return new ArchiveStreamFactory().createArchiveInputStream( archiveStream ); + } + + /** + * Create tar archive with the given name. Optional compression method is + * determined by the file extension. + * + * @param outputFile name of archive to create; can be relative or absolute path + * @return {@link TarArchiveOutputStream} to write archive entries to + * @throws IOException + */ + @SuppressWarnings( "resource" ) + public static TarArchiveOutputStream createTarArchive( String outputFile ) throws IOException + { + OutputStream outputStream = new BufferedOutputStream( new FileOutputStream( outputFile ) ); + OutputStream compressedOutputStream; + if ( outputFile.endsWith( ".tar.gz" ) || outputFile.endsWith( ".tgz" ) ) { + compressedOutputStream = new BufferedOutputStream( new GzipCompressorOutputStream( outputStream ) ); + } else if ( outputFile.endsWith( ".tar.bz2" ) || outputFile.endsWith( ".tbz" ) ) { + compressedOutputStream = new BufferedOutputStream( new BZip2CompressorOutputStream( outputStream ) ); + } else if ( outputFile.endsWith( ".tar.xz" ) || outputFile.endsWith( ".txz" ) ) { + compressedOutputStream = new BufferedOutputStream( new XZCompressorOutputStream( outputStream ) ); + } else if ( outputFile.endsWith( ".tar.Z" ) || outputFile.endsWith( ".tar.z" ) || outputFile.endsWith( ".tz" ) ) { + compressedOutputStream = new BufferedOutputStream( new XZCompressorOutputStream( outputStream ) ); + } else if ( outputFile.endsWith( ".tar.lzma" ) ) { + compressedOutputStream = new BufferedOutputStream( new XZCompressorOutputStream( outputStream ) ); + } else if ( outputFile.endsWith( ".tar" ) ) { + compressedOutputStream = outputStream; + } else { + outputStream.close(); + return null; + } + try { + return new TarArchiveOutputStream( compressedOutputStream ); + } catch ( Throwable t ) { + compressedOutputStream.close(); + return null; + } + } + + public static TarArchiveEntry createTarArchiveEntry( ArchiveEntry inEntry, int defaultUser, int defaultGroup, int defaultDirMode, int defaultFileMode ) + { + if ( inEntry instanceof TarArchiveEntry ) { + // Source is tar - easy + return (TarArchiveEntry)inEntry; + } + final TarArchiveEntry outEntry = new TarArchiveEntry( inEntry.getName() ); + outEntry.setSize( inEntry.getSize() ); + if ( inEntry instanceof ArArchiveEntry ) { + // Source is ar - has most of the stuff tar supports; transform + outEntry.setIds( ( (ArArchiveEntry)inEntry ).getUserId(), ( (ArArchiveEntry)inEntry ).getGroupId() ); + outEntry.setMode( ( (ArArchiveEntry)inEntry ).getMode() ); + outEntry.setModTime( ( (ArArchiveEntry)inEntry ).getLastModifiedDate() ); + } else if ( inEntry instanceof DumpArchiveEntry ) { + // Source is dump (whatever the fuck that is) - has most of the stuff tar supports; transform + outEntry.setIds( ( (DumpArchiveEntry)inEntry ).getUserId(), ( (DumpArchiveEntry)inEntry ).getGroupId() ); + outEntry.setMode( ( (DumpArchiveEntry)inEntry ).getMode() ); + outEntry.setModTime( ( (DumpArchiveEntry)inEntry ).getLastModifiedDate() ); + } else if ( inEntry instanceof CpioArchiveEntry ) { + // Source is cpio - has most of the stuff tar supports; transform + outEntry.setIds( (int) ( (CpioArchiveEntry)inEntry ).getUID(), (int) ( (CpioArchiveEntry)inEntry ).getGID() ); + outEntry.setMode( (int) ( ( (CpioArchiveEntry)inEntry ).getMode() & 07777 ) ); + outEntry.setModTime( ( (CpioArchiveEntry)inEntry ).getLastModifiedDate() ); + } else if ( inEntry instanceof ZipArchiveEntry ) { + // Source is ZIP - might not have unix stuff + outEntry.setIds( defaultUser, defaultGroup ); + int mode = ( (ZipArchiveEntry)inEntry ).getUnixMode(); + if ( mode != 0 ) { // Has unix permissions + outEntry.setMode( mode ); + } else if ( inEntry.isDirectory() ) { // Use default passed in + outEntry.setMode( defaultDirMode ); + } else { // Use default passed in + outEntry.setMode( defaultFileMode ); + } + outEntry.setModTime( ( (ZipArchiveEntry)inEntry ).getLastModifiedDate() ); + } else { + outEntry.setIds( defaultUser, defaultGroup ); + if ( inEntry.isDirectory() ) { + outEntry.setMode( defaultDirMode ); + } else { + outEntry.setMode( defaultFileMode ); + Calendar cal = GregorianCalendar.getInstance(); + cal.set( 2014, 4, 2, 13, 57 ); + outEntry.setModTime( cal.getTime() ); + } + } + return outEntry; + } + + public static boolean tarAddFile( TarArchiveOutputStream tar, String inArchiveFileName, File sourceFile, int mode ) + { + if ( !sourceFile.exists() || !sourceFile.isFile() ) + return false; + InputStream in; + try { + in = new FileInputStream( sourceFile ); + } catch ( Exception e ) { + e.printStackTrace(); + return false; + } + TarArchiveEntry entry = new TarArchiveEntry( inArchiveFileName ); + long size = FileUtils.sizeOf( sourceFile ); + entry.setIds( 0, 0 ); + entry.setMode( mode ); + entry.setSize( size ); + try { + tar.putArchiveEntry( entry ); + Util.streamCopy( in, tar, size ); + tar.closeArchiveEntry(); + } catch ( IOException e ) { + e.printStackTrace(); + return false; + } finally { + Util.multiClose( in ); + } + return true; + } + + public static boolean tarCreateFileFromString( TarArchiveOutputStream tar, String fileName, String contents, int mode ) + { + return tarCreateFileFromString( tar, fileName, contents.getBytes( StandardCharsets.UTF_8 ), mode ); + } + + public static boolean tarCreateFileFromString( TarArchiveOutputStream tar, String fileName, byte[] contents, int mode ) + { + TarArchiveEntry entry = new TarArchiveEntry( fileName ); + entry.setIds( 0, 0 ); + entry.setMode( mode ); + entry.setSize( contents.length ); + try { + tar.putArchiveEntry( entry ); + tar.write( contents ); + tar.closeArchiveEntry(); + } catch ( IOException e ) { + e.printStackTrace(); + return false; + } + return true; + } + + public static boolean tarCreateSymlink( TarArchiveOutputStream tar, String target, String linkName ) + { + TarArchiveEntry entry = new TarArchiveEntry( linkName, TarArchiveEntry.LF_SYMLINK ); + entry.setIds( 0, 0 ); + entry.setMode( 0777 ); + entry.setLinkName( target ); + try { + tar.putArchiveEntry( entry ); + tar.closeArchiveEntry(); + } catch ( IOException e ) { + e.printStackTrace(); + return false; + } + return true; + } + +} -- cgit v1.2.3-55-g7522