The second patch of an estimated 4 to complete the COPS message refactoring as descri...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / stack / COPSDecisionMsg.java
1 /*
2  * Copyright (c) 2003 University of Murcia.  All rights reserved.
3  * --------------------------------------------------------------
4  * For more information, please see <http://www.umu.euro6ix.org/>.
5  */
6
7 package org.umu.cops.stack;
8
9 import org.umu.cops.stack.COPSDecision.DecisionFlag;
10 import org.umu.cops.stack.COPSObjHeader.CNum;
11
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.net.Socket;
15 import java.util.Enumeration;
16 import java.util.Hashtable;
17 import java.util.Vector;
18
19 /**
20  * COPS Decision Message
21  *
22  * @version COPSDecisionMsg.java, v 1.00 2003
23  *
24  */
25 public class COPSDecisionMsg extends COPSMsg {
26
27     /* COPSHeader coming from base class */
28     private COPSHandle _clientHandle;
29     private COPSError _error;
30     private Hashtable _decisions;
31     private COPSIntegrity _integrity;
32     private COPSContext _decContext;
33     private COPSClientSI _decSI;
34
35     ///
36     public COPSDecisionMsg() {
37         _clientHandle = null;
38         _error = null;
39         _decisions = new Hashtable(20);
40         _integrity = null;
41         _decContext = null;
42         _decSI = null;
43     }
44
45     /** Checks the sanity of COPS message and throw an
46       * COPSBadDataException when data is bad.
47       */
48     public void checkSanity() throws COPSException {
49         if ((_hdr == null) || (_clientHandle == null) || ( (_error == null) && (_decisions.size() == 0))) {
50             throw new COPSException("Bad message format");
51         }
52     }
53
54     ///
55     protected COPSDecisionMsg(byte[] data) throws COPSException  {
56         _decisions = new Hashtable(20);
57         _clientHandle = null;
58         _error = null;
59         _integrity = null;
60         _decContext = null;
61         _decSI = null;
62
63         parse(data);
64     }
65
66     /**
67      * Parses the data and fills COPSDecisionMsg with its constituents
68      *
69      * @param    data                a  byte[]
70      *
71      * @throws   COPSException
72      *
73      */
74     protected void parse(byte[] data) throws COPSException {
75         super.parseHeader(data);
76
77         while (_dataStart < _dataLength) {
78             byte[] buf = new byte[data.length - _dataStart];
79             System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);
80
81             final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
82             switch (objHdrData.header.getCNum()) {
83                 case HANDLE:
84                     _clientHandle = COPSHandle.parse(objHdrData, buf);
85                     _dataStart += _clientHandle.getDataLength();
86                     break;
87                 case CONTEXT:
88                     //dec context
89                     _decContext = COPSContext.parse(objHdrData, buf);
90                     _dataStart += _decContext.getDataLength();
91                     break;
92                 case ERROR:
93                     _error = COPSError.parse(objHdrData, buf);
94                     _dataStart += _error.getDataLength();
95                     break;
96                 case DEC:
97                     COPSDecision decs = COPSDecision.parse(objHdrData, buf);
98                     _dataStart += decs.getDataLength();
99                     addDecision(decs, _decContext);
100                     break;
101                 case MSG_INTEGRITY:
102                     _integrity = COPSIntegrity.parse(objHdrData, buf);
103                     _dataStart += _integrity.getDataLength();
104                     break;
105                 default: {
106                     throw new COPSException("Bad Message format, unknown object type");
107                 }
108             }
109         }
110         checkSanity();
111     }
112
113     /**
114      * Parses the data and fills that follows the header hdr and fills COPSDecisionMsg
115      *
116      * @param    hdr                 a  COPSHeader
117      * @param    data                a  byte[]
118      *
119      * @throws   COPSException
120      *
121      */
122     protected void parse(COPSHeader hdr, byte[] data) throws COPSException {
123         _hdr = hdr;
124         parse(data);
125         setMsgLength();
126     }
127
128     /**
129      * Add message header
130      *
131      * @param    hdr                 a  COPSHeader
132      *
133      * @throws   COPSException
134      *
135      */
136     public void add (COPSHeader hdr) throws COPSException {
137         if (hdr == null)
138             throw new COPSException ("Null Header");
139         if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC)
140             throw new COPSException ("Error Header (no COPS_OP_DEC)");
141         _hdr = hdr;
142         setMsgLength();
143     }
144
145     /**
146      * Add client handle to the message
147      *
148      * @param    handle              a  COPSHandle
149      *
150      * @throws   COPSException
151      *
152      */
153     public void add (COPSHandle handle) throws COPSException {
154         if (handle == null)
155             throw new COPSException ("Null Handle");
156         _clientHandle = handle;
157         setMsgLength();
158     }
159
160     /**
161      * Add an Error object
162      *
163      * @param    error               a  COPSError
164      *
165      * @throws   COPSException
166      *
167      */
168     public void add (COPSError error) throws COPSException {
169         if (_decisions.size() != 0)
170             throw new COPSException ("No null decisions");
171         if (_error != null)
172             throw new COPSException ("No null error");
173         //Message integrity object should be the very last one
174         //If it is already added
175         if (_integrity != null)
176             throw new COPSException ("No null integrity");
177         _error = error;
178         setMsgLength();
179     }
180
181     /**
182      * Add one or more local decision object for a given decision context
183      * the context is optional, if null all decision object are tided to
184      * message context
185      *
186      * @param    decision            a  COPSDecision
187      * @param    context             a  COPSContext
188      *
189      * @throws   COPSException
190      *
191      */
192     public void addDecision(COPSDecision decision, COPSContext context)  throws COPSException {
193         //Either error or decision can be added
194         //If error is aleady there assert
195         if (_error != null)
196             throw new COPSException ("No null error");
197
198         if (decision.getHeader().getCNum().equals(CNum.LPDP_DEC))
199             throw new COPSException ("Is local decision");
200
201         Vector v = (Vector) _decisions.get(context);
202         if (v == null) v = new Vector();
203
204         if (!decision.getFlag().equals(DecisionFlag.NA)) {//Commented out as advised by Felix
205             //if (v.size() != 0)
206             //{
207             //Only one set of decision flags is allowed
208             //for each context
209             //     throw new COPSException ("Bad Message format, only one set of decision flags is allowed.");
210             //}
211         } else {
212             if (v.size() == 0) {
213                 //The flags decision must precede any other
214                 //decision message, since the decision is not
215                 //flags throw exception
216                 throw new COPSException ("Bad Message format, flags decision must precede any other decision object.");
217             }
218         }
219         v.add(decision);
220         _decisions.put(context,v);
221
222         setMsgLength();
223     }
224
225     /**
226      * Add integrity object
227      *
228      * @param    integrity           a  COPSIntegrity
229      *
230      * @throws   COPSException
231      *
232      */
233     public void add (COPSIntegrity integrity)  throws COPSException {
234         if (integrity == null)
235             throw new COPSException ("Null Integrity");
236         _integrity = integrity;
237         setMsgLength();
238     }
239     /**
240      * Add clientSI object
241      *
242      * @param    clientSI           a  COPSClientSI
243      *
244      * @throws   COPSException
245      *
246      */
247     public void add (COPSClientSI clientSI)  throws COPSException {
248         if (clientSI == null)
249             throw new COPSException ("Null clientSI");
250         /*
251                   if (!integrity.isMessageIntegrity())
252                        throw new COPSException ("Error Integrity");
253         */
254         _decSI = clientSI;
255         setMsgLength();
256     }
257
258     /**
259      * Writes data to given socket
260      *
261      * @param    id                  a  Socket
262      *
263      * @throws   IOException
264      *
265      */
266     public void writeData(Socket id) throws IOException {
267         // checkSanity();
268         if (_hdr != null) _hdr.writeData(id);
269         if (_clientHandle != null) _clientHandle.writeData(id);
270         if (_error != null) _error.writeData(id);
271
272         //Display decisions
273         //Display any local decisions
274         for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {
275
276             COPSContext context = (COPSContext) e.nextElement();
277             Vector v = (Vector) _decisions.get(context);
278             context.writeData(id);
279
280             for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {
281                 COPSDecision decision = (COPSDecision) ee.nextElement();
282                 decision.writeData(id);
283             }
284         }
285
286         if (_decSI != null) _decSI.writeData(id);
287         if (_integrity != null) _integrity.writeData(id);
288     }
289
290     /**
291      * Method getHeader
292      *
293      * @return   a COPSHeader
294      *
295      */
296     public COPSHeader getHeader() {
297         return _hdr;
298     }
299
300     /**
301      * Method getClientHandle
302      *
303      * @return   a COPSHandle
304      *
305      */
306     public COPSHandle getClientHandle() {
307         return _clientHandle;
308     }
309
310     /**
311      * Returns true if it has error object
312      *
313      * @return   a boolean
314      *
315      */
316     public boolean hasError() {
317         return (_error != null);
318     }
319
320     /**
321      * Should check hasError() before calling
322      *
323      * @return   a COPSError
324      *
325      */
326     public COPSError getError() {
327         return _error;
328     }
329
330     /**
331      * Returns a map of decision for which is an arry of context and vector
332      * of associated decision object.
333      *
334      * @return   a Hashtable
335      *
336      */
337     public Hashtable getDecisions() {
338         return _decisions;
339     }
340
341     /**
342      * Returns true if it has integrity object
343      *
344      * @return   a boolean
345      *
346      */
347     public boolean hasIntegrity() {
348         return (_integrity != null);
349     }
350
351     /**
352      * Should check hasIntegrity() before calling
353      *
354      * @return   a COPSIntegrity
355      *
356      */
357     public COPSIntegrity getIntegrity() {
358         return _integrity;
359     }
360
361     /**
362      * Method setMsgLength
363      *
364      * @throws   COPSException
365      *
366      */
367     protected void setMsgLength()  throws COPSException {
368         short len = 0;
369         if (_clientHandle != null)
370             len += _clientHandle.getDataLength();
371         if (_error != null)
372             len += _error.getDataLength();
373
374         //Display any local decisions
375         for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {
376
377             COPSContext context = (COPSContext) e.nextElement();
378             Vector v = (Vector) _decisions.get(context);
379             len += context.getDataLength();
380
381             for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {
382                 COPSDecision decision = (COPSDecision) ee.nextElement();
383                 len += decision.getDataLength();
384             }
385         }
386         if (_decSI != null) {
387             len += _decSI.getDataLength();
388         }
389         if (_integrity != null) {
390             len += _integrity.getDataLength();
391         }
392
393         _hdr.setMsgLength((int) len);
394     }
395
396     /**
397      * Write an object textual description in the output stream
398      *
399      * @param    os                  an OutputStream
400      *
401      * @throws   IOException
402      *
403      */
404     public void dump(OutputStream os) throws IOException {
405         _hdr.dump(os);
406
407         if (_clientHandle != null)
408             _clientHandle.dump(os);
409         if (_error != null)
410             _error.dump(os);
411
412         //Display any local decisions
413         for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {
414
415             COPSContext context = (COPSContext) e.nextElement();
416             Vector v = (Vector) _decisions.get(context);
417             context.dump(os);
418
419             for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {
420                 COPSDecision decision = (COPSDecision) ee.nextElement();
421                 decision.dump(os);
422             }
423         }
424         if (_decSI != null) {
425             _decSI.dump(os);
426         }
427         if (_integrity != null) {
428             _integrity.dump(os);
429         }
430     }
431 }
432
433
434