All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.nps.moves.disutil.ConcatenatedDisPdus Maven / Gradle / Ivy

Go to download

An open source implementation of the Distributed Interactive Simulation (DIS) IEEE-1278 protocol

There is a newer version: 5.8
Show newest version


package edu.nps.moves.disutil;

import java.io.*;
import java.nio.*;
import java.util.*;
import javax.xml.bind.*;

import edu.nps.moves.dis.*;

/**
 * Reads concatenated PDUs, not necessarily of the same type or the same
 * length, from a binary file. The assumption is that the PDUs were placed
 * in IEEE format, concatenated one after the other, into the file. 

* * It's not uncommonn to place serveral PDUs in a single datagram packet, * since placing one in each datagram can cause a very heavy network load. * This class is useful for extracting the PDUs from that one big byte array. * It's also not uncommon to see people simply write out * IEEE PDUs in a file, one after the other. It's a useful format, but then * you need to read it back, which is what this does.

* * This also includes an "index" method that returns a big array with the * input stream pointer position of the start of each PDU. This is useful * for indexing into the input stream for semi-random access to PDUs * in the stream.

* * This class is too profliigate with memory and should be rewritten to take * advantage of some NIO classes. * * @author DMcG */ public class ConcatenatedDisPdus { private InputStream is; private PduFactory pduFactory; public ConcatenatedDisPdus(InputStream is) { this.is = is; pduFactory = new PduFactory(); } /** * Ugh--this is memory inefficient and should be rewritten so that the * PDU factory can simply take an input stream. This can probably be * done via the MappedByteBuffer in nio.

* * Note that this will fail horribly if the length field is wrong, or if * any one of the length fields before this was wrong.

* * This depends on the input stream being open and not reset through multiple calls * to getNextPdu(). */ public Pdu getNextPdu() { try { byte[] initialBytes = new byte[10]; is.read(initialBytes); short pduLength = 0; // The length field is a short at index 8 and 9. We need to mask // in order to remove any sign bits. int ch1 = initialBytes[8] & 0x000000ff; int ch2 = initialBytes[9] & 0x000000ff; pduLength = (short)((ch1 << 8) + (ch2 << 0)); //System.out.println("PduLength=" + pduLength); // We know how long the array to hold a single PDU is; now we // can create that array byte[] fullArray = new byte[pduLength]; // Copy in the starting bytes (which we've already read) and the // rest of the bytes for this PDU, which we have not. System.arraycopy(initialBytes, 0, fullArray, 0, 10); is.read(fullArray, 10, pduLength - 10); // And create a PDU from that ByteBuffer bbuf = ByteBuffer.wrap(fullArray); return pduFactory.createPdu(bbuf); } catch(Exception e) { System.out.println(e); } return null; } /** * Returns all the PDUs in the concatenated PDU input stream, starting * with the current file position.

* * @return a PduContainer with all the pdus remainig in the input stream */ public PduContainer getAllPdusInPduContainer() { List pdus = this.getAllPdus(); PduContainer container = new PduContainer(); container.setPdus(pdus); return container; } /** * Returns a List of all the PDUs remaining in the input stream * * @return List of all the PDUs remaining */ public List getAllPdus() { Pdu aPdu; List pdus = new ArrayList(); while((aPdu = this.getNextPdu()) != null) { pdus.add(aPdu); } return pdus; } /** * Returns an array of all the index positions in the input stream that * are the starting points for each PDU. Once this has been done, if * you want to read PDUs at the indexes, you should close the input * stream and re-open it so that the position pointer is at zero. Or, * if the stream supports it, reset the pointer position to zero. * * @return array of ints, each entry the starting point (in bytes) of * a PDU */ public int[] getIndexes() { List indexes = new ArrayList(); int currentPos = 0; indexes.add(new Integer(currentPos)); try { while(true) // loop ends via thrown exception (EOF) or finding a PDU length of zero or less { byte[] initialBytes = new byte[10]; is.read(initialBytes); short pduLength = 0; int ch1 = initialBytes[8] & 0x000000ff; int ch2 = initialBytes[9] & 0x000000ff; pduLength = (short)((ch1 << 8) + (ch2 << 0)); //System.out.println("PDU length in index is " + pduLength); if(pduLength <= 0) { break; } currentPos = currentPos + pduLength; indexes.add(new Integer(currentPos)); is.skip(pduLength - 10); } } catch(Exception e) { System.out.println("end of input"); } // Convert the list to an array. We may be able to get rid of a lot of // this with autoboxing, but that's 1.6 specific (I think.) int[] buf = new int[indexes.size()]; for(int idx = 0; idx < indexes.size(); idx++) { buf[idx] = indexes.get(idx).intValue(); } return buf; } /** * Useful for some testing, maybe some example code * @param args */ public static void main(String args[]) { try { FileInputStream fis = new FileInputStream(args[0]); ConcatenatedDisPdus concat = new ConcatenatedDisPdus(fis); PduContainer container = concat.getAllPdusInPduContainer(); System.out.println("got back " + container.getNumberOfPdus()); JAXBContext context = JAXBContext.newInstance("edu.nps.moves.dis"); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(container, new FileOutputStream("someWorkbenchPdus.xml")); fis.close(); fis = new FileInputStream(args[0]); concat = new ConcatenatedDisPdus(fis); concat.getIndexes(); } catch(Exception e) { System.out.println(e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy