KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > agent > mo > snmp > RowStatus


1 /*_############################################################################
2   _##
3   _## SNMP4J-Agent - RowStatus.java
4   _##
5   _## Copyright (C) 2005-2007 Frank Fock (SNMP4J.org)
6   _##
7   _## Licensed under the Apache License, Version 2.0 (the "License");
8   _## you may not use this file except in compliance with the License.
9   _## You may obtain a copy of the License at
10   _##
11   _## http://www.apache.org/licenses/LICENSE-2.0
12   _##
13   _## Unless required by applicable law or agreed to in writing, software
14   _## distributed under the License is distributed on an "AS IS" BASIS,
15   _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   _## See the License for the specific language governing permissions and
17   _## limitations under the License.
18   _##
19   _##########################################################################*/

20
21
22 package org.snmp4j.agent.mo.snmp;
23
24 import java.util.*;
25
26 import org.snmp4j.*;
27 import org.snmp4j.agent.*;
28 import org.snmp4j.agent.mo.*;
29 import org.snmp4j.agent.request.*;
30 import org.snmp4j.smi.*;
31 import org.snmp4j.log.LogAdapter;
32 import org.snmp4j.log.LogFactory;
33
34 /**
35  * The <code>RowStatus</code> class implements the columnar object TC RowStatus.
36  * The RowStatus textual convention is used to manage the creation and deletion
37  * of conceptual rows, and is used as the value of the SYNTAX clause for the
38  * status column of a conceptual row. See RFC 2579.
39  *
40  * The RowStatus column controls row creation and deletion in SNMP tables with
41  * READ-CREATE maximum access. Since the state of a dynamic row is/may be
42  * important to dependent rows / other objects of an agent, row status change
43  * events can be propagated to other objects through registering
44  * {@link RowStatusListener}s.
45  *
46  * @author Frank Fock
47  * @version 1.0
48  */

49 public class RowStatus extends MOMutableColumn implements MOChangeListener,
50     MOTableRowListener
51 {
52
53   private static final LogAdapter logger =
54       LogFactory.getLogger(RowStatus.class);
55
56   public static final int notExistant = 0;
57   public static final int active = 1;
58   public static final int notInService = 2;
59   public static final int notReady = 3;
60   public static final int createAndGo = 4;
61   public static final int createAndWait = 5;
62   public static final int destroy = 6;
63
64   private OID oid;
65   private int columnIndex;
66
67   private transient Vector rowStatusListeners;
68
69   /**
70    * Creates a RowStatus column with the specified column sub-identifier and
71    * maximum access of 'read-create'.
72    * @param columnID
73    * a column sub-identifier.
74    */

75   public RowStatus(int columnID) {
76     super(columnID, SMIConstants.SYNTAX_INTEGER,
77           MOAccessImpl.ACCESS_READ_CREATE);
78     this.addMOValueValidationListener(new RowStatusValidator());
79   }
80
81   /**
82    * Creates a RowStatus column with the specified column sub-identifier.
83    * @param columnID
84    * a column sub-identifier.
85    * @param access
86    * the maximum access for the RowStatus column (should be READ-CREATE).
87    */

88   public RowStatus(int columnID, MOAccess access) {
89     super(columnID, SMIConstants.SYNTAX_INTEGER, access);
90     this.addMOValueValidationListener(new RowStatusValidator());
91   }
92
93   /**
94    * Sets the table instance this columnar object is contained in. This method
95    * should be called by {@link MOTable} instance to register the table with
96    * the RowStatus column. When called, this RowStatus registers itself as
97    * {@link MOChangeListener} and {@link MOTableRowListener}.
98    * @param table
99    * the <code>MOTable</code> instance where this column is contained in.
100    */

101   public void setTable(MOTable table) {
102     super.setTable(table);
103     oid = new OID(table.getOID());
104     oid.append(getColumnID());
105     columnIndex = table.getColumnIndex(getColumnID());
106
107     table.addMOChangeListener(this);
108     table.addMOTableRowListener(this);
109   }
110
111   /**
112    * Unsets the table instance and thus unregisters itself as
113    * {@link MOChangeListener} and {@link MOTableRowListener}.
114    * @param table
115    * the <code>MOTable</code> instance where this column was part of.
116    */

117   public void unsetTable(MOTable table) {
118     columnIndex = 0;
119     table.removeMOChangeListener(this);
120     table.removeMOTableRowListener(this);
121   }
122
123   protected boolean isReady(MOTableRow row, int rowStatusColumn) {
124     return isReady(row, rowStatusColumn, null);
125   }
126
127   protected boolean isReady(MOTableRow row, int rowStatusColumn,
128                             MOTableRow changeSet) {
129     MOColumn[] columns = getTable().getColumns();
130     for (int i=0; i<columns.length; i++) {
131       if (i == rowStatusColumn) {
132         continue;
133       }
134       if (columns[i] instanceof MOMutableColumn) {
135         MOMutableColumn mcol = (MOMutableColumn) columns[i];
136         if ((mcol.isMandatory()) &&
137             ((row.getValue(i) == null) &&
138              ((changeSet == null) || (changeSet.getValue(i) == null)))) {
139           if (logger.isDebugEnabled()) {
140             logger.debug("Row "+row+" is not ready because column "+i+
141                          " is not set properly");
142           }
143           return false;
144         }
145       }
146     }
147     return true;
148   }
149
150   public void prepare(SubRequest subRequest, MOTableRow row,
151                       MOTableRow changeSet, int column) {
152     super.prepare(subRequest, row, null, column);
153     if (subRequest.getStatus().getErrorStatus() == PDU.noError) {
154       int newValue =
155           ((Integer32)subRequest.getVariableBinding().getVariable()).getValue();
156       int oldValue = notExistant;
157       if (row.getValue(column) != null) {
158         oldValue = ((Integer32) row.getValue(column)).getValue();
159       }
160       if ((oldValue == notExistant) || (oldValue == notReady) ||
161           (oldValue == createAndGo)) {
162         switch (newValue) {
163           case createAndGo:
164           case notInService:
165           case active: {
166             if (!isReady(row, column, changeSet)) {
167               if (logger.isDebugEnabled()) {
168                 logger.debug(toString()+": Row '"+
169                              row.getIndex() +
170                              " is not ready! Cannot change status to from "+
171                              oldValue+" to "+newValue);
172               }
173               subRequest.getStatus().setErrorStatus(PDU.inconsistentValue);
174             }
175             break;
176           }
177         }
178       }
179       RowStatusEvent rowStatusEvent =
180           new RowStatusEvent(this, getTable(), row, changeSet,
181                              oldValue, newValue, true);
182       fireRowStatusChanged(rowStatusEvent);
183       if (rowStatusEvent.getDenyReason() != PDU.noError) {
184         subRequest.getStatus().setErrorStatus(rowStatusEvent.getDenyReason());
185       }
186     }
187   }
188
189   public void commit(SubRequest subRequest, MOTableRow row,
190                      MOTableRow changeSet, int column) {
191     int oldValue = ((Integer32)row.getValue(column)).getValue();
192     super.commit(subRequest, row, null, column);
193     if (!subRequest.hasError()) {
194       int newValue = ((Integer32)row.getValue(column)).getValue();
195       assignNewValue(subRequest, row, column, newValue);
196       RowStatusEvent rowStatusEvent =
197           new RowStatusEvent(this, getTable(), row, changeSet,
198                              oldValue, newValue);
199       fireRowStatusChanged(rowStatusEvent);
200     }
201   }
202
203   protected void assignNewValue(SubRequest subRequest,
204                                 MOTableRow row, int column,
205                                 int newValue) {
206     switch (newValue) {
207       case destroy: {
208         MOTableRow deleted = getTable().removeRow(row.getIndex());
209         if (deleted == null) {
210           subRequest.getStatus().setErrorStatus(PDU.commitFailed);
211         }
212         else {
213           subRequest.setUndoValue(deleted);
214         }
215         break;
216       }
217       case createAndWait: {
218         if (isReady(row, column)) {
219           ((Integer32)row.getValue(column)).setValue(RowStatus.notInService);
220         }
221         else {
222           ((Integer32) row.getValue(column)).setValue(RowStatus.notReady);
223         }
224         break;
225       }
226       case createAndGo: {
227         ((Integer32)row.getValue(column)).setValue(RowStatus.active);
228         break;
229       }
230     }
231   }
232
233   public void undo(SubRequest subRequest, MOTableRow row, int column) {
234     super.undo(subRequest, row, column);
235     if (!subRequest.hasError()) {
236       int newStatus = ((Integer32)row.getValue(column)).getValue();
237       switch (newStatus) {
238         case destroy: {
239           MOTableRow oldRow = (MOTableRow)subRequest.getUndoValue();
240           Integer32 oldValue = (Integer32) oldRow.getValue(column);
241           boolean added =
242               getTable().addRow((MOTableRow)subRequest.getUndoValue());
243           if (!added) {
244             subRequest.getStatus().setErrorStatus(PDU.undoFailed);
245           }
246           else {
247             RowStatusEvent rowStatusEvent =
248                 new RowStatusEvent(this, getTable(), oldRow, row,
249                                    oldValue.getValue(), RowStatus.destroy);
250             fireRowStatusChanged(rowStatusEvent);
251           }
252           break;
253         }
254         case createAndGo:
255         case createAndWait: {
256           MOTableRow deleted = getTable().removeRow(row.getIndex());
257           if (deleted == null) {
258             subRequest.getStatus().setErrorStatus(PDU.undoFailed);
259           }
260           else {
261             RowStatusEvent rowStatusEvent =
262                 new RowStatusEvent(this, getTable(), row, deleted,
263                                    RowStatus.notExistant, newStatus);
264             fireRowStatusChanged(rowStatusEvent);
265           }
266           break;
267         }
268       }
269     }
270   }
271
272   public void beforePrepareMOChange(MOChangeEvent changeEvent) {
273     if (changeEvent.getOID().startsWith(oid)) {
274       int currentValue = notExistant;
275       if (changeEvent.getOldValue() instanceof Integer32) {
276         currentValue = ((Integer32) changeEvent.getOldValue()).getValue();
277       }
278       int newValue = ((Integer32) changeEvent.getNewValue()).getValue();
279       boolean ok = false;
280       switch (currentValue) {
281         case notExistant:
282           ok = ((newValue == createAndGo) ||
283                 (newValue == createAndWait) || (newValue == destroy));
284           break;
285         case notReady:
286           ok = ((newValue == destroy) || (newValue == active) ||
287                 (newValue == notInService));
288           break;
289         case active:
290           ok = ((newValue == active) ||
291                 (newValue == notInService) || (newValue == destroy));
292           break;
293         case notInService:
294           ok = ((newValue == notInService) ||
295                 (newValue == active) || (newValue == destroy));
296           break;
297         // for row creation
298
case createAndWait:
299           ok = (newValue == createAndWait);
300           break;
301         case createAndGo:
302           ok = (newValue == createAndGo);
303           break;
304         case destroy:
305           ok = (newValue == destroy);
306           break;
307       }
308       if (!ok) {
309         changeEvent.setDenyReason(PDU.wrongValue);
310       }
311     }
312   }
313
314   public void beforeMOChange(MOChangeEvent changeEvent) {
315   }
316
317   public void afterMOChange(MOChangeEvent changeEvent) {
318   }
319
320   public void afterPrepareMOChange(MOChangeEvent changeEvent) {
321   }
322
323   public synchronized void addRowStatusListener(RowStatusListener l) {
324     if (rowStatusListeners == null) {
325       rowStatusListeners = new Vector(2);
326     }
327     rowStatusListeners.add(l);
328   }
329
330   public synchronized void removeRowStatusListener(RowStatusListener l) {
331     if (rowStatusListeners != null) {
332       rowStatusListeners.remove(l);
333     }
334   }
335
336   protected void fireRowStatusChanged(RowStatusEvent event) {
337     if (rowStatusListeners != null) {
338       Vector listeners = rowStatusListeners;
339       int count = listeners.size();
340       for (int i = 0; i < count; i++) {
341         ((RowStatusListener) listeners.elementAt(i)).rowStatusChanged(event);
342       }
343     }
344   }
345
346   /**
347    * Tests if the specified row is active.
348    * @param row
349    * a row with a RowStatus column.
350    * @param rowStatusColumnIndex
351    * the column index of the RowStatus column in <code>row</code>.
352    * @return
353    * <code>true</code> if <code>row</code> is active.
354    */

355   public static boolean isRowActive(MOTableRow row, int rowStatusColumnIndex) {
356     Integer32 rowStatus = (Integer32) row.getValue(rowStatusColumnIndex);
357     if (rowStatus != null) {
358       return rowStatus.getValue() == RowStatus.active;
359     }
360     return false;
361   }
362
363   /**
364    * The <code>ActiveRowsFilter</code> is a {@link MOTableRowFilter} that
365    * returns only the active rows of a table with a RowStatus column.
366    *
367    * @author Frank Fock
368    * @version 1.0
369    */

370   public static class ActiveRowsFilter implements MOTableRowFilter {
371
372     private int rowStatusColumnIndex;
373
374     /**
375      * Creates an active row filter by specifying the RowStatus column's index
376      * in the target table.
377      * @param rowStatusColumnIndex
378      * the column index (zero-based) of the RowStatus column on behalf the
379      * filtering is done.
380      */

381     public ActiveRowsFilter(int rowStatusColumnIndex) {
382       this.rowStatusColumnIndex = rowStatusColumnIndex;
383     }
384
385     public boolean passesFilter(MOTableRow row) {
386       return (((Integer32)
387                row.getValue(rowStatusColumnIndex)).getValue() == active);
388     }
389   }
390
391   static class RowStatusValidator implements MOValueValidationListener {
392
393     public void validate(MOValueValidationEvent event) {
394       if (!(event.getNewValue() instanceof Integer32)) {
395         event.setValidationStatus(PDU.wrongType);
396       }
397       int v = ((Integer32)event.getNewValue()).getValue();
398       if ((v < 1) || (v > 6) || (v == 3)) {
399         event.setValidationStatus(PDU.wrongValue);
400       }
401     }
402   }
403
404   public void rowChanged(MOTableRowEvent event) {
405     switch (event.getType()) {
406       case MOTableRowEvent.CREATE: {
407         // by default do not allow row creation if RowStatus is not set!
408
MOTableRow row = event.getRow();
409         int myIndex = getTable().getColumnIndex(getColumnID());
410         if (row.getValue(myIndex) == null) {
411           event.setVetoStatus(PDU.inconsistentName);
412         }
413         break;
414       }
415       case MOTableRowEvent.CHANGE: {
416         // check whether the changed column can be changed if row is active
417
int rowStatus = getCurrentRowStatus(event);
418         switch (rowStatus) {
419           case active: {
420             for (int i=0; i<getTable().getColumnCount(); i++) {
421               if (event.getPreparedChanges().getValue(i) == null) {
422                 continue;
423               }
424               MOColumn col = getTable().getColumn(i);
425               if (col instanceof MOMutableColumn) {
426                 if (!((MOMutableColumn) col).isMutableInService()) {
427                   event.setVetoStatus(PDU.inconsistentValue);
428                   event.setVetoColumn(i);
429                 }
430               }
431             }
432             break;
433           }
434         }
435       }
436       case MOTableRowEvent.UPDATED: {
437         // check whether changed row is ready to be set active
438
int rowStatus = getCurrentRowStatus(event);
439         switch (rowStatus) {
440           case notReady: {
441             if ((event.getRow() instanceof MOMutableTableRow) &&
442                 (isReady(event.getRow(), columnIndex))) {
443               ((MOMutableTableRow) event.getRow()).setValue(columnIndex,
444                   new Integer32(notInService));
445             }
446             break;
447           }
448         }
449       }
450     }
451   }
452
453   private int getCurrentRowStatus(MOTableRowEvent event) {
454     Integer32 rowStatusVariable =
455         (Integer32)event.getRow().getValue(columnIndex);
456     int rowStatus = RowStatus.notExistant;
457     if (rowStatusVariable != null) {
458       rowStatus = rowStatusVariable.getValue();
459     }
460     return rowStatus;
461   }
462
463   public boolean isVolatile(MOTableRow row, int column) {
464     Integer32 value = (Integer32) row.getValue(column);
465     if (value != null) {
466       int rowStatus = value.getValue();
467       if ((rowStatus != active) && (rowStatus != notInService)) {
468         return true;
469       }
470     }
471     return false;
472   }
473
474   public void get(SubRequest subRequest, MOTableRow row, int column) {
475     Integer32 rowStatus = (Integer32) getValue(row, column);
476     if ((rowStatus != null) && (rowStatus.getValue() == notReady)) {
477       if (isReady(row, column)) {
478         rowStatus.setValue(notInService);
479       }
480     }
481     super.get(subRequest, row, column);
482   }
483
484 }
485
Popular Tags