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.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteOrder; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.jnetstream.capture.Capture; import org.jnetstream.capture.CapturePacket; import org.jnetstream.capture.Captures; import org.jnetstream.capture.FileCapture; import org.jnetstream.capture.FileFormatException; import org.jnetstream.capture.FileMode; import org.jnetstream.capture.FilePacket; import org.jnetstream.capture.FormatType; import org.jnetstream.capture.InputCapture; import org.jnetstream.capture.PacketIterator; import org.jnetstream.capture.Captures.LocalFactory; import org.jnetstream.capture.file.pcap.PcapFile; import org.jnetstream.capture.file.snoop.SnoopFile; import org.jnetstream.filter.Filter; import org.jnetstream.packet.Packet; import org.jnetstream.packet.ProtocolFilterTarget; import com.slytechs.file.pcap.PcapFileCapture; import com.slytechs.file.snoop.SnoopFileCapture; /** * @author Mark Bednarczyk * @author Sly Technologies, Inc. */ public abstract class FileFactory implements LocalFactory { private static final Log logger = Captures.logger; public FormatType formatType(final File file) throws IOException { try { new PcapFileCapture(file, FileMode.ReadOnlyNoMap, null).close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", type=" + FormatType.Pcap); } return FormatType.Pcap; } catch (final Exception e) { } try { new SnoopFileCapture(file, FileMode.ReadOnlyNoMap, null).close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", type=" + FormatType.Pcap); } return FormatType.Snoop; } catch (final Exception e) { } /* * Now try InputCapture which may also yield a known format */ ReadableByteChannel channel = new RandomAccessFile(file, "r").getChannel(); FormatType type = formatType(channel); channel.close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", type=" + FormatType.Pcap); } return type; } public FormatType.Detail formatTypeDetail(final File file) throws IOException { try { new PcapFileCapture(file, FileMode.ReadOnlyNoMap, null).close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", type=" + FormatType.Pcap); } return new DefaultFormatTypeDetail(FormatType.Pcap); } catch (final Exception e) { } try { new SnoopFileCapture(file, FileMode.ReadOnlyNoMap, null).close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", type=" + FormatType.Pcap); } return new DefaultFormatTypeDetail(FormatType.Snoop); } catch (final Exception e) { } /* * Now try InputCapture which may also yield a known format */ ReadableByteChannel channel = new RandomAccessFile(file, "r").getChannel(); FormatType.Detail detail = formatTypeDetail(channel); channel.close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", type=" + FormatType.Pcap + ", detail=" + detail); } return detail; } public <T extends FileCapture<? extends FilePacket>> T newFile(final Class<T> c, final File file) throws IOException, FileFormatException { if (c == PcapFile.class) { final FileCapture pcap = PcapFileCapture.createFile(file, FileMode.ReadWrite, ByteOrder.BIG_ENDIAN, null); return c.cast(pcap); } if (c == SnoopFile.class) { final FileCapture snoop = SnoopFileCapture.createFile(file, FileMode.ReadWrite, null); return c.cast(snoop); } else { throw new FileFormatException("Unknown file format " + c.getName()); } } public <T extends FileCapture<? extends FilePacket>> T newFile(final Class<T> type, final File file, final Capture<? extends CapturePacket> capture) throws IOException { if (logger.isDebugEnabled()) { logger.debug(file.getName() + ", type=" + type.getName() + (capture == null ? "" : ", src=" + capture)); } final T dst = newFile(type, file); append(dst, capture); return dst; } public FileCapture<? extends FilePacket> newFile(final FormatType type, final File file) throws IOException { final FileCapture<? extends FilePacket> f; if (type == FormatType.Pcap) { f = PcapFileCapture.createFile(file, FileMode.ReadWrite, ByteOrder.BIG_ENDIAN, null); } else if (type == FormatType.Snoop) { f = SnoopFileCapture.createFile(file, FileMode.ReadWrite, null); } else { throw new IllegalArgumentException("Unknown file format type [" + type + "] specified"); } return f; } @SuppressWarnings("unchecked") public <T extends FileCapture<? extends FilePacket>> T newFile(final FormatType type, final File file, Capture<? extends CapturePacket> capture) throws IOException { if (logger.isDebugEnabled()) { logger.debug(file.getName() + ", type=" + type.getName() + (capture == null ? "" : ", src=" + capture)); } final FileCapture<? extends FilePacket> dst = newFile(type, file); append(dst, capture); return (T) dst; } public <T extends FileCapture<? extends FilePacket>> T openFile(final Class<T> t, final File file) throws IOException, FileFormatException { return openFile(t, file, FileMode.ReadOnly, null); } public <T extends FileCapture<? extends FilePacket>> T openFile(final Class<T> type, final File file, FileMode mode, Filter<ProtocolFilterTarget> filter) throws IOException, FileFormatException { if (logger.isDebugEnabled()) { logger.debug( file.getName() + ", type=" + type.getName() + (filter == null ? "" : ", filter=" + filter)); } FileCapture capture; if (type == PcapFile.class) { capture = new PcapFileCapture(file, mode, null); } else if (type == SnoopFile.class) { capture = new SnoopFileCapture(file, mode, null); } else { throw new FileFormatException("Unsupported file format type, " + type.getName()); } return type.cast(capture); } public FileCapture<? extends FilePacket> openFile(final File file) throws IOException, FileFormatException { return openFile(file, FileMode.ReadOnly, null); } public FileCapture<? extends FilePacket> openFile(final File file, final FileMode mode, final Filter<ProtocolFilterTarget> filter) throws IOException, FileFormatException { if (logger.isDebugEnabled()) { logger.debug(file.getName() + ", mode=" + mode + (filter == null ? "" : ", filter=" + filter)); } final FormatType type = this.formatType(file); FileCapture<? extends FilePacket> capture = null; if (type == null) { return null; } switch (type) { case Pcap: capture = new PcapFileCapture(file, mode, filter); break; case Snoop: capture = new SnoopFileCapture(file, mode, filter); break; case Nap: break; default: return null; } return capture; } public List<File> splitFile(final File file) throws IOException { final long count = countPackets(file); final long size = file.length(); final long megs = size / (1024 * 1024); final long kilos = megs / 1024; if (megs > 1) { long packets = count / megs; return splitFile(file, packets, true); } else if (kilos > 100) { long packets = count / kilos; return splitFile(file, packets, true); } else { return splitFile(file, count, true); } } public List<File> splitFile(final File file, final long packetCount, final boolean maxCompression) throws IOException { final FileCapture<? extends FilePacket> source = openFile(file); final FormatType type = source.getFormatType(); final List<File> files = new ArrayList<File>(100); final List<Packet> packets = new ArrayList<Packet>((int) packetCount); int fileCount = 0; int count = 0; // packet count final PacketIterator<? extends FilePacket> i = source.getPacketIterator(); FileCapture<? extends FilePacket> dst = null; while (i.hasNext()) { if (count % packetCount == 0 && packets.isEmpty() == false) { File f = new File(file.getCanonicalFile() + "-" + fileCount); files.add(f); fileCount++; dst = newFile(type, f); try { PacketIterator<? extends FilePacket> pi = dst.getPacketIterator(); pi.addAll(packets); packets.clear(); } finally { dst.close(); } } final Packet packet = i.next(); packets.add(packet); count++; } /* * Don't forget the remainder */ if (packets.isEmpty() == false) { File f = new File(file.getCanonicalFile() + "-" + fileCount); files.add(f); fileCount++; dst = newFile(type, f); try { PacketIterator<? extends FilePacket> pi = dst.getPacketIterator(); pi.addAll(packets); packets.clear(); } finally { dst.close(); } } source.close(); if (logger.isTraceEnabled()) { logger.trace(file.getName() + ", count=" + packetCount + ", compression=" + maxCompression + ", files=" + files); } return files; } public boolean validateFile(final File file) throws IOException { // TODO Auto-generated method stub return false; } public long countPackets(File dst) throws IOException, FileFormatException { final FormatType type = formatType(dst); if (type == null) { throw new FileFormatException("Unrecognized file format"); } final long count; switch (type) { case Other: final ReadableByteChannel channel = new RandomAccessFile(dst, "r").getChannel(); final InputCapture<? extends CapturePacket> input = newInput(channel, null); count = Captures.count(input.getPacketIterator()); input.close(); break; default: final FileCapture capture = openFile(dst); count = capture.getPacketCount(); capture.close(); break; } return count; } public FileCapture<? extends FilePacket> openFile(File file, FileMode mode) throws FileFormatException, IOException { return openFile(file, mode, null); } }