1 36 package org.ungoverned.moduleloader.search; 37 38 import java.net.URL ; 39 import java.util.*; 40 41 import org.ungoverned.moduleloader.*; 42 43 232 public class ImportSearchPolicy implements SearchPolicy, ModuleListener 233 { 234 240 public static final String EXPORTS_ATTR = "exports"; 241 247 public static final String IMPORTS_ATTR = "imports"; 248 254 public static final String PROPAGATES_ATTR = "propagates"; 255 261 public static final String VALID_ATTR = "valid"; 262 263 268 public static final int IDENTIFIER_IDX = 0; 269 274 public static final int VERSION_IDX = 1; 275 280 public static final int RESOLVING_MODULE_IDX = 2; 281 282 private ModuleManager m_mgr = null; 283 private CompatibilityPolicy m_compatPolicy = null; 284 private SelectionPolicy m_selectPolicy = null; 285 private ValidationListener[] m_listeners = null; 286 private String [] m_searchAttrs = { IMPORTS_ATTR, EXPORTS_ATTR }; 287 private static final ValidationListener[] m_noListeners = new ValidationListener[0]; 288 289 297 public ImportSearchPolicy( 298 CompatibilityPolicy compatPolicy, 299 SelectionPolicy selectPolicy) 300 { 301 m_compatPolicy = compatPolicy; 302 m_selectPolicy = selectPolicy; 303 m_listeners = m_noListeners; 304 } 305 306 310 public CompatibilityPolicy getCompatibilityPolicy() 311 { 312 return m_compatPolicy; 313 } 314 315 319 public SelectionPolicy getSelectionPolicy() 320 { 321 return m_selectPolicy; 322 } 323 324 public void setModuleManager(ModuleManager mgr) 326 throws IllegalStateException 327 { 328 if (m_mgr == null) 329 { 330 m_mgr = mgr; 331 m_mgr.addModuleListener(this); 332 } 333 else 334 { 335 throw new IllegalStateException ("Module manager is already initialized"); 336 } 337 } 338 339 355 public Class findClass(Module module, String name) 356 throws ClassNotFoundException 357 { 358 try { 360 validate(module); 361 } catch (ValidationException ex) { 362 throw new ClassNotFoundException (name); 363 } 364 365 String pkgName = (name.lastIndexOf('.') < 0) 367 ? "" : name.substring(0, name.lastIndexOf('.')); 368 369 for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++) 377 { 378 Object [][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]); 379 380 if ((imports != null) && (imports.length > 0)) 383 { 384 for (int i = 0; i < imports.length; i++) 385 { 386 if (imports[i][IDENTIFIER_IDX].equals(pkgName)) 389 { 390 Module resolvingModule = (Module) imports[i][RESOLVING_MODULE_IDX]; 391 try 392 { 393 Class clazz = 394 resolvingModule.getClassLoader().searchForClass(name); 395 if (clazz != null) 396 { 397 return clazz; 398 } 399 } 400 catch (Throwable th) 401 { 402 } 404 throw new ClassNotFoundException (name); 405 } 406 } 407 } 408 } 409 410 return null; 411 } 412 413 427 public URL findResource(Module module, String name) 428 throws ResourceNotFoundException 429 { 430 try 432 { 433 validate(module); 434 } 435 catch (ValidationException ex) 436 { 437 return null; 438 } 439 440 String pkgName = (name.startsWith("/")) ? name.substring(1) : name; 453 pkgName = (pkgName.lastIndexOf('/') < 0) 454 ? "" : pkgName.substring(0, pkgName.lastIndexOf('/')); 455 pkgName = pkgName.replace('/', '.'); 456 457 for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++) 465 { 466 Object [][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]); 467 468 if ((imports != null) && (imports.length > 0)) 471 { 472 for (int i = 0; i < imports.length; i++) 473 { 474 if (imports[i][IDENTIFIER_IDX].equals(pkgName)) 477 { 478 Module resolvingModule = (Module) imports[i][RESOLVING_MODULE_IDX]; 479 try 480 { 481 URL url = 482 resolvingModule.getClassLoader().searchForResource(name); 483 if (url != null) 484 { 485 return url; 486 } 487 } 488 catch (Throwable th) 489 { 490 } 492 throw new ResourceNotFoundException(name); 493 } 494 } 495 } 496 } 497 498 return null; 499 } 500 501 private Map m_validateMap = new HashMap(); 502 private Module m_rootModule = null; 503 504 523 public void validate(Module module) 524 throws ValidationException 525 { 526 if (getValidAttribute(module).booleanValue()) 527 { 528 return; 529 } 530 531 boolean isValid = true; 533 534 List fireValidatedList = null; 538 539 ValidationException invalidException = null; 541 542 synchronized (m_mgr) 546 { 547 if (m_validateMap.get(module) != null) 550 { 551 return; 552 } 553 554 m_validateMap.put(module, module); 557 558 if (m_rootModule == null) 562 { 563 m_rootModule = module; 564 } 565 566 Map propagateMap = new HashMap(); 568 569 for (int attrIdx = 0; (isValid) && (attrIdx < m_searchAttrs.length); attrIdx++) 579 { 580 Object [][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]); 583 for (int impIdx = 0; impIdx < imports.length; impIdx++) 585 { 586 Module[] candidates = 588 getCompatibleModules( 589 imports[impIdx][IDENTIFIER_IDX], imports[impIdx][VERSION_IDX]); 590 if (candidates == null) 593 { 594 isValid = false; 595 invalidException = 596 new ValidationException( 597 "Unable to validate module", 598 module, 599 imports[impIdx][IDENTIFIER_IDX], 600 imports[impIdx][VERSION_IDX], 601 false); 602 break; 603 } 604 605 Module exportingModule = m_selectPolicy.select( 607 module, imports[impIdx][IDENTIFIER_IDX], 608 imports[impIdx][VERSION_IDX], candidates, m_compatPolicy); 609 if (exportingModule == null) 612 { 613 isValid = false; 614 invalidException = 615 new ValidationException( 616 "Unable to validate module", 617 module, 618 imports[impIdx][IDENTIFIER_IDX], 619 imports[impIdx][VERSION_IDX], 620 false); 621 break; 622 } 623 624 try 627 { 628 validate(exportingModule); 629 } 630 catch (ValidationException ex) 631 { 632 isValid = false; 635 invalidException = ex; 636 break; 637 } 638 639 Object [] propagates = getPropagatesAttribute(exportingModule); 644 for (int propIdx = 0; propIdx < propagates.length; propIdx++) 645 { 646 if (doesImport(module, propagates[propIdx])) 649 { 650 Module sourceModule = 651 (Module) propagateMap.get(propagates[propIdx]); 652 653 if (sourceModule == null) 658 { 659 propagateMap.put( 660 propagates[propIdx], 661 getImportResolvingModule( 662 exportingModule, propagates[propIdx])); 663 } 664 else if (sourceModule != 669 getImportResolvingModule( 670 exportingModule, propagates[propIdx])) 671 { 672 isValid = false; 673 invalidException = 674 new ValidationException( 675 "Unable to validate module", 676 exportingModule, 677 propagates[propIdx], 678 null, 679 true); 680 break; 681 } 682 } 683 } 684 685 imports[impIdx][RESOLVING_MODULE_IDX] = exportingModule; 688 } 689 } 690 691 if (m_rootModule == module) 695 { 696 if (isValid) 698 { 699 Iterator iter = m_validateMap.keySet().iterator(); 702 while (iter.hasNext()) 703 { 704 Module m = (Module) iter.next(); 705 if (!getValidAttribute(m).booleanValue()) 706 { 707 m.setAttribute(VALID_ATTR, Boolean.TRUE); 708 if (fireValidatedList == null) 709 { 710 fireValidatedList = new ArrayList(); 711 } 712 fireValidatedList.add(m); 713 } 714 } 715 } 716 else 719 { 720 Iterator iter = m_validateMap.keySet().iterator(); 721 while (iter.hasNext()) 722 { 723 Module m = (Module) iter.next(); 724 invalidate( 725 m, 726 m.getAttributes(), 727 m.getResourceSources(), 728 m.getLibrarySources()); 729 } 730 } 731 732 m_rootModule = null; 735 m_validateMap.clear(); 736 } 737 } 738 739 if (!isValid) 743 { 744 throw invalidException; 745 } 746 else if (fireValidatedList != null) 747 { 748 for (int i = 0; i < fireValidatedList.size(); i++) 749 { 750 fireModuleValidated((Module) fireValidatedList.get(i)); 751 } 752 } 753 } 754 755 763 protected Module[] getCompatibleModules(Object identifier, Object version) 764 { 765 List list = null; 766 Module[] modules = m_mgr.getModules(); 767 for (int modIdx = 0; modIdx < modules.length; modIdx++) 768 { 769 Object [][] exports = getExportsAttribute(modules[modIdx]); 770 for (int expIdx = 0; expIdx < exports.length; expIdx++) 771 { 772 if (m_compatPolicy.isCompatible( 775 exports[expIdx][IDENTIFIER_IDX], exports[expIdx][VERSION_IDX], 776 identifier, version)) 777 { 778 if (list == null) 779 { 780 list = new ArrayList(); 781 } 782 list.add(modules[modIdx]); 783 } 784 } 785 } 786 787 if (list == null) 788 { 789 return null; 790 } 791 792 Module[] result = new Module[list.size()]; 793 return (Module[]) list.toArray(result); 794 } 795 796 807 public void invalidate( 808 Module module, Object [][] attributes, 809 ResourceSource[] resSources, LibrarySource[] libSources) 810 { 811 synchronized (m_mgr) 815 { 816 m_mgr.resetModule(module, attributes, resSources, libSources); 817 } 818 819 fireModuleInvalidated(m_mgr.getModule(module.getId())); 821 } 822 823 827 833 public void addValidationListener(ValidationListener l) 834 { 835 if (l == null) 837 { 838 throw new IllegalArgumentException ("Listener is null"); 839 } 840 841 synchronized (m_noListeners) 843 { 844 if (m_listeners == m_noListeners) 846 { 847 m_listeners = new ValidationListener[] { l }; 848 } 849 else 855 { 856 ValidationListener[] newList = new ValidationListener[m_listeners.length + 1]; 857 System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length); 858 newList[m_listeners.length] = l; 859 m_listeners = newList; 860 } 861 } 862 } 863 864 868 public void removeValidationListener(ValidationListener l) 869 { 870 if (l == null) 872 { 873 throw new IllegalArgumentException ("Listener is null"); 874 } 875 876 synchronized (m_noListeners) 878 { 879 int idx = -1; 881 for (int i = 0; i < m_listeners.length; i++) 882 { 883 if (m_listeners[i].equals(l)) 884 { 885 idx = i; 886 break; 887 } 888 } 889 890 if (idx >= 0) 892 { 893 if (m_listeners.length == 1) 895 { 896 m_listeners = m_noListeners; 897 } 898 else 904 { 905 ValidationListener[] newList = new ValidationListener[m_listeners.length - 1]; 906 System.arraycopy(m_listeners, 0, newList, 0, idx); 907 if (idx < newList.length) 908 { 909 System.arraycopy(m_listeners, idx + 1, newList, idx, 910 newList.length - idx); 911 } 912 m_listeners = newList; 913 } 914 } 915 } 916 } 917 918 922 protected void fireModuleValidated(Module module) 923 { 924 ModuleEvent event = null; 926 927 ValidationListener[] listeners = m_listeners; 930 931 for (int i = 0; i < listeners.length; i++) 933 { 934 if (event == null) 936 { 937 event = new ModuleEvent(m_mgr, module); 938 } 939 listeners[i].moduleValidated(event); 940 } 941 } 942 943 947 protected void fireModuleInvalidated(Module module) 948 { 949 ModuleEvent event = null; 951 952 ValidationListener[] listeners = m_listeners; 955 956 for (int i = 0; i < listeners.length; i++) 958 { 959 if (event == null) 961 { 962 event = new ModuleEvent(m_mgr, module); 963 } 964 listeners[i].moduleInvalidated(event); 965 } 966 } 967 968 972 979 public void moduleAdded(ModuleEvent event) 980 { 981 synchronized (event.getModule()) 982 { 983 event.getModule().setAttribute(VALID_ATTR, Boolean.FALSE); 985 986 for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++) 987 { 988 Object [][] imports = 989 getImportsOrExports(event.getModule(), m_searchAttrs[attrIdx]); 990 for (int i = 0; i < imports.length; i++) 991 { 992 imports[i][RESOLVING_MODULE_IDX] = null; 993 } 994 } 995 } 996 } 997 998 1006 public void moduleReset(ModuleEvent event) 1007 { 1008 moduleAdded(event); 1010 1011 ModuleManager m_mgr = (ModuleManager) event.getSource(); 1013 List list = createImporterList(m_mgr, event.getModule()); 1014 for (int i = 0; (list != null) && (i < list.size()); i++) 1015 { 1016 Module module = (Module) list.get(i); 1017 invalidate( 1018 module, module.getAttributes(), 1019 module.getResourceSources(), module.getLibrarySources()); 1020 } 1021 } 1022 1023 1029 public void moduleRemoved(ModuleEvent event) 1030 { 1031 ModuleManager m_mgr = (ModuleManager) event.getSource(); 1033 List list = createImporterList(m_mgr, event.getModule()); 1034 for (int i = 0; (list != null) && (i < list.size()); i++) 1035 { 1036 Module module = (Module) list.get(i); 1037 invalidate( 1038 module, module.getAttributes(), 1039 module.getResourceSources(), module.getLibrarySources()); 1040 } 1041 } 1042 1043 1047 1062 public Module resolveImportTarget(Object identifier, Object version) 1063 { 1064 Object [] targetImport = { identifier, version, null }; 1068 Object [][] attrs = new Object [][] { 1069 new Object [] { EXPORTS_ATTR, new Object [0][0] }, 1070 new Object [] { IMPORTS_ATTR, new Object [][] { targetImport } }, 1071 new Object [] { PROPAGATES_ATTR, new Object [0] }, 1072 new Object [] { VALID_ATTR, Boolean.FALSE} 1073 }; 1074 Module fake = new Module(m_mgr, "resolve import", attrs, null, null); 1075 try { 1076 validate(fake); 1077 } catch (ValidationException ex) { 1078 } 1080 return (Module) targetImport[RESOLVING_MODULE_IDX]; 1081 } 1082 1083 1087 private static final Object [][] m_emptyImports = new Object [0][0]; 1088 private static final Object [] m_emptyProp = new Object [0]; 1089 1090 1097 public static Boolean getValidAttribute(Module module) 1098 { 1099 Object value = module.getAttribute(VALID_ATTR); 1100 if (value != null) 1101 { 1102 return (Boolean ) value; 1103 } 1104 return Boolean.FALSE; 1105 } 1106 1107 1114 public static Object [][] getImportsAttribute(Module module) 1115 { 1116 Object value = module.getAttribute(IMPORTS_ATTR); 1117 if (value != null) 1118 { 1119 return (Object [][]) value; 1120 } 1121 return m_emptyImports; 1122 } 1123 1124 1131 public static Object [][] getExportsAttribute(Module module) 1132 { 1133 Object value = module.getAttribute(EXPORTS_ATTR); 1134 if (value != null) 1135 { 1136 return (Object [][]) value; 1137 } 1138 return m_emptyImports; 1139 } 1140 1141 1150 public static Object [][] getImportsOrExports(Module module, String name) 1151 { 1152 Object value = module.getAttribute(name); 1153 if (value != null) 1154 { 1155 return (Object [][]) value; 1156 } 1157 return m_emptyImports; 1158 } 1159 1160 1167 public static Object [] getPropagatesAttribute(Module module) 1168 { 1169 Object value = module.getAttribute(PROPAGATES_ATTR); 1170 if (value != null) 1171 { 1172 return (Object []) value; 1173 } 1174 return m_emptyProp; 1175 } 1176 1177 1186 public static boolean doesImport(Module module, Object identifier) 1187 { 1188 Object [][] imports = getImportsAttribute(module); 1189 for (int i = 0; i < imports.length; i++) 1190 { 1191 if (imports[i][IDENTIFIER_IDX].equals(identifier)) 1192 { 1193 return true; 1194 } 1195 } 1196 imports = getExportsAttribute(module); 1197 for (int i = 0; i < imports.length; i++) 1198 { 1199 if (imports[i][IDENTIFIER_IDX].equals(identifier)) 1200 { 1201 return true; 1202 } 1203 } 1204 return false; 1205 } 1206 1207 1215 public static List createImporterList(ModuleManager mgr, Module module) 1216 { 1217 List list = null; 1218 Module[] modules = mgr.getModules(); 1219 for (int modIdx = 0; modIdx < modules.length; modIdx++) 1220 { 1221 Object [][] imports = getImportsAttribute(modules[modIdx]); 1222 for (int impIdx = 0; impIdx < imports.length; impIdx++) 1223 { 1224 if (imports[impIdx][RESOLVING_MODULE_IDX] == module) 1225 { 1226 if (list == null) 1227 { 1228 list = new ArrayList(); 1229 } 1230 list.add(modules[modIdx]); 1231 break; 1232 } 1233 } 1234 } 1235 1236 return list; 1237 } 1238 1239 1247 public static Object getImportVersion(Module module, Object identifier) 1248 { 1249 Object [][] imports = getImportsAttribute(module); 1250 for (int i = 0; i < imports.length; i++) 1251 { 1252 if (imports[i][IDENTIFIER_IDX].equals(identifier)) 1253 { 1254 return imports[i][VERSION_IDX]; 1255 } 1256 } 1257 return null; 1258 } 1259 1260 1268 public static Object getExportVersion(Module module, Object identifier) 1269 { 1270 Object [][] exports = getExportsAttribute(module); 1271 for (int i = 0; i < exports.length; i++) 1272 { 1273 if (exports[i][IDENTIFIER_IDX].equals(identifier)) 1274 { 1275 return exports[i][VERSION_IDX]; 1276 } 1277 } 1278 return null; 1279 } 1280 1281 1289 public static Module getImportResolvingModule(Module module, Object identifier) 1290 { 1291 Object [][] imports = getImportsAttribute(module); 1292 1293 for (int i = 0; i < imports.length; i++) 1294 { 1295 if (imports[i][IDENTIFIER_IDX].equals(identifier)) 1296 { 1297 return (Module) imports[i][RESOLVING_MODULE_IDX]; 1298 } 1299 } 1300 1301 return null; 1302 } 1303 1304 1312 public static Module getExportResolvingModule(Module module, Object identifier) 1313 { 1314 Object [][] exports = getExportsAttribute(module); 1315 1316 for (int i = 0; i < exports.length; i++) 1317 { 1318 if (exports[i][IDENTIFIER_IDX].equals(identifier)) 1319 { 1320 return (Module) exports[i][RESOLVING_MODULE_IDX]; 1321 } 1322 } 1323 1324 return null; 1325 } 1326} | Popular Tags |