1 20 21 22 package org.snmp4j.agent.mo.snmp; 23 24 import java.util.*; 25 26 import org.snmp4j.log.*; 27 import org.snmp4j.agent.*; 28 import org.snmp4j.agent.mo.*; 29 import org.snmp4j.agent.mo.util.*; 30 import org.snmp4j.agent.security.*; 31 import org.snmp4j.security.*; 32 import org.snmp4j.smi.*; 33 34 43 public class VacmMIB implements MOGroup, MutableVACM { 44 45 private static final LogAdapter logger = LogFactory.getLogger(VacmMIB.class); 46 47 private static final OID vacmContextEntryOID = 48 new OID(new int[] {1,3,6,1,6,3,16,1,1,1}); 49 50 private static final int colVacmGroupName = 3; 51 private static final int colVacmSecurityToGroupStorageType = 4; 52 private static final int colVacmSecurityToGroupRowStatus = 5; 53 54 private static final int idxVacmGroupName = 0; 55 private static final int idxVacmSecurityToGroupStorageType = 1; 56 private static final int idxVacmSecurityToGroupRowStatus = 2; 57 58 private static final OID vacmSecurityToGroupEntryOID = 59 new OID(new int[] {1,3,6,1,6,3,16,1,2,1}); 60 61 private static final int colVacmAccessContextMatch = 4; 62 private static final int colVacmAccessReadViewName = 5; 63 private static final int colVacmAccessWriteViewName = 6; 64 private static final int colVacmAccessNotifyViewName = 7; 65 private static final int colVacmAccessStorageType = 8; 66 private static final int colVacmAccessRowStatus = 9; 67 68 private static final int idxVacmAccessContextPrefix = 1; 70 private static final int idxVacmAccessSecurityModel = 2; 71 private static final int idxVacmAccessSecurityLevel = 3; 72 private static final int idxVacmAccessContextMatch = 0; 73 private static final int idxVacmAccessReadViewName = 1; 74 private static final int idxVacmAccessWriteViewName = 2; 75 private static final int idxVacmAccessNotifyViewName = 3; 76 private static final int idxVacmAccessStorageType = 4; 77 private static final int idxVacmAccessRowStatus = 5; 78 79 private static final OID vacmAccessEntryOID = 80 new OID(new int[] {1,3,6,1,6,3,16,1,4,1}); 81 82 public static final int vacmExactMatch = MutableVACM.VACM_MATCH_EXACT; 83 public static final int vacmPrefixMatch = MutableVACM.VACM_MATCH_PREFIX; 84 85 86 private static final OID vacmViewSpinLockOID = 87 new OID(new int[] {1,3,6,1,6,3,16,1,5,1,0}); 88 89 private static final int colVacmViewTreeFamilyMask = 3; 90 private static final int colVacmViewTreeFamilyType = 4; 91 private static final int colVacmViewTreeFamilyStorageType = 5; 92 private static final int colVacmViewTreeFamilyRowStatus = 6; 93 94 private static final int idxVacmViewTreeSubtree = 1; 96 97 private static final int idxVacmViewTreeFamilyMask = 0; 98 private static final int idxVacmViewTreeFamilyType = 1; 99 private static final int idxVacmViewTreeFamilyStorageType = 2; 100 private static final int idxVacmViewTreeFamilyRowStatus = 3; 101 102 private static final OID vacmViewTreeFamilyEntryOID = 103 new OID(new int[] {1,3,6,1,6,3,16,1,5,2,1}); 104 105 public static final int vacmViewIncluded = MutableVACM.VACM_VIEW_INCLUDED; 106 public static final int vacmViewExcluded = MutableVACM.VACM_VIEW_EXCLUDED; 107 108 private static final int[] vacmViewTreeFamilyTypeValues = { 109 vacmViewIncluded, vacmViewExcluded 110 }; 111 112 private static MOTableSubIndex[] vacmViewTreeFamilyIndexes = 113 new MOTableSubIndex[] { 114 new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32), 115 new MOTableSubIndex(SMIConstants.SYNTAX_OBJECT_IDENTIFIER, 0, 96) 116 }; 117 118 private static MOTableIndex vacmViewTreeFamilyIndex = 119 new MOTableIndex(vacmViewTreeFamilyIndexes); 120 121 private static MOTableSubIndex[] vacmAccessIndexes = new MOTableSubIndex[] { 122 new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32), 123 new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 0, 32), 124 new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1), 125 new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1) 126 }; 127 128 private static MOTableIndex vacmAccessIndex = 129 new MOTableIndex(vacmAccessIndexes) { 130 public boolean isValidIndex(OID index) { 131 boolean ok = super.isValidIndex(index); 132 if (ok) { 133 SecurityModels secModels = SecurityModels.getInstance(); 134 Integer32 secModel = new Integer32(index.get(index.size()-2)); 135 if ((secModel.getValue() != SecurityModel.SECURITY_MODEL_ANY) && 136 (secModels.getSecurityModel(secModel) == null)) { 137 return false; 138 } 139 int secLevel = index.get(index.size()-1); 140 if ((secLevel < 1) || (secLevel > 3)) { 141 return false; 142 } 143 } 144 return ok; 145 } 146 }; 147 148 private MOServer server; 149 150 private DefaultMOTable vacmContextTable; 151 152 private DefaultMOTable vacmSecurityToGroupTable; 153 private DefaultMOMutableTableModel vacmSecurityToGroupTableModel; 154 155 private DefaultMOTable vacmAccessTable; 156 private DefaultMOMutableTableModel vacmAccessTableModel; 157 158 private TestAndIncr vacmViewSpinLock; 159 160 private DefaultMOTable vacmViewTreeFamilyTable; 161 private DefaultMOMutableTableModel vacmViewTreeFamilyTableModel; 162 163 164 public VacmMIB(MOServer server) { 165 this.server = server; 166 createVacmContextTable(); 167 createVacmSecuritToGroupTable(); 168 createVacmAccessTable(); 169 createVacmViewTreeFamilyTable(); 170 vacmViewSpinLock = new TestAndIncr(vacmViewSpinLockOID); 171 } 172 173 public void registerMOs(MOServer server, OctetString context) throws 174 DuplicateRegistrationException { 175 server.register(vacmContextTable, context); 176 server.register(vacmSecurityToGroupTable, context); 177 server.register(vacmAccessTable, context); 178 server.register(vacmViewSpinLock, context); 179 server.register(vacmViewTreeFamilyTable, context); 180 } 181 182 private void createVacmContextTable() { 183 MOTableSubIndex[] vacmContextTableIndexes = new MOTableSubIndex[] { 184 new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 0, 32) }; 185 MOTableIndex vacmContextTableIndex = 186 new MOTableIndex(vacmContextTableIndexes); 187 MOColumn[] vacmContextColumns = new MOColumn[] { 188 new MOColumn(1, SMIConstants.SYNTAX_OCTET_STRING, 189 MOAccessImpl.ACCESS_READ_ONLY) }; 190 191 this.vacmContextTable = 192 new DefaultMOTable(vacmContextEntryOID, vacmContextTableIndex, 193 vacmContextColumns); 194 this.vacmContextTable.setVolatile(true); 195 this.vacmContextTable.setModel(new VacmContextTableModel()); 196 } 197 198 private void createVacmSecuritToGroupTable() { 199 MOTableSubIndex[] vacmSecurityToGroupIndexes = new MOTableSubIndex[] { 200 new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1), 201 new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32) }; 202 203 MOTableIndex vacmSecurityToGroupIndex = 204 new MOTableIndex(vacmSecurityToGroupIndexes) { 205 public boolean isValidIndex(OID index) { 206 boolean ok = super.isValidIndex(index); 207 if (ok) { 208 SecurityModels secModels = SecurityModels.getInstance(); 209 if (secModels.getSecurityModel(new Integer32(index.get(0))) == null) { 210 return false; 211 } 212 } 213 return ok; 214 } 215 }; 216 217 MOColumn[] vacmSecurityToGroupColumns = new MOColumn[] { 218 new SnmpAdminString(colVacmGroupName, 219 MOAccessImpl.ACCESS_READ_CREATE, null, true, 1, 32), 220 new StorageType(colVacmSecurityToGroupStorageType, 221 MOAccessImpl.ACCESS_READ_CREATE, 222 new Integer32(StorageType.nonVolatile), true), 223 new RowStatus(colVacmSecurityToGroupRowStatus) 224 }; 225 226 this.vacmSecurityToGroupTable = 227 new DefaultMOTable(vacmSecurityToGroupEntryOID, 228 vacmSecurityToGroupIndex, 229 vacmSecurityToGroupColumns); 230 vacmSecurityToGroupTableModel = new DefaultMOMutableTableModel(); 231 vacmSecurityToGroupTableModel.setRowFactory(new DefaultMOMutableRow2PCFactory()); 232 this.vacmSecurityToGroupTable.setModel(vacmSecurityToGroupTableModel); 233 } 234 235 private void createVacmAccessTable() { 236 MOColumn[] vacmAccessColumns = new MOColumn[] { 237 new Enumerated(colVacmAccessContextMatch, 238 MOAccessImpl.ACCESS_READ_CREATE, 239 new Integer32(vacmExactMatch), true, 240 new int[] { vacmExactMatch, vacmPrefixMatch }), 241 new SnmpAdminString(colVacmAccessReadViewName, 242 MOAccessImpl.ACCESS_READ_CREATE, 243 new OctetString(), true, 0, 32), 244 new SnmpAdminString(colVacmAccessWriteViewName, 245 MOAccessImpl.ACCESS_READ_CREATE, 246 new OctetString(), true, 0, 32), 247 new SnmpAdminString(colVacmAccessNotifyViewName, 248 MOAccessImpl.ACCESS_READ_CREATE, 249 new OctetString(), true, 0, 32), 250 new StorageType(colVacmAccessStorageType, 251 MOAccessImpl.ACCESS_READ_CREATE, 252 new Integer32(StorageType.nonVolatile), true), 253 new RowStatus(colVacmAccessRowStatus) 254 }; 255 256 vacmAccessTable = new DefaultMOTable(vacmAccessEntryOID, 257 vacmAccessIndex, 258 vacmAccessColumns); 259 vacmAccessTableModel = new DefaultMOMutableTableModel(); 260 vacmAccessTableModel.setRowFactory(new DefaultMOMutableRow2PCFactory()); 261 vacmAccessTable.setModel(vacmAccessTableModel); 262 } 263 264 private void createVacmViewTreeFamilyTable() { 265 MOColumn[] vacmViewTreeFamilyColumns = new MOColumn[] { 266 new SnmpAdminString(colVacmViewTreeFamilyMask, 267 MOAccessImpl.ACCESS_READ_CREATE, 268 new OctetString(), true, 0, 16), 269 new Enumerated(colVacmViewTreeFamilyType, 270 MOAccessImpl.ACCESS_READ_CREATE, 271 new Integer32(vacmViewIncluded), true, 272 vacmViewTreeFamilyTypeValues), 273 new StorageType(colVacmViewTreeFamilyStorageType, 274 MOAccessImpl.ACCESS_READ_CREATE, 275 new Integer32(StorageType.nonVolatile), true), 276 new RowStatus(colVacmViewTreeFamilyRowStatus) 277 }; 278 279 vacmViewTreeFamilyTable = new DefaultMOTable(vacmViewTreeFamilyEntryOID, 280 vacmViewTreeFamilyIndex, 281 vacmViewTreeFamilyColumns); 282 vacmViewTreeFamilyTableModel = new DefaultMOMutableTableModel(); 283 vacmViewTreeFamilyTableModel.setRowFactory(new DefaultMOMutableRow2PCFactory()); 284 vacmViewTreeFamilyTable.setModel(vacmViewTreeFamilyTableModel); 285 } 286 287 public void unregisterMOs(MOServer server, OctetString context) { 288 server.unregister(this.vacmContextTable, context); 289 server.unregister(this.vacmSecurityToGroupTable, context); 290 server.unregister(this.vacmAccessTable, context); 291 server.unregister(vacmViewSpinLock, context); 292 server.unregister(vacmViewTreeFamilyTable, context); 293 } 294 295 public int isAccessAllowed(OctetString context, OctetString securityName, 296 int securityModel, int securityLevel, int viewType, 297 OID oid) { 298 if (logger.isDebugEnabled()) { 299 logger.debug("VACM access requested for context="+context+ 300 ", securityName="+securityName+ 301 ", securityModel="+securityModel+ 302 ", securityLevel="+securityLevel+ 303 ", viewType="+viewType+ 304 ", OID="+oid); 305 } 306 if (!server.isContextSupported(context)) { 307 if (logger.isDebugEnabled()) { 308 logger.debug("Context '"+context+"' ist not supported"); 309 } 310 return VACM.VACM_NO_SUCH_CONTEXT; 311 } 312 OctetString groupName = getGroupName(securityName, securityModel); 313 if (groupName == null) { 314 if (logger.isDebugEnabled()) { 315 logger.debug("No group name for securityName="+securityName+ 316 " and securityModel="+securityModel); 317 } 318 return VACM.VACM_NO_GROUP_NAME; 319 } 320 OctetString viewName = getViewNameByGroup(context, securityModel, 321 securityLevel, viewType, 322 groupName); 323 if (viewName == null) { 324 return VACM.VACM_NO_ACCESS_ENTRY; 325 } 326 if (viewName.length() == 0) { 327 return VACM.VACM_NO_SUCH_VIEW; 328 } 329 return isAccessAllowed(viewName, oid); 330 } 331 332 public OctetString getViewName(OctetString context, 333 OctetString securityName, 334 int securityModel, 335 int securityLevel, 336 int viewType) { 337 OctetString groupName = getGroupName(securityName, securityModel); 338 if (groupName == null) { 339 return null; 340 } 341 return getViewNameByGroup(context, securityModel, securityLevel, 342 viewType, groupName); 343 } 344 345 private OctetString getViewNameByGroup(OctetString context, int securityModel, 346 int securityLevel, int viewType, 347 OctetString groupName) { 348 List accessEntries = getAccessEntries(groupName); 349 350 if (logger.isDebugEnabled()) { 351 logger.debug("Got views "+accessEntries+ 352 " for group name '"+groupName+"'"); 353 } 354 355 MOTableRow possibleMatch = null; 356 boolean foundExactContextMatch = false; 357 boolean foundMatchedSecModel = false; 358 int foundContextPrefixLength = 0; 359 int foundSecLevel = 0; 360 361 for (Iterator it = accessEntries.iterator(); it.hasNext(); ) { 362 MOTableRow row = (MOTableRow) it.next(); 363 if (((Integer32)row.getValue(idxVacmAccessRowStatus)).getValue() != 364 RowStatus.active) { 365 continue; 366 } 367 Variable[] indexValues = vacmAccessIndex.getIndexValues(row.getIndex()); 368 OctetString rowContext = 369 (OctetString) indexValues[idxVacmAccessContextPrefix]; 370 int rowSecurityModel = 371 ((Integer32)indexValues[idxVacmAccessSecurityModel]).getValue(); 372 int rowSecurityLevel = 373 ((Integer32)indexValues[idxVacmAccessSecurityLevel]).getValue(); 374 int rowContextMatch = 375 ((Integer32)row.getValue(idxVacmAccessContextMatch)).getValue(); 376 boolean exactContextMatch = rowContext.equals(context); 377 boolean prefixMatch = (!exactContextMatch) && 378 ((rowContextMatch == vacmPrefixMatch) && 379 (context.startsWith(rowContext))); 380 boolean matchSecModel = (rowSecurityModel == securityModel); 381 boolean matchSecLevel = (rowSecurityLevel <= securityLevel); 382 if ((exactContextMatch || prefixMatch) && 383 ((matchSecModel) || 384 (rowSecurityModel == SecurityModel.SECURITY_MODEL_ANY)) && 385 matchSecLevel) { 386 if ((possibleMatch == null) || 388 (((!foundMatchedSecModel) && (matchSecModel)) || 389 (((!foundMatchedSecModel) || (matchSecModel)) && 390 ((!foundExactContextMatch) && (exactContextMatch)) || 391 ((((!foundExactContextMatch) || (exactContextMatch)) && 392 (foundContextPrefixLength < rowContext.length())) || 393 ((foundContextPrefixLength == rowContext.length()) && 394 (foundSecLevel < rowSecurityLevel)))))) { 395 possibleMatch = row; 396 foundExactContextMatch = exactContextMatch; 397 if (prefixMatch) { 398 foundContextPrefixLength = rowContext.length(); 399 } 400 foundMatchedSecModel = matchSecModel; 401 foundSecLevel = securityLevel; 402 } 403 } 404 } 405 if (possibleMatch != null) { 406 OctetString viewName = null; 407 switch (viewType) { 408 case VACM.VIEW_READ: { 409 viewName = 410 (OctetString)possibleMatch.getValue(idxVacmAccessReadViewName); 411 break; 412 } 413 case VACM.VIEW_WRITE: { 414 viewName = (OctetString) 415 possibleMatch.getValue(idxVacmAccessWriteViewName); 416 break; 417 } 418 case VACM.VIEW_NOTIFY: { 419 viewName = (OctetString) 420 possibleMatch.getValue(idxVacmAccessNotifyViewName); 421 break; 422 } 423 } 424 if (logger.isDebugEnabled()) { 425 logger.debug("Matching view found for group name '"+groupName+"' is '"+ 426 viewName+"'"); 427 } 428 return viewName; 429 } 430 return null; 431 } 432 433 private OctetString getGroupName(OctetString securityName, 434 int securityModel) { 435 OID index = new OID(); 436 index.append(securityModel); 437 index.append(securityName.toSubIndex(false)); 438 MOTableRow row = vacmSecurityToGroupTableModel.getRow(index); 439 if (row != null) { 440 OctetString groupName = (OctetString) row.getValue(idxVacmGroupName); 441 if (logger.isDebugEnabled()) { 442 logger.debug("Found group name '"+groupName+"' for secName '"+ 443 securityName+" and secModel "+securityModel); 444 } 445 return groupName; 446 } 447 return null; 448 } 449 450 public int isAccessAllowed(OctetString viewName, OID oid) { 451 List views = getViews(viewName); 452 if (views.size() == 0) { 453 if (logger.isDebugEnabled()) { 454 logger.debug("No view tree family entry for view '" + viewName + "'"); 455 } 456 return VACM.VACM_NO_SUCH_VIEW; 457 } 458 for (int v=views.size()-1; v >= 0; v--) { 462 MOTableRow row = (MOTableRow) views.get(v); 463 if (((Integer32)row.getValue(idxVacmViewTreeFamilyRowStatus)).getValue()!= 464 RowStatus.active) { 465 continue; 467 } 468 OID index = row.getIndex(); 469 Variable[] indexValues = vacmViewTreeFamilyIndex.getIndexValues(index); 470 OID subtree = (OID) indexValues[idxVacmViewTreeSubtree]; 471 if (oid.size() < subtree.size()) { 472 continue; 474 } 475 OctetString mask = (OctetString) row.getValue(idxVacmViewTreeFamilyMask); 476 boolean match = true; 477 for (int i=0; i<subtree.size(); i++) { 478 if ((subtree.get(i) != oid.get(i)) && isBitSet(i, mask)) { 479 match = false; 480 break; 481 } 482 } 483 if (match) { 484 if (((Integer32)row.getValue(idxVacmViewTreeFamilyType)).getValue() == 486 vacmViewIncluded) { 487 if (logger.isDebugEnabled()) { 488 logger.debug("Access allowed for view '"+viewName+"' by subtree "+ 489 subtree+" for OID "+oid); 490 } 491 return VACM.VACM_OK; 492 } 493 else { 494 if (logger.isDebugEnabled()) { 496 logger.debug("Access denied for view '"+viewName+"' by subtree "+ 497 subtree+" for OID "+oid); 498 } 499 return VACM.VACM_NOT_IN_VIEW; 500 } 501 } 502 } 503 return VACM.VACM_NOT_IN_VIEW; 504 } 505 506 519 public void addGroup(int securityModel, OctetString securityName, 520 OctetString groupName, int storageType) { 521 OID index = createGroupIndex(securityModel, securityName); 522 Variable[] values = new Variable[vacmSecurityToGroupTable.getColumnCount()]; 523 values[idxVacmGroupName] = groupName; 524 values[idxVacmSecurityToGroupStorageType] = new Integer32(storageType); 525 values[idxVacmSecurityToGroupRowStatus] = new Integer32(RowStatus.active); 526 MOTableRow row = vacmSecurityToGroupTable.createRow(index, values); 527 vacmSecurityToGroupTableModel.addRow(row); 528 } 529 530 private static OID createGroupIndex(int securityModel, 531 OctetString securityName) { 532 OID index = new OID(); 533 index.append(securityModel); 534 index.append(securityName.toSubIndex(false)); 535 return index; 536 } 537 538 548 public boolean removeGroup(int securityModel, OctetString securityName) { 549 OID index = createGroupIndex(securityModel, securityName); 550 return (vacmSecurityToGroupTableModel.removeRow(index) != null); 551 } 552 553 579 public void addAccess(OctetString groupName, OctetString contextPrefix, 580 int securityModel, int securityLevel, 581 int match, 582 OctetString readView, OctetString writeView, 583 OctetString notifyView, int storageType) { 584 OID index = createAccessIndex(groupName, contextPrefix, securityModel, 585 securityLevel); 586 Variable[] values = new Variable[vacmAccessTable.getColumnCount()]; 587 values[idxVacmAccessContextMatch] = new Integer32(match); 588 values[idxVacmAccessReadViewName] = readView; 589 values[idxVacmAccessWriteViewName] = writeView; 590 values[idxVacmAccessNotifyViewName] = notifyView; 591 values[idxVacmAccessStorageType] = new Integer32(storageType); 592 values[idxVacmAccessRowStatus] = new Integer32(RowStatus.active); 593 vacmAccessTableModel.addRow(vacmAccessTableModel.createRow(index, values)); 594 } 595 596 610 public boolean removeAccess(OctetString groupName, OctetString contextPrefix, 611 int securityModel, int securityLevel) { 612 OID index = createAccessIndex(groupName, contextPrefix, securityModel, 613 securityLevel); 614 return (vacmAccessTableModel.removeRow(index) != null); 615 } 616 617 private static OID createAccessIndex(OctetString groupName, 618 OctetString contextPrefix, 619 int securityModel, int securityLevel) { 620 OID index = groupName.toSubIndex(false); 621 index.append(contextPrefix.toSubIndex(false)); 622 index.append(securityModel); 623 index.append(securityLevel); 624 return index; 625 } 626 627 644 public void addViewTreeFamily(OctetString viewName, OID subtree, 645 OctetString mask, int type, int storageType) { 646 OID index = createViewIndex(viewName, subtree); 647 Variable[] values = new Variable[vacmViewTreeFamilyTable.getColumnCount()]; 648 values[idxVacmViewTreeFamilyMask] = mask; 649 values[idxVacmViewTreeFamilyType] = new Integer32(type); 650 values[idxVacmViewTreeFamilyStorageType] = new Integer32(storageType); 651 values[idxVacmViewTreeFamilyRowStatus] = new Integer32(RowStatus.active); 652 MOTableRow row = vacmViewTreeFamilyTableModel.createRow(index, values); 653 vacmViewTreeFamilyTableModel.addRow(row); 654 } 655 656 666 public boolean removeViewTreeFamily(OctetString viewName, OID subtree) { 667 OID index = createViewIndex(viewName, subtree); 668 return (vacmViewTreeFamilyTableModel.removeRow(index) != null); 669 } 670 671 private static OID createViewIndex(OctetString viewName, OID subtree) { 672 OID index = viewName.toSubIndex(false); 673 index.append(subtree.toSubIndex(false)); 674 return index; 675 } 676 677 684 private static boolean isBitSet(final int n, final OctetString os) { 685 if (os.length() <= n/8) { 686 return true; 687 } 688 return (os.get(n/8) & (0x01 << (7 - (n % 8)))) > 0; 689 } 690 691 private List getAccessEntries(OctetString groupName) { 692 OctetString upperBound = new OctetString(groupName); 693 byte last = -1; 694 if (upperBound.length() > 0) { 695 last = upperBound.get(upperBound.length() - 1); 696 } 697 if (last == -1) { 698 upperBound.append((byte)0); 699 } 700 else { 701 upperBound.set(upperBound.length()-1, (byte)(last+1)); 702 } 703 OID lowerOID = groupName.toSubIndex(false); 704 OID upperOID = upperBound.toSubIndex(false); 705 List views = vacmAccessTableModel.getRows(lowerOID, upperOID); 706 return views; 707 } 708 709 private List getViews(OctetString viewName) { 710 if (viewName.length() == 0) { 711 return Collections.EMPTY_LIST; 712 } 713 OctetString upperBound = new OctetString(viewName); 714 byte last = upperBound.get(upperBound.length()-1); 715 if (last == -1) { 716 upperBound.append((byte)0); 717 } 718 else { 719 upperBound.set(upperBound.length()-1, (byte)(last+1)); 720 } 721 OID lowerOID = viewName.toSubIndex(false); 722 OID upperOID = upperBound.toSubIndex(false); 723 List views = vacmViewTreeFamilyTableModel.getRows(lowerOID, upperOID); 724 return views; 725 } 726 727 public static class VacmContextIterator implements Iterator { 728 729 private int index = 0; 730 private OctetString[] contexts; 731 732 VacmContextIterator(OctetString[] contexts, int offset) { 733 this.contexts = contexts; 734 this.index = offset; 735 } 736 737 public void remove() { 738 throw new UnsupportedOperationException (); 739 } 740 741 public boolean hasNext() { 742 return (index < contexts.length); 743 } 744 745 public Object next() { 746 if (index < contexts.length) { 747 OctetString context = contexts[index++]; 748 DefaultMOTableRow row = 749 new DefaultMOTableRow(context.toSubIndex(false), 750 new Variable[] { context }); 751 return row; 752 } 753 throw new NoSuchElementException(); 754 } 755 756 } 757 758 private static OctetString getContextFromIndex(OID index) { 759 if (index.size() > 0) { 760 return new OctetString(index.toByteArray(), 1, index.size() - 1); 761 } 762 return new OctetString(); 763 } 764 765 766 class VacmContextTableModel implements MOTableModel { 767 768 public int getColumnCount() { 769 return 1; 770 } 771 772 public int getRowCount() { 773 return server.getContexts().length; 774 } 775 776 public boolean containsRow(OID index) { 777 return server.isContextSupported(getContextFromIndex(index)); 778 } 779 780 public MOTableRow getRow(OID index) { 781 if (index == null) { 782 return null; 783 } 784 OctetString context = getContextFromIndex(index); 785 if (server.isContextSupported(context)) { 786 DefaultMOTableRow row = 787 new DefaultMOTableRow(index, new Variable[] { context }); 788 return row; 789 } 790 return null; 791 } 792 793 public Iterator iterator() { 794 return tailIterator(new OID()); 795 } 796 797 public Iterator tailIterator(OID lowerBound) { 798 OctetString[] contexts = server.getContexts(); 799 if (contexts == null) { 800 return new VacmContextIterator(new OctetString[0], 0); 801 } 802 Arrays.sort(contexts, new LexicographicOctetStringComparator()); 803 int offset = 0; 804 if (lowerBound != null) { 805 offset = Arrays.binarySearch(contexts, getContextFromIndex(lowerBound)); 806 } 807 if (offset < 0) { 808 offset = -(offset+1); 809 } 810 return new VacmContextIterator(contexts, offset); 811 } 812 813 public OID lastIndex() { 814 OctetString[] contexts = server.getContexts(); 815 if ((contexts == null) || (contexts.length == 0)) { 816 return null; 817 } 818 Arrays.sort(contexts, new LexicographicOctetStringComparator()); 819 return contexts[contexts.length-1].toSubIndex(false); 820 } 821 822 public OID firstIndex() { 823 OctetString[] contexts = server.getContexts(); 824 if ((contexts == null) || (contexts.length == 0)) { 825 return null; 826 } 827 Arrays.sort(contexts, new LexicographicOctetStringComparator()); 828 return contexts[0].toSubIndex(false); 829 } 830 831 public MOTableRow firstRow() { 832 return getRow(firstIndex()); 833 } 834 835 public MOTableRow lastRow() { 836 return getRow(lastIndex()); 837 } 838 } 839 840 } 841 | Popular Tags |