Java tutorial
/** * 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"); } }