1 10 11 package com.triactive.jdo; 12 13 import java.sql.Connection ; 14 import java.util.ArrayList ; 15 import java.util.Arrays ; 16 import java.util.Collection ; 17 import java.util.Collections ; 18 import java.util.Enumeration ; 19 import java.util.HashMap ; 20 import java.util.HashSet ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Map ; 24 import java.util.Properties ; 25 import java.util.Set ; 26 import javax.jdo.JDOUnsupportedOptionException; 27 import javax.jdo.JDOUserException; 28 import javax.jdo.PersistenceManager; 29 import javax.jdo.PersistenceManagerFactory; 30 import javax.jdo.spi.JDOPermission; 31 import javax.naming.InitialContext ; 32 import javax.naming.NamingException ; 33 import javax.sql.DataSource ; 34 import org.apache.log4j.Category; 35 36 37 43 44 public class PersistenceManagerFactoryImpl implements PersistenceManagerFactory 45 { 46 private static final Category LOG = Category.getInstance(PersistenceManagerFactoryImpl.class); 47 48 53 public static final String VALIDATE_TABLES_PROPERTY = "com.triactive.jdo.validateTables"; 54 55 60 public static final String VALIDATE_CONSTRAINTS_PROPERTY = "com.triactive.jdo.validateConstraints"; 61 62 67 public static final String AUTO_CREATE_TABLES_PROPERTY = "com.triactive.jdo.autoCreateTables"; 68 69 74 public static final String TRANSACTION_ISOLATION_PROPERTY = "com.triactive.jdo.transactionIsolation"; 75 76 77 81 public interface PropertySetter 82 { 83 88 public void set(PersistenceManagerFactoryImpl pmf, String value); 89 } 90 91 94 private static final Map PROPERTY_SETTERS = initPropertySetters(); 95 96 97 private String driverName = null; 98 private String URL = null; 99 private String userName = null; 100 private String password = null; 101 102 private Object connectionFactory = null; 103 private String connectionFactoryName = null; 104 105 private Object connectionFactory2 = null; 106 private String connectionFactory2Name = null; 107 108 private boolean multithreaded = false; 109 private boolean optimistic = false; 110 private boolean retainValues = false; 111 private boolean restoreValues = false; 112 private boolean nontransactionalRead = false; 113 private boolean nontransactionalWrite = false; 114 private boolean ignoreCache = false; 115 private boolean validateTables = new Boolean (System.getProperty(VALIDATE_TABLES_PROPERTY, "true")).booleanValue(); 116 private boolean validateConstraints = new Boolean (System.getProperty(VALIDATE_CONSTRAINTS_PROPERTY, "true")).booleanValue(); 117 private boolean autoCreateTables = new Boolean (System.getProperty(AUTO_CREATE_TABLES_PROPERTY, "false")).booleanValue(); 118 private int isolationLevel = Connection.TRANSACTION_SERIALIZABLE; 119 120 private int minPool = 3; 121 private int maxPool = 100; 122 private int msWait = 30000; 123 124 128 private transient boolean configurable = true; 129 private transient DataSource tds = null; 130 private transient DataSource ntds = null; 131 132 136 private transient Set openPMs = new HashSet (); 137 138 139 142 143 public PersistenceManagerFactoryImpl() 144 { 145 String tip = System.getProperty(TRANSACTION_ISOLATION_PROPERTY); 146 147 if (tip != null) 148 { 149 try 150 { 151 setTransactionIsolation(tip); 152 } 153 catch (IllegalArgumentException e) 154 { 155 LOG.warn("Invalid transaction isolation property ignored: " + TRANSACTION_ISOLATION_PROPERTY + "=" + tip); 156 } 157 } 158 } 159 160 161 169 public synchronized static PersistenceManagerFactory getPersistenceManagerFactory(Properties props) 170 { 171 PersistenceManagerFactoryImpl pmf = new PersistenceManagerFactoryImpl(); 172 173 pmf.setOptions(props); 175 176 return pmf; 177 } 178 179 180 public synchronized void close() 181 { 182 if (openPMs == null) 183 return; 184 185 SecurityManager secmgr = System.getSecurityManager(); 186 if (secmgr != null) 187 secmgr.checkPermission(JDOPermission.CLOSE_PERSISTENCE_MANAGER_FACTORY); 188 189 List nestedEx = new ArrayList (); 190 Iterator i = openPMs.iterator(); 191 192 while (i.hasNext()) 193 { 194 PersistenceManager pm = (PersistenceManager)i.next(); 195 196 if (pm.currentTransaction().isActive()) 197 nestedEx.add(new JDOUserException("PersistenceManager has an active transaction", pm)); 198 } 199 200 if (!nestedEx.isEmpty()) 201 { 202 Throwable [] nested = (Throwable [])nestedEx.toArray(new Throwable [nestedEx.size()]); 203 throw new JDOUserException("One or more PersistenceManagers have an active transaction", nested); 204 } 205 206 i = openPMs.iterator(); 207 208 while (i.hasNext()) 209 ((PersistenceManagerImpl)i.next()).forceClose(); 210 211 configurable = false; 212 openPMs = null; 213 } 214 215 216 public synchronized boolean equals(Object obj) 217 { 218 if (obj == this) 219 return true; 220 221 if (!(obj instanceof PersistenceManagerFactoryImpl)) 222 return false; 223 224 PersistenceManagerFactoryImpl pmf = (PersistenceManagerFactoryImpl)obj; 225 226 if (driverName == null) { if (pmf.driverName != null) return false; } 227 else if (!driverName.equals(pmf.driverName)) return false; 228 229 if (URL == null) { if (pmf.URL != null) return false; } 230 else if (!URL.equals(pmf.URL)) return false; 231 232 if (userName == null) { if (pmf.userName != null) return false; } 233 else if (!userName.equals(pmf.userName)) return false; 234 235 if (password == null) { if (pmf.password != null) return false; } 236 else if (!password.equals(pmf.password)) return false; 237 238 if (connectionFactory == null) { if (pmf.connectionFactory != null) return false; } 239 else if (!connectionFactory.equals(pmf.connectionFactory)) return false; 240 241 if (connectionFactoryName == null) { if (pmf.connectionFactoryName != null) return false; } 242 else if (!connectionFactoryName.equals(pmf.connectionFactoryName)) return false; 243 244 if (connectionFactory2 == null) { if (pmf.connectionFactory2 != null) return false; } 245 else if (!connectionFactory2.equals(pmf.connectionFactory2)) return false; 246 247 if (connectionFactory2Name == null) { if (pmf.connectionFactory2Name != null) return false; } 248 else if (!connectionFactory2Name.equals(pmf.connectionFactory2Name)) return false; 249 250 return multithreaded == pmf.multithreaded 251 && optimistic == pmf.optimistic 252 && retainValues == pmf.retainValues 253 && restoreValues == pmf.restoreValues 254 && nontransactionalRead == pmf.nontransactionalRead 255 && nontransactionalWrite == pmf.nontransactionalWrite 256 && ignoreCache == pmf.ignoreCache 257 && validateTables == pmf.validateTables 258 && validateConstraints == pmf.validateConstraints 259 && autoCreateTables == pmf.autoCreateTables 260 && minPool == pmf.minPool 261 && maxPool == pmf.maxPool 262 && msWait == pmf.msWait; 263 } 264 265 public synchronized int hashCode() 266 { 267 return (driverName == null ? 0 : driverName.hashCode()) 268 ^ (URL == null ? 0 : URL.hashCode()) 269 ^ (userName == null ? 0 : userName.hashCode()) 270 ^ (password == null ? 0 : password.hashCode()) 271 ^ (connectionFactory == null ? 0 : connectionFactory.hashCode()) 272 ^ (connectionFactoryName == null ? 0 : connectionFactoryName.hashCode()) 273 ^ (connectionFactory2 == null ? 0 : connectionFactory2.hashCode()) 274 ^ (connectionFactory2Name == null ? 0 : connectionFactory2Name.hashCode()) 275 ^ (multithreaded ? 1 : 0) 276 ^ (optimistic ? 1 : 0) 277 ^ (retainValues ? 1 : 0) 278 ^ (restoreValues ? 1 : 0) 279 ^ (nontransactionalRead ? 1 : 0) 280 ^ (nontransactionalWrite ? 1 : 0) 281 ^ (ignoreCache ? 1 : 0) 282 ^ (validateTables ? 1 : 0) 283 ^ (validateConstraints ? 1 : 0) 284 ^ (autoCreateTables ? 1 : 0) 285 ^ minPool 286 ^ maxPool 287 ^ msWait; 288 } 289 290 291 295 private static final Map initPropertySetters() 296 { 297 final Map map = new HashMap (); 298 map.put("javax.jdo.option.Optimistic", 299 new PropertySetter() 300 { 301 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setOptimistic(Boolean.valueOf(s).booleanValue()); } 302 }); 303 map.put("javax.jdo.option.RetainValues", 304 new PropertySetter() 305 { 306 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setRetainValues(Boolean.valueOf(s).booleanValue()); } 307 }); 308 map.put("javax.jdo.option.RestoreValues", 309 new PropertySetter() 310 { 311 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setRestoreValues(Boolean.valueOf(s).booleanValue()); } 312 }); 313 map.put("javax.jdo.option.IgnoreCache", 314 new PropertySetter() 315 { 316 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setIgnoreCache(Boolean.valueOf(s).booleanValue()); } 317 }); 318 map.put("javax.jdo.option.NontransactionalRead", 319 new PropertySetter() 320 { 321 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setNontransactionalRead(Boolean.valueOf(s).booleanValue()); } 322 }); 323 map.put("javax.jdo.option.NontransactionalWrite", 324 new PropertySetter() 325 { 326 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setNontransactionalWrite(Boolean.valueOf(s).booleanValue()); } 327 }); 328 map.put("javax.jdo.option.Multithreaded", 329 new PropertySetter() 330 { 331 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setMultithreaded(Boolean.valueOf(s).booleanValue()); } 332 }); 333 map.put("javax.jdo.option.ConnectionUserName", 334 new PropertySetter() 335 { 336 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setConnectionUserName(s); } 337 }); 338 map.put("javax.jdo.option.ConnectionPassword", 339 new PropertySetter() 340 { 341 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setConnectionPassword(s); } 342 }); 343 map.put("javax.jdo.option.ConnectionDriverName", 344 new PropertySetter() 345 { 346 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setConnectionDriverName(s); } 347 }); 348 map.put("javax.jdo.option.ConnectionURL", 349 new PropertySetter() 350 { 351 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setConnectionURL(s); } 352 }); 353 map.put("javax.jdo.option.ConnectionFactoryName", 354 new PropertySetter() 355 { 356 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setConnectionFactoryName(s); } 357 }); 358 map.put("javax.jdo.option.ConnectionFactory2Name", 359 new PropertySetter() 360 { 361 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setConnectionFactory2Name(s); } 362 }); 363 map.put(VALIDATE_TABLES_PROPERTY, 364 new PropertySetter() 365 { 366 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setValidateTables(Boolean.valueOf(s).booleanValue()); } 367 }); 368 map.put(VALIDATE_CONSTRAINTS_PROPERTY, 369 new PropertySetter() 370 { 371 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setValidateConstraints(Boolean.valueOf(s).booleanValue()); } 372 }); 373 map.put(AUTO_CREATE_TABLES_PROPERTY, 374 new PropertySetter() 375 { 376 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setAutoCreateTables(Boolean.valueOf(s).booleanValue()); } 377 }); 378 map.put(TRANSACTION_ISOLATION_PROPERTY, 379 new PropertySetter() 380 { 381 public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setTransactionIsolation(s); } 382 }); 383 return map; 384 } 385 386 387 390 391 private void assertConfigurable() 392 { 393 if (!configurable) 394 throw new JDOUserException("Configuration changes not allowed after PersistenceManagers have been generated"); 395 } 396 397 398 401 402 private void assertNotClosed() 403 { 404 if (openPMs == null) 405 throw new JDOUserException("PersistenceManagerFactory has been closed"); 406 } 407 408 409 421 422 private DataSource lookupDataSource(String name) 423 { 424 Object obj; 425 426 try 427 { 428 obj = new InitialContext ().lookup(name); 429 } 430 catch (NamingException e) 431 { 432 throw new ConnectionFactoryNotFoundException(name, e); 433 } 434 435 if (!(obj instanceof DataSource )) 436 throw new UnsupportedConnectionFactoryException(obj); 437 438 return (DataSource )obj; 439 } 440 441 442 448 449 private void freezeConfiguration() 450 { 451 if (configurable) 452 { 453 if (connectionFactory != null) 454 { 455 if (!(connectionFactory instanceof DataSource )) 456 throw new UnsupportedConnectionFactoryException(connectionFactory); 457 458 tds = (DataSource )connectionFactory; 459 } 460 else if (connectionFactoryName != null) 461 tds = lookupDataSource(connectionFactoryName); 462 else 463 tds = new DriverManagerDataSource(driverName, URL); 464 465 if (connectionFactory2 != null) 466 { 467 if (!(connectionFactory2 instanceof DataSource )) 468 throw new UnsupportedConnectionFactoryException(connectionFactory2); 469 470 ntds = (DataSource )connectionFactory2; 471 } 472 else if (connectionFactory2Name != null) 473 ntds = lookupDataSource(connectionFactory2Name); 474 else 475 ntds = tds; 476 477 configurable = false; 478 } 479 } 480 481 482 486 private void setOptions(Properties props) 487 { 488 for (Enumeration e=props.propertyNames(); e.hasMoreElements(); ) 489 { 490 String prop = (String )e.nextElement(); 491 492 PropertySetter setter = (PropertySetter)PROPERTY_SETTERS.get(prop); 493 if (null != prop && null != setter) 494 { 495 String value = props.getProperty(prop); 496 setter.set(this, value); 497 } 498 } 499 } 500 501 502 507 508 public synchronized DataSource getTransactionalDataSource() 509 { 510 freezeConfiguration(); 511 512 return tds; 513 } 514 515 516 521 522 public synchronized DataSource getNontransactionalDataSource() 523 { 524 freezeConfiguration(); 525 526 return ntds; 527 } 528 529 530 539 540 public synchronized PersistenceManager getPersistenceManager() 541 { 542 return getPersistenceManager(userName, password); 543 } 544 545 546 560 561 public synchronized PersistenceManager getPersistenceManager(String userName, String password) 562 { 563 assertNotClosed(); 564 freezeConfiguration(); 565 566 PersistenceManagerImpl pm = new PersistenceManagerImpl(this, userName, password); 567 568 openPMs.add(pm); 569 570 return pm; 571 } 572 573 574 synchronized void pmClosed(PersistenceManagerImpl pm) 575 { 576 if (openPMs != null) 577 openPMs.remove(pm); 578 } 579 580 581 585 586 public synchronized void setConnectionUserName(String userName) 587 { 588 assertConfigurable(); 589 this.userName = userName; 590 } 591 592 593 597 598 public String getConnectionUserName() 599 { 600 return userName; 601 } 602 603 604 608 609 public synchronized void setConnectionPassword(String password) 610 { 611 assertConfigurable(); 612 this.password = password; 613 } 614 615 616 620 621 public synchronized void setConnectionURL(String URL) 622 { 623 assertConfigurable(); 624 this.URL = URL; 625 } 626 627 628 632 633 public String getConnectionURL() 634 { 635 return URL; 636 } 637 638 639 643 644 public synchronized void setConnectionDriverName(String driverName) 645 { 646 assertConfigurable(); 647 this.driverName = driverName; 648 } 649 650 651 655 656 public String getConnectionDriverName() 657 { 658 return driverName; 659 } 660 661 662 666 667 public synchronized void setConnectionFactoryName(String connectionFactoryName) 668 { 669 assertConfigurable(); 670 this.connectionFactoryName = connectionFactoryName; 671 } 672 673 674 678 679 public String getConnectionFactoryName() 680 { 681 return connectionFactoryName; 682 } 683 684 685 691 692 public synchronized void setConnectionFactory(Object connectionFactory) 693 { 694 assertConfigurable(); 695 this.connectionFactory = connectionFactory; 696 } 697 698 699 703 704 public Object getConnectionFactory() 705 { 706 return connectionFactory; 707 } 708 709 710 716 717 public synchronized void setConnectionFactory2Name(String connectionFactory2Name) 718 { 719 assertConfigurable(); 720 this.connectionFactory2Name = connectionFactory2Name; 721 } 722 723 724 730 731 public String getConnectionFactory2Name() 732 { 733 return connectionFactory2Name; 734 } 735 736 737 745 746 public synchronized void setConnectionFactory2(Object connectionFactory2) 747 { 748 assertConfigurable(); 749 this.connectionFactory2 = connectionFactory2; 750 } 751 752 753 759 760 public Object getConnectionFactory2() 761 { 762 return connectionFactory2; 763 } 764 765 766 772 773 public synchronized void setMultithreaded(boolean flag) 774 { 775 assertConfigurable(); 776 777 multithreaded = flag; 778 } 779 780 781 787 788 public boolean getMultithreaded() 789 { 790 return multithreaded; 791 } 792 793 794 800 801 public synchronized void setOptimistic(boolean flag) 802 { 803 assertConfigurable(); 804 805 optimistic = flag; 806 807 if (flag) 808 nontransactionalRead = flag; 809 } 810 811 812 818 819 public boolean getOptimistic() 820 { 821 return optimistic; 822 } 823 824 825 831 832 public synchronized void setRetainValues(boolean flag) 833 { 834 assertConfigurable(); 835 retainValues = flag; 836 837 if (flag) 838 nontransactionalRead = flag; 839 } 840 841 842 848 849 public boolean getRetainValues() 850 { 851 return retainValues; 852 } 853 854 855 861 862 public synchronized void setRestoreValues(boolean flag) 863 { 864 assertConfigurable(); 865 restoreValues = flag; 866 } 867 868 869 875 876 public boolean getRestoreValues() 877 { 878 return restoreValues; 879 } 880 881 882 888 889 public synchronized void setNontransactionalRead(boolean flag) 890 { 891 assertConfigurable(); 892 nontransactionalRead = flag; 893 } 894 895 896 902 903 public boolean getNontransactionalRead() 904 { 905 return nontransactionalRead; 906 } 907 908 909 915 916 public synchronized void setNontransactionalWrite(boolean flag) 917 { 918 assertConfigurable(); 919 nontransactionalWrite = flag; 920 } 921 922 923 929 930 public boolean getNontransactionalWrite() 931 { 932 return nontransactionalWrite; 933 } 934 935 936 942 943 public synchronized void setIgnoreCache(boolean flag) 944 { 945 assertConfigurable(); 946 ignoreCache = flag; 947 } 948 949 950 956 957 public boolean getIgnoreCache() 958 { 959 return ignoreCache; 960 } 961 962 963 968 969 public synchronized void setMaxPool(int maxPool) 970 { 971 assertConfigurable(); 972 this.maxPool = maxPool; 973 } 974 975 976 981 982 public int getMaxPool() 983 { 984 return maxPool; 985 } 986 987 988 993 994 public synchronized void setMinPool(int minPool) 995 { 996 assertConfigurable(); 997 this.minPool = minPool; 998 } 999 1000 1001 1006 1007 public int getMinPool() 1008 { 1009 return minPool; 1010 } 1011 1012 1013 1018 1019 public synchronized void setMsWait(int msWait) 1020 { 1021 assertConfigurable(); 1022 this.msWait = msWait; 1023 } 1024 1025 1026 1031 1032 public int getMsWait() 1033 { 1034 return msWait; 1035 } 1036 1037 1038 1044 1045 public synchronized void setValidateTables(boolean flag) 1046 { 1047 assertConfigurable(); 1048 validateTables = flag; 1049 } 1050 1051 1052 1058 1059 public boolean getValidateTables() 1060 { 1061 return validateTables; 1062 } 1063 1064 1065 1071 1072 public synchronized void setValidateConstraints(boolean flag) 1073 { 1074 assertConfigurable(); 1075 validateConstraints = flag; 1076 } 1077 1078 1079 1085 1086 public boolean getValidateConstraints() 1087 { 1088 return validateConstraints; 1089 } 1090 1091 1092 1098 1099 public synchronized void setAutoCreateTables(boolean flag) 1100 { 1101 assertConfigurable(); 1102 autoCreateTables = flag; 1103 } 1104 1105 1106 1112 1113 public boolean getAutoCreateTables() 1114 { 1115 return autoCreateTables; 1116 } 1117 1118 1119 1129 1130 private synchronized void setTransactionIsolation(String isolationLevelName) 1131 { 1132 assertConfigurable(); 1133 1134 String iln = isolationLevelName.trim().replace(' ', '_').toUpperCase(); 1135 1136 if (iln.equals("READ_UNCOMMITTED")) 1137 isolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED; 1138 else if (iln.equals("READ_COMMITTED")) 1139 isolationLevel = Connection.TRANSACTION_READ_COMMITTED; 1140 else if (iln.equals("REPEATABLE_READ")) 1141 isolationLevel = Connection.TRANSACTION_REPEATABLE_READ; 1142 else if (iln.equals("SERIALIZABLE")) 1143 isolationLevel = Connection.TRANSACTION_SERIALIZABLE; 1144 else 1145 throw new IllegalArgumentException ("Illegal isolation level: " + isolationLevelName); 1146 } 1147 1148 1149 1155 1156 public synchronized void setTransactionIsolation(int isolationLevel) 1157 { 1158 assertConfigurable(); 1159 1160 switch (isolationLevel) 1161 { 1162 case Connection.TRANSACTION_READ_UNCOMMITTED: 1163 case Connection.TRANSACTION_READ_COMMITTED: 1164 case Connection.TRANSACTION_REPEATABLE_READ: 1165 case Connection.TRANSACTION_SERIALIZABLE: 1166 break; 1167 1168 default: 1169 throw new IllegalArgumentException ("Illegal isolation level: " + isolationLevel); 1170 } 1171 1172 this.isolationLevel = isolationLevel; 1173 } 1174 1175 1176 1182 1183 public int getTransactionIsolation() 1184 { 1185 return isolationLevel; 1186 } 1187 1188 1189 1196 1197 public Properties getProperties() 1198 { 1199 Properties props = new Properties (); 1200 1201 props.setProperty("VendorName", "TriActive"); 1202 props.setProperty("VersionNumber", "$Name: TJDO_2_1 $"); 1203 1204 return props; 1205 } 1206 1207 1208 1246 1247 public Collection supportedOptions() 1248 { 1249 return Collections.unmodifiableList(Arrays.asList(optionArray)); 1250 } 1251 1252 private static final String [] optionArray = 1253 { 1254 "javax.jdo.option.TransientTransactional", 1255 "javax.jdo.option.NontransactionalRead", 1256 "javax.jdo.option.RetainValues", 1257 "javax.jdo.option.DatastoreIdentity", 1258 "javax.jdo.option.NonDatastoreIdentity", 1259 "javax.jdo.option.HashMap", 1260 "javax.jdo.option.Map", 1261 "javax.jdo.query.JDOQL", 1262 "javax.jdo.query.TJDOSQL" 1263 }; 1264} 1265 | Popular Tags |