com.slytechs.capture.StreamFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.slytechs.capture.StreamFactory.java

Source

/**
 * Copyright (C) 2007 Sly Technologies, Inc. This library is free software; you
 * can redistribute it and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version. This
 * library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details. You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package com.slytechs.capture;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteOrder;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.zip.GZIPInputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jnetstream.capture.CapturePacket;
import org.jnetstream.capture.FilePacket;
import org.jnetstream.capture.FormatType;
import org.jnetstream.capture.InputCapture;
import org.jnetstream.capture.OutputCapture;
import org.jnetstream.capture.Captures.LocalFactory;
import org.jnetstream.capture.file.pcap.PcapInput;
import org.jnetstream.capture.file.snoop.SnoopInput;
import org.jnetstream.filter.Filter;
import org.jnetstream.packet.ProtocolFilterTarget;

import com.slytechs.file.pcap.PcapInputCapture;
import com.slytechs.file.snoop.SnoopInputCapture;
import com.slytechs.utils.factory.FactoryLoader;
import com.slytechs.utils.memory.channel.BufferedReadableByteChannel;

/**
 * @author Mark Bednarczyk
 * @author Sly Technologies, Inc.
 */
public abstract class StreamFactory extends LiveFactory implements LocalFactory {

    private final static Log logger = LogFactory.getLog(StreamFactory.class);

    /**
     * Factory for loading <code>FormatType.Other</code> which by default
     * invokes an NPL based codec to decode the file format.
     */
    private static final FactoryLoader<InputCapture.FormatTypeOtherFactory> factoryForOther = new FactoryLoader<InputCapture.FormatTypeOtherFactory>(
            logger, InputCapture.PROPERTY_INPUTCAPTURE_OTHER_FACTORY,
            InputCapture.DEFAULT_INPUTCAPTURE_OTHER_FACTORY);

    public FormatType formatType(final ReadableByteChannel in) throws IOException {

        /*
         * Wrap the original input in buffer channel so that we can rewind and check
         * various types.
         */

        final BufferedReadableByteChannel b = new BufferedReadableByteChannel(in);
        b.mark(24); // Max number of bytes of all the known block headers

        if (PcapInputCapture.checkFormat(b) != null) {
            return FormatType.Pcap;
        }

        b.reset();

        if (SnoopInputCapture.checkFormat(b) != null) {
            return FormatType.Snoop;
        }

        b.reset();

        if (factoryForOther.getFactory().formatType(b) != null) {
            return FormatType.Other;
        }

        return null;
    }

    public FormatType.Detail formatTypeDetail(final ReadableByteChannel in) throws IOException {

        /*
         * Wrap the original input in buffer channel so that we can rewind and check
         * various types.
         */

        final BufferedReadableByteChannel b = new BufferedReadableByteChannel(in);
        b.mark(24); // Max number of bytes of all the known block headers

        if (PcapInputCapture.checkFormat(b) != null) {
            return new DefaultFormatTypeDetail(FormatType.Pcap);
        }

        b.reset();

        if (SnoopInputCapture.checkFormat(b) != null) {
            return new DefaultFormatTypeDetail(FormatType.Snoop);
        }

        b.reset();

        final FormatType.Detail detail;

        detail = factoryForOther.getFactory().formatTypeDetail(b);

        return detail;
    }

    public <T extends InputCapture<? extends FilePacket>> T newInput(final Class<T> t, final File file,
            Filter<ProtocolFilterTarget> filter) throws IOException {

        final BufferedInputStream b = new BufferedInputStream(new FileInputStream(file));
        b.mark(1024); // Buffer first 1K of stream so we can rewind

        /*
         * Check the stream, without decompression first
         */
        if (formatType(Channels.newChannel(b)) != null) {
            b.close();

            /*
             * This is a plain uncompressed file, open up a FileChannel. It will be
             * much faster
             */
            return newInput(t, new RandomAccessFile(file, "rw").getChannel(), filter);
        }

        /*
         * Try with gunziped stream, second
         */
        b.reset(); // Rewind
        if (formatType(Channels.newChannel(new GZIPInputStream(b))) != null) {
            b.close();

            /*
             * Now reopen the same file, but this time without the buffered
             * inputstream in the middle. Try to make things as efficient as possible.
             * TODO: implement much faster channel based GZIP decompression algorithm
             */
            return newInput(t, Channels.newChannel(new GZIPInputStream(new FileInputStream(file))), filter);
        }

        throw new IllegalArgumentException(
                "File is not any compressed or decompressed known format [" + file.getName() + "]");

    }

    public <T extends InputCapture<? extends FilePacket>> T newInput(final Class<T> t, final ReadableByteChannel in)
            throws IOException {
        return this.newInput(t, in, null);
    }

    public <T extends InputCapture<? extends FilePacket>> T newInput(final Class<T> t, final ReadableByteChannel in,
            final Filter<ProtocolFilterTarget> filter) throws IOException {
        if (t == PcapInput.class) {
            final BufferedReadableByteChannel b = new BufferedReadableByteChannel(in);
            b.mark(4);

            ByteOrder order = PcapInputCapture.checkFormat(b);

            b.reset();
            return t.cast(new PcapInputCapture(b, order, filter));

        } else if (t == SnoopInput.class) {
            return t.cast(new SnoopInputCapture(in, filter));
        }

        throw new IllegalArgumentException("Unknown input stream format type [" + t.getName() + "]");
    }

    public InputCapture<? extends CapturePacket> newInput(final File file,
            final Filter<ProtocolFilterTarget> filter) throws IOException {

        final BufferedInputStream b = new BufferedInputStream(new FileInputStream(file));
        b.mark(1024); // Buffer first 1K of stream so we can rewind

        /*
         * Check the stream, without decompression first
         */
        if (formatType(Channels.newChannel(b)) != null) {
            b.close();

            /*
             * This is a plain uncompressed file, open up a FileChannel. It will be
             * much faster
             */
            return newInput(new RandomAccessFile(file, "rw").getChannel(), filter);
        }

        /*
         * Try with gunziped stream, second
         */
        b.reset(); // Rewind
        if (formatType(Channels.newChannel(new GZIPInputStream(b))) != null) {
            b.close();

            /*
             * Now reopen the same file, but this time without the buffered
             * inputstream in the middle. Try to make things as efficient as possible.
             * TODO: implement much faster channel based GZIP decompression algorithm
             */
            return newInput(Channels.newChannel(new GZIPInputStream(new FileInputStream(file))), filter);
        }

        b.close();
        return factoryForOther.getFactory().newInput(new RandomAccessFile(file, "r").getChannel(), filter);

    }

    /**
     * 
     */
    public InputCapture<? extends CapturePacket> newInput(final ReadableByteChannel in) throws IOException {
        return this.newInput(in, null);
    }

    /**
     * 
     */
    public InputCapture<? extends CapturePacket> newInput(final ReadableByteChannel in,
            final Filter<ProtocolFilterTarget> filter) throws IOException {

        final BufferedReadableByteChannel b = new BufferedReadableByteChannel(in);
        b.mark(24);

        final FormatType type = this.formatType(b);

        switch (type) {
        case Pcap:
            b.reset();
            ByteOrder order = PcapInputCapture.checkFormat(b);

            b.reset();
            return new PcapInputCapture(b, order, filter);

        case Snoop:
            return new SnoopInputCapture(b, filter);

        /**
         * Loads NPL based file formats. Use
         * <code>InputCapture.getFormatName()</code> to get a more accurate
         * name of the file format if its NPL based.
         */
        case Other:
            b.reset();
            return factoryForOther.getFactory().newInput(b, filter);

        default:
            /*
             * Otherwise throw an exception, we don't recognize the format
             */
            throw new IllegalStateException("Unrecognized internal format type [" + type + "]");

        }
    }

    public <T extends OutputCapture> T newOutput(final Class<T> t, final OutputStream out) throws IOException {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Not implemented yet");
    }

    public <T extends OutputCapture> T newOutput(final Class<T> t, final WritableByteChannel out)
            throws IOException {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Not implemented yet");
    }

    public OutputCapture newOutput(final FormatType type, final OutputStream out) throws IOException {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Not implemented yet");
    }
}