Package org.redline_rpm

Source Code of org.redline_rpm.Util

package org.redline_rpm;

import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.redline_rpm.header.AbstractHeader.Entry;
import org.redline_rpm.header.Header;
import org.redline_rpm.header.Header.HeaderTag;
import org.redline_rpm.header.PayloadCompressionType;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.Formatter;
import java.util.zip.GZIPInputStream;

/**
* General utilities needed to read and write
* RPM files. Some of these utilities are available
* elsewhere but reproduced here to minimize runtime
* dependencies.
*/
public class Util {

  private Util() {}

  /**
   * Converts path characters from their native
   * format to the "forward-slash" format expected
   * within RPM files.
   * @param path the path to the file
   * @return the normalized path
   */
  public static String normalizePath( final String path) {
    return path.replace( '\\', '/');
  }

  /**
   * Creates a new buffer and fills it with bytes from the
   * provided channel. The amount of data to read is specified
   * in the arguments.
   *
   * @param in the channel to read from
   * @param size the number of bytes to read into a new buffer
   * @return a new buffer containing the bytes read
   * @throws IOException if an IO error occurs
   */
  public static ByteBuffer fill( ReadableByteChannel in, int size) throws IOException {
    return fill( in, ByteBuffer.allocate( size));
  }

  /**
   * Fills the provided buffer it with bytes from the
   * provided channel. The amount of data to read is
   * dependant on the available space in the provided
   * buffer.
   *
   * @param in the channel to read from
   * @param buffer the buffer to read into
   * @return the provided buffer
   * @throws IOException if an IO error occurs
   */
  public static ByteBuffer fill( ReadableByteChannel in, ByteBuffer buffer) throws IOException {
    while ( buffer.hasRemaining()) if ( in.read( buffer) == -1) throw new BufferUnderflowException();
    buffer.flip();
    return buffer;
  }

  /**
   * Empties the contents of the given buffer into the
   * writable channel provided. The buffer will be copied
   * to the channel in it's entirety.
   *
   * @param out the channel to write to
   * @param buffer the buffer to write out to the channel
   * @throws IOException if an IO error occurs
   */
  public static void empty( WritableByteChannel out, ByteBuffer buffer) throws IOException {
    while ( buffer.hasRemaining()) out.write( buffer);
  }

  /**
   * Checks that two integers are the same, while generating
   * a formatted error message if they are not. The error
   * message will indicate the hex value of the integers if
   * they do not match.
   *
   * @param expected the expected value
   * @param actual the actual value
   * @throws IOException if the two values do not match
   */
  public static void check( int expected, int actual) throws IOException {
    if ( expected != actual) throw new IOException( "check expected " + Integer.toHexString( 0xff & expected) + ", found " + Integer.toHexString( 0xff & actual));
  }

  /**
   * Checks that two bytes are the same, while generating
   * a formatted error message if they are not. The error
   * message will indicate the hex value of the bytes if
   * they do not match.
   *
   * @param expected the expected value
   * @param actual the actual value
   * @throws IOException if the two values do not match
   */
  public static void check( byte expected, byte actual) throws IOException {
    if ( expected != actual) throw new IOException( "check expected " + Integer.toHexString( 0xff & expected) + ", found " + Integer.toHexString( 0xff & actual));
  }

  public static int difference( int start, int boundary) {
    return (( boundary + 1) - ( start & boundary)) & boundary;
  }

  public static int round( int start, int boundary) {
    return ( start + boundary) & ~boundary;
  }

  /**
   * Pads the given buffer up to the indicated boundary.
   * The RPM file format requires that headers be aligned
   * with various boundaries, this method pads output
   * to match the requirements.
   *
   * @param buffer the buffer to pad zeros into
   * @param boundary the boundary to which we need to pad
   */
  public static void pad( ByteBuffer buffer, int boundary) {
    buffer.position( round( buffer.position(), boundary));
  }

  public static void dump( byte[] data) {
    dump( data, System.out);
  }

  public static void dump( byte[] data, Appendable out) {
    dump( ByteBuffer.wrap( data), out);
  }

  public static void dump( char[] data) {
    dump( data, System.out);
  }

  public static void dump( CharSequence data) {
    dump( Charset.forName( "US-ASCII").encode( CharBuffer.wrap( data)), System.out);
  }

  public static void dump( char[] data, Appendable out) {
    dump( Charset.forName( "US-ASCII").encode( CharBuffer.wrap( data)), out);
  }

  public static void dump( ByteBuffer buf, Appendable out) {
    Formatter fmt = new Formatter( out);

    int pos = buf.position();
    fmt.format( "%8x:", pos & ~0xf);
    StringBuilder builder = new StringBuilder();
    for ( int i = 0; i < ( pos & 0xf); i++) {
      fmt.format( "   ");
      builder.append( ' ');
    }
    while ( buf.hasRemaining()) {
      byte b = buf.get();
      fmt.format( " %2x", b);
      if ( ' ' <= b && b < 0x7f) {
        builder.append(( char) b);
      } else {
        builder.append( ' ');
      }
      if ( buf.hasRemaining() && ( buf.position() & 0xf) == 0) {
        fmt.format( " %s\n%8x:", builder, buf.position());
        builder.setLength( 0);
      }
    }
    buf.position( pos);
  }

  public static String hex( byte[] data) {
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final PrintStream printer = new PrintStream( baos);
    for ( byte b : data) printer.format( "%02x", b);
    printer.flush();
    return baos.toString();
  }

   /**
    * Create the proper stream wrapper to handling the rpmIS payload section based on the
    * payload compression header tag.
    *
    * @param header the header
    * @param rpmIS raw input stream of the rpm
    * @return the "proper" input stream
    * @throws IOException an IO error occurred
    */
   public static InputStream openPayloadStream(Header header, InputStream rpmIS) throws IOException {
      Entry pcEntry = header.getEntry(HeaderTag.PAYLOADCOMPRESSOR);
      String[] pc = (String[]) pcEntry.getValues();
      PayloadCompressionType pcType = PayloadCompressionType.valueOf(pc[0]);
      InputStream payloadIS = rpmIS;
      switch (pcType) {
         case none:
            break;
         case gzip:
            payloadIS = new GZIPInputStream(rpmIS);
            break;
         case bzip2:
            try {
               payloadIS = new org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream(rpmIS);
            } catch (Exception e) {
               throw new IOException("Failed to load BZIP2 compression stream", e);
            }
            break;
         case xz:
            try {
               payloadIS = new XZCompressorInputStream(rpmIS);
            } catch (Exception e) {
               throw new IOException("Failed to load XZ compression stream", e);
            }
            break;
      }
      return payloadIS;
   }
}
TOP

Related Classes of org.redline_rpm.Util

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.