/* * Copyright (c) 2003 University of Murcia. All rights reserved. * -------------------------------------------------------------- * For more information, please see . */ package org.umu.cops.stack; import org.umu.cops.stack.COPSDecision.DecisionFlag; import org.umu.cops.stack.COPSObjHeader.CNum; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; /** * COPS Decision Message * * @version COPSDecisionMsg.java, v 1.00 2003 * */ public class COPSDecisionMsg extends COPSMsg { /* COPSHeader coming from base class */ private COPSHandle _clientHandle; private COPSError _error; private Hashtable _decisions; private COPSIntegrity _integrity; private COPSContext _decContext; private COPSClientSI _decSI; /// public COPSDecisionMsg() { _clientHandle = null; _error = null; _decisions = new Hashtable(20); _integrity = null; _decContext = null; _decSI = null; } /** Checks the sanity of COPS message and throw an * COPSBadDataException when data is bad. */ public void checkSanity() throws COPSException { if ((_hdr == null) || (_clientHandle == null) || ( (_error == null) && (_decisions.size() == 0))) { throw new COPSException("Bad message format"); } } /// protected COPSDecisionMsg(byte[] data) throws COPSException { _decisions = new Hashtable(20); _clientHandle = null; _error = null; _integrity = null; _decContext = null; _decSI = null; parse(data); } /** * Parses the data and fills COPSDecisionMsg with its constituents * * @param data a byte[] * * @throws COPSException * */ protected void parse(byte[] data) throws COPSException { super.parseHeader(data); while (_dataStart < _dataLength) { byte[] buf = new byte[data.length - _dataStart]; System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart); final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf); switch (objHdrData.header.getCNum()) { case HANDLE: _clientHandle = COPSHandle.parse(objHdrData, buf); _dataStart += _clientHandle.getDataLength(); break; case CONTEXT: //dec context _decContext = COPSContext.parse(objHdrData, buf); _dataStart += _decContext.getDataLength(); break; case ERROR: _error = COPSError.parse(objHdrData, buf); _dataStart += _error.getDataLength(); break; case DEC: COPSDecision decs = COPSDecision.parse(objHdrData, buf); _dataStart += decs.getDataLength(); addDecision(decs, _decContext); break; case MSG_INTEGRITY: _integrity = COPSIntegrity.parse(objHdrData, buf); _dataStart += _integrity.getDataLength(); break; default: { throw new COPSException("Bad Message format, unknown object type"); } } } checkSanity(); } /** * Parses the data and fills that follows the header hdr and fills COPSDecisionMsg * * @param hdr a COPSHeader * @param data a byte[] * * @throws COPSException * */ protected void parse(COPSHeader hdr, byte[] data) throws COPSException { _hdr = hdr; parse(data); setMsgLength(); } /** * Add message header * * @param hdr a COPSHeader * * @throws COPSException * */ public void add (COPSHeader hdr) throws COPSException { if (hdr == null) throw new COPSException ("Null Header"); if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC) throw new COPSException ("Error Header (no COPS_OP_DEC)"); _hdr = hdr; setMsgLength(); } /** * Add client handle to the message * * @param handle a COPSHandle * * @throws COPSException * */ public void add (COPSHandle handle) throws COPSException { if (handle == null) throw new COPSException ("Null Handle"); _clientHandle = handle; setMsgLength(); } /** * Add an Error object * * @param error a COPSError * * @throws COPSException * */ public void add (COPSError error) throws COPSException { if (_decisions.size() != 0) throw new COPSException ("No null decisions"); if (_error != null) throw new COPSException ("No null error"); //Message integrity object should be the very last one //If it is already added if (_integrity != null) throw new COPSException ("No null integrity"); _error = error; setMsgLength(); } /** * Add one or more local decision object for a given decision context * the context is optional, if null all decision object are tided to * message context * * @param decision a COPSDecision * @param context a COPSContext * * @throws COPSException * */ public void addDecision(COPSDecision decision, COPSContext context) throws COPSException { //Either error or decision can be added //If error is aleady there assert if (_error != null) throw new COPSException ("No null error"); if (decision.getHeader().getCNum().equals(CNum.LPDP_DEC)) throw new COPSException ("Is local decision"); Vector v = (Vector) _decisions.get(context); if (v == null) v = new Vector(); if (!decision.getFlag().equals(DecisionFlag.NA)) {//Commented out as advised by Felix //if (v.size() != 0) //{ //Only one set of decision flags is allowed //for each context // throw new COPSException ("Bad Message format, only one set of decision flags is allowed."); //} } else { if (v.size() == 0) { //The flags decision must precede any other //decision message, since the decision is not //flags throw exception throw new COPSException ("Bad Message format, flags decision must precede any other decision object."); } } v.add(decision); _decisions.put(context,v); setMsgLength(); } /** * Add integrity object * * @param integrity a COPSIntegrity * * @throws COPSException * */ public void add (COPSIntegrity integrity) throws COPSException { if (integrity == null) throw new COPSException ("Null Integrity"); _integrity = integrity; setMsgLength(); } /** * Add clientSI object * * @param clientSI a COPSClientSI * * @throws COPSException * */ public void add (COPSClientSI clientSI) throws COPSException { if (clientSI == null) throw new COPSException ("Null clientSI"); /* if (!integrity.isMessageIntegrity()) throw new COPSException ("Error Integrity"); */ _decSI = clientSI; setMsgLength(); } /** * Writes data to given socket * * @param id a Socket * * @throws IOException * */ public void writeData(Socket id) throws IOException { // checkSanity(); if (_hdr != null) _hdr.writeData(id); if (_clientHandle != null) _clientHandle.writeData(id); if (_error != null) _error.writeData(id); //Display decisions //Display any local decisions for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) { COPSContext context = (COPSContext) e.nextElement(); Vector v = (Vector) _decisions.get(context); context.writeData(id); for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) { COPSDecision decision = (COPSDecision) ee.nextElement(); decision.writeData(id); } } if (_decSI != null) _decSI.writeData(id); if (_integrity != null) _integrity.writeData(id); } /** * Method getHeader * * @return a COPSHeader * */ public COPSHeader getHeader() { return _hdr; } /** * Method getClientHandle * * @return a COPSHandle * */ public COPSHandle getClientHandle() { return _clientHandle; } /** * Returns true if it has error object * * @return a boolean * */ public boolean hasError() { return (_error != null); } /** * Should check hasError() before calling * * @return a COPSError * */ public COPSError getError() { return _error; } /** * Returns a map of decision for which is an arry of context and vector * of associated decision object. * * @return a Hashtable * */ public Hashtable getDecisions() { return _decisions; } /** * Returns true if it has integrity object * * @return a boolean * */ public boolean hasIntegrity() { return (_integrity != null); } /** * Should check hasIntegrity() before calling * * @return a COPSIntegrity * */ public COPSIntegrity getIntegrity() { return _integrity; } /** * Method setMsgLength * * @throws COPSException * */ protected void setMsgLength() throws COPSException { short len = 0; if (_clientHandle != null) len += _clientHandle.getDataLength(); if (_error != null) len += _error.getDataLength(); //Display any local decisions for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) { COPSContext context = (COPSContext) e.nextElement(); Vector v = (Vector) _decisions.get(context); len += context.getDataLength(); for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) { COPSDecision decision = (COPSDecision) ee.nextElement(); len += decision.getDataLength(); } } if (_decSI != null) { len += _decSI.getDataLength(); } if (_integrity != null) { len += _integrity.getDataLength(); } _hdr.setMsgLength((int) len); } /** * Write an object textual description in the output stream * * @param os an OutputStream * * @throws IOException * */ public void dump(OutputStream os) throws IOException { _hdr.dump(os); if (_clientHandle != null) _clientHandle.dump(os); if (_error != null) _error.dump(os); //Display any local decisions for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) { COPSContext context = (COPSContext) e.nextElement(); Vector v = (Vector) _decisions.get(context); context.dump(os); for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) { COPSDecision decision = (COPSDecision) ee.nextElement(); decision.dump(os); } } if (_decSI != null) { _decSI.dump(os); } if (_integrity != null) { _integrity.dump(os); } } }