1 64 65 package com.jcorporate.expresso.core.dbobj; 66 67 import com.jcorporate.expresso.core.controller.Controller; 68 import com.jcorporate.expresso.core.controller.ControllerException; 69 import com.jcorporate.expresso.core.db.DBException; 70 import com.jcorporate.expresso.core.i18n.Messages; 71 import com.jcorporate.expresso.core.job.Job; 72 import com.jcorporate.expresso.core.misc.ConfigContext; 73 import com.jcorporate.expresso.core.misc.ConfigManager; 74 import com.jcorporate.expresso.core.misc.ConfigSetupDefault; 75 import com.jcorporate.expresso.core.misc.StringUtil; 76 import com.jcorporate.expresso.core.servlet.StdServlet; 77 import com.jcorporate.expresso.ext.report.ExpressoReport; 78 import com.jcorporate.expresso.kernel.ComponentLifecycle; 79 import com.jcorporate.expresso.kernel.Configuration; 80 import com.jcorporate.expresso.kernel.ContainerComponentBase; 81 import com.jcorporate.expresso.kernel.InstallLog; 82 import com.jcorporate.expresso.kernel.exception.ConfigurationException; 83 import com.jcorporate.expresso.kernel.management.ExpressoRuntimeMap; 84 import com.jcorporate.expresso.kernel.util.ClassLocator; 85 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 86 import com.jcorporate.expresso.services.controller.RegistrationFactory; 87 import com.jcorporate.expresso.services.dbobj.Setup; 88 import org.apache.log4j.Logger; 89 90 import java.net.URL ; 91 import java.util.Collections ; 92 import java.util.Enumeration ; 93 import java.util.HashMap ; 94 import java.util.Hashtable ; 95 import java.util.Iterator ; 96 import java.util.Map ; 97 import java.util.StringTokenizer ; 98 import java.util.Vector ; 99 100 101 117 public abstract class Schema extends ContainerComponentBase implements ComponentLifecycle, RegistrationFactory { 118 119 private static Logger log = Logger.getLogger(Schema.class); 120 121 private static Map schemaDefinitions = Collections.synchronizedMap(new HashMap (5)); 122 123 124 127 private Map setupValue = new HashMap (); 128 129 132 private Map defaultSetupValues = new HashMap (); 133 134 140 private String dbKey = ""; 141 142 143 147 private String defaultComponentCode = ""; 148 149 152 private String defaultDescription = "No Description Provided"; 153 154 158 private static Schema myInstance = null; 159 160 161 164 private String messageBundlePath = ""; 165 private int mUserID; 166 167 168 171 public Schema() { 172 173 if (schemaDefinitions.containsKey(this.getClass().getName())) { 177 return; 179 } 180 181 if (myInstance == null) { 182 myInstance = this; 183 } 184 185 schemaDefinitions.put(this.getClass().getName(), new SchemaDefinition()); 186 187 188 } 189 190 195 protected synchronized void addDBObject(String dbobjectClass) { 196 addDBObject(dbobjectClass, null, "default"); 197 } 198 199 206 protected synchronized void addDBObject(Class c, String categoryName) { 207 addDBObject(c.getName(), null, categoryName); 208 } 209 210 218 protected synchronized void addDBObject(Class c) { 219 addDBObject(c.getName(), null, "default"); 220 } 221 222 223 231 protected synchronized void addDBObject(String dbobjectClass, 232 String otherDBName) { 233 addDBObject(dbobjectClass, otherDBName, "default"); 234 } 235 236 244 protected synchronized void addDBObject(String dbobjectClass, 245 String otherDBName, 246 String categoryName) { 247 StringUtil.assertNotBlank(dbobjectClass, 248 "DB Object class name may not " + 249 " be null or blank here"); 250 SchemaDefinition sd = getDef(); 251 sd.addMember(dbobjectClass); 252 253 if (otherDBName != null) { 254 sd.addDBObjectMap(dbobjectClass, otherDBName); 255 } 256 257 } 258 259 260 266 protected synchronized void addController(String controllerName) { 267 addController(controllerName, "default"); 268 } 269 270 278 protected synchronized void addController(Class c) { 279 addController(c.getName()); 280 } 281 282 291 protected synchronized void addController(String controllerName, 292 String categoryName) { 293 SchemaDefinition sd = getDef(); 294 sd.addController(controllerName); 295 } 296 297 306 protected synchronized void addController(Class c, String categoryName) { 307 addController(c.getName(), categoryName); 308 } 309 310 317 public synchronized void addReportPage(Class reportClass) { 318 addReportPage(reportClass.getName()); 319 } 320 321 327 public synchronized void addReportPage(String reportClassName) { 328 StringUtil.assertNotBlank(reportClassName, 329 "Blank report class name not allowed here"); 330 SchemaDefinition sd = getDef(); 331 sd.addReport(reportClassName); 332 } 333 334 342 public synchronized void add(Job oneJob) 343 throws DBException { 344 getDef().addJob(oneJob.getClass().getName()); 345 } 346 347 355 protected synchronized void addJob(Class c) { 356 getDef().addJob(c.getName()); 357 } 358 359 367 protected synchronized void addServlet(Class c) { 368 getDef().addServlet(c.getName()); 369 } 370 371 382 public synchronized void add(String schemaClass, String setupCode, 383 String descrip, String defaultValue) 384 throws DBException { 385 addSetup(schemaClass, setupCode, descrip, defaultValue); 386 } 387 388 397 public synchronized void addSetup(String schemaClass, String setupCode, 398 String descrip, String defaultValue) 399 throws DBException { 400 401 FastStringBuffer fsb = FastStringBuffer.getInstance(); 402 try { 403 fsb.append(schemaClass); 404 fsb.append("|"); 405 fsb.append(setupCode); 406 fsb.append("|"); 407 fsb.append(descrip); 408 fsb.append("|"); 409 fsb.append(defaultValue); 410 411 getDef().addConfigValue(fsb.toString()); 412 } finally { 413 fsb.release(); 414 } 415 416 this.defaultSetupValues.put(setupCode, defaultValue); 417 418 } 419 420 428 public synchronized void addSetup(String setupCode, 429 String descrip, String defaultValue) 430 throws DBException { 431 addSetup(getClass().getName(), setupCode, descrip, defaultValue); 432 } 433 434 439 public synchronized Vector getConfig() { 440 Vector newConfig = new Vector (); 441 String oneHolder = null; 442 443 for (Iterator e = getDef().getConfigValues(); e.hasNext();) { 444 oneHolder = (String ) e.next(); 445 446 StringTokenizer stk = new StringTokenizer (oneHolder, "|"); 447 448 try { 449 Setup oneSetup = new Setup(SecuredDBObject.SYSTEM_ACCOUNT); 450 oneSetup.setField("SchemaClass", stk.nextToken()); 451 oneSetup.setField("SetupCode", stk.nextToken()); 452 oneSetup.setField("Descrip", stk.nextToken()); 453 454 if (stk.hasMoreTokens()) { 456 oneSetup.setField("SetupValue", stk.nextToken()); 457 } 458 459 newConfig.addElement(oneSetup); 460 } catch (Exception ee) { 461 log.error("Error parsing setup value: " + oneHolder, ee); 462 } 463 } 464 465 466 return newConfig; 467 } 468 469 476 public java.util.List getControllerList() { 477 java.util.List theControllers = new java.util.ArrayList (4); 478 String oneControllerName = null; 479 Controller oneController = null; 480 481 for (Iterator ee = getDef().getControllers(); ee.hasNext();) { 482 oneControllerName = (String ) ee.next(); 483 484 try { 485 oneController = ConfigManager.getControllerFactory().getController(oneControllerName); 486 theControllers.add(oneController); 487 } catch (Exception e) { 488 log.error("Unable to instantiate controller '" + 489 oneControllerName + "'", e); 490 } 491 } 492 493 494 return theControllers; 495 496 } 497 498 504 public String getDefaultComponentCode() { 505 return this.defaultComponentCode; 506 } 507 508 509 515 public String getDefaultDescription() { 516 return this.defaultDescription; 517 } 518 519 527 public synchronized String getDBName() { 528 if (StringUtil.notNull(dbKey).equals("")) { 529 return "default"; 530 } 531 532 return dbKey; 533 } 534 535 536 546 public synchronized String getDataContext() { 547 if (StringUtil.notNull(dbKey).equals("")) { 548 return "default"; 549 } 550 551 return dbKey; 552 } 553 554 555 558 public static Schema getInstance() { 559 return myInstance; 560 } 561 562 568 public Enumeration getJobs() { 569 Vector theJobs = new Vector (); 570 String oneJobName = null; 571 572 for (Iterator ee = getDef().getJobs(); ee.hasNext();) { 573 oneJobName = (String ) ee.next(); 574 575 try { 576 Class clazz = ClassLocator.loadClass(oneJobName); 577 Job oneJob = (Job) clazz.newInstance(); 578 theJobs.addElement(oneJob); 579 } catch (Exception e) { 580 log.error("Unable to instantiate job '" + oneJobName + 581 "' belonging to schema '" + getClass().getName() + 582 "'", e); 583 } 584 } 585 586 587 return theJobs.elements(); 588 } 589 590 595 public Enumeration getMembers() { 596 Vector theDBObjects = new Vector (); 597 String oneDBObjectName = null; 598 DBObject oneDBObject = null; 599 600 boolean threadLoader = false; 601 602 if (this.getClass().getClassLoader() != null) { 603 threadLoader = true; 604 } 605 606 for (Iterator ee = getDef().getMembers(); ee.hasNext();) { 607 oneDBObjectName = (String ) ee.next(); 608 609 try { 610 oneDBObject = null; 611 Class clazz = null; 612 if (threadLoader == true) { 613 clazz = this.getClass().getClassLoader().loadClass(oneDBObjectName); 614 } else { 615 clazz = ClassLocator.loadClass(oneDBObjectName); 616 } 617 oneDBObject = (DBObject) clazz.newInstance(); 618 } catch (Exception e) { 619 log.error("Unable to instantiate dbobject '" + 620 oneDBObjectName + "'", e); 621 } 622 623 624 if (oneDBObject != null) { 625 626 if (getDataContext() != null) { 627 try { 628 oneDBObject.setDBName(getDataContext()); 629 } catch (DBException e) { 630 log.error("cannot set data context: ", e); 631 } 632 } 633 634 646 if (oneDBObject instanceof SecuredDBObject) { 647 if (getRequestingUser() != 0) { 648 ((SecuredDBObject) oneDBObject).setRequestingUid(getRequestingUser()); 649 } else { 650 ((SecuredDBObject) oneDBObject).setRequestingUid(SecuredDBObject.SYSTEM_ACCOUNT); 651 } 652 } 653 654 theDBObjects.addElement(oneDBObject); 655 } } 657 658 659 return theDBObjects.elements(); 660 } 661 662 671 public String getMessageBundlePath() { 672 return this.messageBundlePath; 673 } 674 675 681 public synchronized Vector getReports() { 682 Vector theReports = new Vector (); 683 String oneReportName = null; 684 ExpressoReport oneReport = null; 685 686 for (Iterator ee = getDef().getReports(); ee.hasNext();) { 687 oneReportName = (String ) ee.next(); 688 689 try { 690 Class clazz = ClassLocator.loadClass(oneReportName); 691 oneReport = (ExpressoReport) clazz.newInstance(); 692 } catch (Exception e) { 693 log.error("Unable to instantiate Expresso Report '" + 694 oneReportName + "'", e); 695 } 696 697 theReports.addElement(oneReport); 698 } 699 700 701 return theReports; 702 } 703 704 710 public Enumeration getServlets() { 711 Vector theServlets = new Vector (); 712 String oneServletName = null; 713 StdServlet oneServlet = null; 714 715 for (Iterator ee = getDef().getServlets(); ee.hasNext();) { 716 oneServletName = (String ) ee.next(); 717 718 try { 719 Class clazz = ClassLocator.loadClass(oneServletName); 720 oneServlet = (StdServlet) clazz.newInstance(); 721 theServlets.addElement(oneServlet); 722 } catch (Exception e) { 723 log.error("Unable to instantiate servlet '" + oneServletName + 724 "'", e); 725 } 726 } 727 728 729 return theServlets.elements(); 730 } 731 732 741 protected String getSetupDefault(String paramName, String defaultValue) { 742 try { 743 ConfigContext myContext = ConfigManager.getContext(getDataContext()); 744 ConfigSetupDefault oneValue = null; 745 746 for (Enumeration sv = myContext.getSetupDefaults().elements(); 747 sv.hasMoreElements();) { 748 oneValue = (ConfigSetupDefault) sv.nextElement(); 749 750 if (oneValue.getName().equals(paramName)) { 751 return oneValue.getValue(); 752 } 753 } 754 } catch (com.jcorporate.expresso.core.misc.ConfigurationException ce) { 755 log.error(ce); 756 } 757 758 return defaultValue; 759 } 760 761 768 public Controller getStartController() { 769 return null; 770 } 771 772 778 public String getSetupValue(String key) { 779 return (String ) setupValue.get(key); 780 } 781 782 788 public void setSetupValue(String key, String value) { 789 setupValue.put(key, value); 790 } 791 792 801 public synchronized void otherSetup(InstallLog installLog, String dataContext) 802 throws DBException { 803 } 804 805 806 816 public synchronized void otherSetup(String dbName) 817 throws DBException { 818 819 } 820 821 822 830 public synchronized void setDBName(String newOther) 831 throws DBException { 832 setDataContext(newOther); 833 } 834 835 842 public synchronized void setDataContext(String newOther) 843 throws DBException { 844 dbKey = newOther; 845 } 846 847 853 public synchronized void setupDefaultValues(String dbName) { 854 try { 855 setupDefaultValuesWithException(dbName); 856 } catch (DBException de) { 857 log.error("Unable to populate table with default values", de); 858 } 859 } 860 861 869 public synchronized void setupDefaultValuesWithException(String dbName) 870 throws DBException { 871 872 if (ExpressoRuntimeMap.getDefaultRuntime() != null) { 873 log.warn("Setup Values no longer apply in the Expresso Runtime context." + 874 " please add them to your Metadata for various values instead"); 875 } 876 877 DBObject oneMember = null; 878 879 for (Enumeration e = getMembers(); e.hasMoreElements();) { 880 oneMember = (DBObject) e.nextElement(); 881 if (log.isInfoEnabled()) { 882 log.info("Populating table " + oneMember.getDataContext()); 883 } 884 oneMember.setDataContext(dbName); 885 oneMember.populateDefaultValues(); 886 } 887 888 Controller oneController = null; 889 890 for (Iterator e = this.getControllerList().iterator(); e.hasNext();) { 891 oneController = (Controller) e.next(); 892 if (log.isInfoEnabled()) { 893 log.info("Populating Default Controller Data " + 894 oneController.getClass().getName()); 895 } 896 oneController.setupDefaultValues(dbName); 897 } 898 899 populateSchemaData(dbName); 900 } 901 902 903 910 public synchronized void populateSchemaData(String dbName) 911 throws DBException { 912 } 913 914 915 922 public Enumeration getTests() { 923 Vector v = new Vector (); 924 for (Iterator i = getDef().getTests(); i.hasNext();) { 925 v.add(i.next()); 926 } 927 return v.elements(); 928 } 929 930 935 private SchemaDefinition getDef() { 936 return (SchemaDefinition) schemaDefinitions.get(this.getClass().getName()); 937 } 938 939 944 public Hashtable getDBObjMap() { 945 return getDef().getDbobjMap(); 946 } 947 948 954 protected String getString(String stringCode) { 955 Object [] args = {}; 956 String language = null; 957 String country = null; 958 959 try { 960 ConfigContext myContext = ConfigManager.getContext(getDataContext()); 961 language = myContext.getLanguage(); 962 country = myContext.getCountry(); 963 } catch (com.jcorporate.expresso.core.misc.ConfigurationException ce) { 964 language = "en"; 965 country = "US"; 966 } 967 968 return Messages.getStringByPath(getMessageBundlePath(), language, 969 country, stringCode, args); 970 } 971 972 991 public String getVersion() { 992 if (this.getMetaData() != null) { 993 return this.getMetaData().getVersionNumber(); 994 } else { 995 return "No Version Defined"; 996 } 997 } 998 999 1010 protected void requiresVersion(String versionString, 1011 String schemaClassName) 1012 throws DBException { 1013 Schema otherSchema = instantiate(schemaClassName); 1014 1015 if (otherSchema.getVersion().equals(versionString)) { 1016 return; 1017 } 1018 1019 1020 1021 try { 1022 String foundVersionString = otherSchema.getVersion(); 1023 String requiredVersionString = versionString; 1024 1025 StringTokenizer stok1 = new StringTokenizer (foundVersionString, "."); 1026 StringTokenizer stok2 = new StringTokenizer (requiredVersionString, "."); 1027 1028 if (stok1.hasMoreTokens() && stok2.hasMoreTokens()) { 1029 int foundVersionNumbers[] = {0, 0, 0, 0}; 1030 int requiredVersionNumbers[] = {0, 0, 0, 0}; 1031 try { 1032 parseVersionString(stok1, foundVersionNumbers); 1033 parseVersionString(stok2, requiredVersionNumbers); 1034 1035 if (foundVersionNumbers[0] == requiredVersionNumbers[0]) { 1036 if (foundVersionNumbers[1] == requiredVersionNumbers[1]) { 1037 if (foundVersionNumbers[2] > requiredVersionNumbers[2]) { 1038 return; 1039 } else { 1040 if (log.isInfoEnabled()) { 1041 log.info("Schema '" + getClass().getName() + 1042 "', version " + getVersion() + 1043 " requires version " + versionString + 1044 " of schema '" + schemaClassName + 1045 "', but version " + otherSchema.getVersion() + 1046 " was found instead. You might encounter " + 1047 "some problems because of bugs being fixed. " + 1048 "It is recommended that you upgrade to the required version"); 1049 } 1050 return; 1051 1052 } 1053 1054 } else { 1055 log.warn("Schema '" + getClass().getName() + 1056 "', version " + getVersion() + 1057 " requires version " + versionString + 1058 " of schema '" + schemaClassName + 1059 "', but version " + otherSchema.getVersion() + 1060 " was found instead. You may encounter " + 1061 "some problems because of the minor version differences."); 1062 return; 1063 } 1064 1065 } else { 1066 log.error("Schema '" + getClass().getName() + 1067 "', version " + getVersion() + 1068 " requires version " + versionString + 1069 " of schema '" + schemaClassName + 1070 "', but version " + otherSchema.getVersion() + 1071 " was found instead. You may encounter " + 1072 "serious problems because of the major version differences."); 1073 return; 1074 } 1075 } catch (NumberFormatException ex) { 1076 log.error("Schema '" + getClass().getName() + 1077 "', version " + getVersion() + 1078 " requires version " + versionString + 1079 " of schema '" + schemaClassName + 1080 "', but version " + otherSchema.getVersion() + 1081 " was found instead."); 1082 return; 1083 } 1084 } else { 1085 if (stok1.hasMoreTokens()) { 1086 log.warn("Unable to find version information for :" + 1087 schemaClassName); 1088 } else { 1089 log.warn("Unable to find version information for :" + 1090 this.getClass().getName()); 1091 } 1092 1093 return; 1094 } 1095 } catch (Exception ne) { 1096 log.warn("Unable to convert version numbers to strings"); 1097 } 1098 1099 log.error("Schema '" + getClass().getName() + 1100 "', version " + getVersion() + 1101 " requires version " + versionString + 1102 " of schema '" + schemaClassName + 1103 "', but version " + otherSchema.getVersion() + 1104 " was found instead."); 1105 } 1106 1107 1115 private void parseVersionString(StringTokenizer tokenizer, int parsedNumbers[]) 1116 throws NumberFormatException { 1117 int index = 0; 1118 while (tokenizer.hasMoreTokens()) { 1119 String temp = tokenizer.nextToken(); 1120 if (temp.indexOf("-") > 0 && index == 2) { 1121 StringTokenizer releaseTokenizer = new StringTokenizer (temp, "-"); 1122 String buildNum = releaseTokenizer.nextToken(); 1123 String eaNum = releaseTokenizer.nextToken(); 1124 parsedNumbers[index] = Integer.parseInt(buildNum); 1125 index++; 1126 parsedNumbers[index] = Integer.parseInt(eaNum); 1127 index++; 1128 } else { 1129 parsedNumbers[index] = Integer.parseInt(temp); 1130 } 1131 index++; 1132 1133 if (index >= 4) { 1134 return; 1135 } 1136 } 1137 1138 } 1139 1140 1141 1148 public static Schema instantiate(String className) 1149 throws DBException { 1150 StringUtil.assertNotBlank(className, 1151 "Schema class name " + 1152 " may not be blank or null here"); 1153 1154 try { 1155 1156 Class c = ClassLocator.loadClass(className); 1157 return (Schema) c.newInstance(); 1158 } catch (ClassNotFoundException cn) { 1159 throw new DBException("Schema object '" + className + 1160 "' not found", cn); 1161 } catch (InstantiationException ie) { 1162 throw new DBException("Schema object '" + className + 1163 "' cannot be instantiated", ie); 1164 } catch (IllegalAccessException iae) { 1165 throw new DBException("llegal access loading " + 1166 "Schema object '" + className + "'. " + 1167 "Your schema must have a default public constructor", iae); 1168 } catch (java.lang.Throwable t) { 1169 t.printStackTrace(); 1170 throw new DBException("Error instantiating schema: " + className + ".", t); 1171 1172 } 1173 } 1174 1175 1182 public URL getMetadataLocation() { 1183 return Schema.class.getResource("Schema.xml"); 1184 } 1185 1186 1189 public void initialize() { 1190 this.dbKey = this.getParent().getMetaData().getName(); 1191 } 1192 1193 1198 public void configure(Configuration newConfig) throws ConfigurationException { 1199 this.setupValue = newConfig.getMappedProperties("SetupValue"); 1200 1201 for (Iterator i = this.defaultSetupValues.keySet().iterator(); i.hasNext();) { 1205 String key = (String ) i.next(); 1206 if (!setupValue.containsKey(key)) { 1207 setupValue.put(key, defaultSetupValues.get(key)); 1208 } 1209 } 1210 1211 this.defaultComponentCode = (String ) newConfig.get("DefaultComponentCode"); 1212 this.defaultDescription = (String ) newConfig.get("DefaultDescription"); 1213 this.messageBundlePath = (String ) newConfig.get("MessageBundlePath"); 1214 } 1215 1216 1217 1222 public void reconfigure(Configuration newConfig) throws ConfigurationException { 1223 synchronized (Schema.class) { 1224 this.setupValue = null; 1225 this.defaultComponentCode = null; 1226 this.defaultDescription = null; 1227 this.messageBundlePath = null; 1228 configure(newConfig); 1229 } 1230 } 1231 1232 public void destroy() { 1233 } 1235 1236 1245 public Controller getLoginController() throws ControllerException { 1246 String className = ConfigManager.getClassHandler(com.jcorporate 1247 .expresso.services.controller.LoginController.CLASS_HANDLER_NAME); 1248 if (className == null || className.length() == 0) { 1249 className = com.jcorporate.expresso.services.controller 1250 .LoginController.DEFAULT_CLASS_NAME; 1251 } 1252 1253 return ConfigManager.getControllerFactory().getController(className); 1254 } 1255 1256 1264 public Controller getRegistrationController() throws ControllerException { 1265 String className = ConfigManager.getClassHandler("registration"); 1266 if (className == null || className.length() == 0) { 1267 className = com.jcorporate.expresso.services 1268 .controller.SimpleRegistration.class.getName(); 1269 } 1270 1271 return ConfigManager.getControllerFactory().getController(className); 1272 } 1273 1274 1279 public void setRequestingUser(int uid) { 1280 mUserID = uid; 1281 } 1282 1283 1288 public int getRequestingUser() { 1289 return mUserID; 1290 } 1291 1292 1298 public boolean contains(DBObject dbObject) { 1299 SchemaDefinition def = getDef(); 1300 return def.contains(dbObject); 1301 } 1302 1303 1304} 1305 | Popular Tags |