1 23 24 29 30 package com.sun.jdo.spi.persistence.support.ejb.ejbc; 31 32 import java.io.BufferedInputStream ; 33 import java.io.File ; 34 import java.io.FileInputStream ; 35 import java.io.FileOutputStream ; 36 import java.io.OutputStream ; 37 import java.io.InputStream ; 38 import java.io.IOException ; 39 40 import java.util.Iterator ; 41 import java.util.Map ; 42 import java.util.Properties ; 43 import java.util.ResourceBundle ; 44 import java.util.Set ; 45 import java.util.HashSet ; 46 import java.util.HashMap ; 47 import java.util.List ; 48 import java.util.LinkedList ; 49 50 import java.sql.Connection ; 51 import java.sql.DatabaseMetaData ; 52 import java.sql.SQLException ; 53 54 import com.sun.ejb.codegen.EjbcContext; 55 import com.sun.ejb.codegen.GeneratorException; 56 57 import com.sun.enterprise.deployment.EjbBundleDescriptor; 58 import com.sun.enterprise.deployment.ResourceReferenceDescriptor; 59 60 import com.sun.enterprise.deployment.backend.DeploymentStatus; 61 62 import com.sun.enterprise.server.Constants; 63 64 import com.sun.jdo.api.persistence.mapping.ejb.beans.EntityMapping; 65 import com.sun.jdo.api.persistence.mapping.ejb.beans.CmpFieldMapping; 66 import com.sun.jdo.api.persistence.mapping.ejb.beans.CmrFieldMapping; 67 import com.sun.jdo.api.persistence.mapping.ejb.beans.ColumnPair; 68 import com.sun.jdo.api.persistence.mapping.ejb.beans.SunCmpMapping; 69 import com.sun.jdo.api.persistence.mapping.ejb.beans.SunCmpMappings; 70 71 import com.sun.jdo.api.persistence.mapping.ejb.ConversionHelper; 72 import com.sun.jdo.api.persistence.mapping.ejb.ConversionException; 73 import com.sun.jdo.api.persistence.mapping.ejb.MappingFile; 74 import com.sun.jdo.api.persistence.mapping.ejb.AbstractNameMapper; 75 76 import com.sun.jdo.api.persistence.model.Model; 77 import com.sun.jdo.api.persistence.model.ModelException; 78 79 import com.sun.jdo.api.persistence.model.mapping.MappingClassElement; 80 81 import com.sun.jdo.spi.persistence.utility.StringHelper; 82 import com.sun.jdo.spi.persistence.utility.I18NHelper; 83 import com.sun.jdo.spi.persistence.utility.logging.Logger; 84 import com.sun.jdo.spi.persistence.utility.database.DBVendorTypeHelper; 85 import com.sun.jdo.spi.persistence.utility.database.DatabaseConstants; 86 87 import com.sun.jdo.spi.persistence.support.sqlstore.ejb.DeploymentHelper; 88 89 import com.sun.jdo.spi.persistence.generator.database.DatabaseGenerator; 90 91 import org.netbeans.modules.dbschema.DBException; 92 import org.netbeans.modules.dbschema.DBIdentifier; 93 import org.netbeans.modules.dbschema.SchemaElement; 94 import org.netbeans.modules.dbschema.jdbcimpl.ConnectionProvider; 95 import org.netbeans.modules.dbschema.jdbcimpl.SchemaElementImpl; 96 import org.netbeans.modules.dbschema.util.NameUtil; 97 98 import org.netbeans.modules.schema2beans.Schema2BeansException; 99 import org.netbeans.modules.schema2beans.ValidateException; 100 101 109 public class MappingGenerator extends 110 com.sun.jdo.api.persistence.mapping.ejb.MappingGenerator { 111 112 public static final String JAVA_TO_DB_FLAG = DatabaseConstants.JAVA_TO_DB_FLAG; 115 116 private static final String DBSCHEMA_EXTENSION = ".dbschema"; private static final char DOT = '.'; 119 120 private static final Logger logger = LogHelperEJBCompiler.getLogger(); 121 122 private final EjbBundleDescriptor bundle; 123 124 private String dbVendorName = null; 125 private boolean isJavaToDatabaseFlag = false; 126 private boolean isVerifyFlag = false; 127 128 131 private final static ResourceBundle messages = I18NHelper.loadBundle( 132 MappingGenerator.class); 133 134 142 public MappingGenerator(EjbBundleDescriptor bundle, Model model, 143 NameMapper nameMapper, ClassLoader loader) { 144 super(new EJBBundleInfoHelper(bundle, nameMapper, model, null), loader, false); 145 this.bundle = bundle; 146 } 147 148 169 public SchemaElement generateMapping( 170 EjbcContext ejbcContext, String inputFilesPath, 171 String generatedXmlsPath, File classout, 172 boolean ignoreSunDeploymentDescriptors) 173 throws IOException , DBException, ModelException, 174 Schema2BeansException, SQLException , GeneratorException, 175 ConversionException { 176 177 SchemaElement schema = null; 178 if (ejbcContext == null) 179 isVerifyFlag = true; 180 181 File cmpMappingFile = getSunCmpMappingFile(inputFilesPath); 182 boolean mappedBeans = !ignoreSunDeploymentDescriptors 183 && cmpMappingFile.exists(); 184 ResourceReferenceDescriptor cmpResource = checkOrCreateCMPResource( 185 mappedBeans); 186 187 isJavaToDatabaseFlag = DeploymentHelper.isJavaToDatabase( 189 cmpResource.getSchemaGeneratorProperties()); 190 191 boolean mustHaveDBVendorName = 194 !mappedBeans || (mappedBeans && isJavaToDatabaseFlag); 195 196 Results deploymentArguments = getDeploymentArguments( 199 ejbcContext, cmpResource, mustHaveDBVendorName); 200 dbVendorName = deploymentArguments.getDatabaseVendorName(); 201 202 if (mappedBeans) { 203 206 if (!isVerifyFlag) { 208 String warning = null; 210 if (isJavaToDatabaseFlag) { 211 212 if (deploymentArguments.hasUniqueTableNames()) { 218 warning = 219 I18NHelper.getMessage( 220 messages, 221 "EXC_DisallowJava2DBUniqueTableNames", bundle.getApplication().getRegistrationName(), 223 JDOCodeGeneratorHelper.getModuleName(bundle)); 224 logger.warning(warning); 225 } 226 } else if (deploymentArguments.hasJavaToDatabaseArgs()) { 227 228 warning = 232 I18NHelper.getMessage( 233 messages, 234 "EXC_DisallowJava2DBCLIOverrides", bundle.getApplication().getRegistrationName(), 236 JDOCodeGeneratorHelper.getModuleName(bundle)); 237 logger.warning(warning); 238 } 239 240 if (warning != null) { 241 DeploymentStatus status = 242 ejbcContext.getDeploymentRequest() 243 .getCurrentDeploymentStatus(); 244 status.setStageStatus(DeploymentStatus.WARNING); 245 String msg = status.getStageStatusMessage(); 246 msg = (msg == null) ? warning : (msg + "\n" + warning); status.setStageStatusMessage(msg); 248 } 249 } 250 251 SunCmpMappings sunCmpMappings = getSunCmpMappings(cmpMappingFile); 253 254 ensureDBSchemaExistence(cmpResource, sunCmpMappings, inputFilesPath, 257 classout); 258 259 Map mappingClasses = loadMappingClasses(sunCmpMappings, getClassLoader()); 261 262 MappingClassElement mc = null; 269 Iterator iter = mappingClasses.values().iterator(); 270 while (iter.hasNext()) { 271 mc = (MappingClassElement)iter.next(); 272 if (mc != null) { 273 schema = SchemaElement.forName(mc.getDatabaseRoot()); 274 break; 275 } 276 } 277 278 if (logger.isLoggable(Logger.FINE)){ 279 logger.fine("Loaded mapped beans for " + cmpResource.getJndiName() 281 + ", isJavaToDatabase=" + isJavaToDatabaseFlag); } 283 } 284 else { 285 DatabaseGenerator.Results results = generateMappingClasses( 289 dbVendorName, deploymentArguments.getUseUniqueTableNames(), 290 deploymentArguments.getUserPolicy(), inputFilesPath); 291 292 if (!isVerifyFlag) { 294 writeSunCmpMappingFile(results.getMappingClasses(), 297 getSunCmpMappingFile(generatedXmlsPath)); 298 299 schema = results.getSchema(); 300 301 writeSchemaFile(schema, classout); 303 304 setJavaToDatabase(cmpResource, true); 305 } 306 } 307 308 return schema; 309 } 310 311 public String getDatabaseVendorName() { 312 return dbVendorName; 313 } 314 315 319 public boolean isJavaToDatabase() { 320 return isJavaToDatabaseFlag; 321 } 322 323 328 private void setJavaToDatabase(ResourceReferenceDescriptor 329 cmpResource, boolean value) { 330 331 if (logger.isLoggable(Logger.FINE)) { 332 logger.fine("set javatodb flag to " + value + " in cmpResource"); } 334 335 Properties schemaGeneratorProperties = cmpResource. 336 getSchemaGeneratorProperties(); 337 if (schemaGeneratorProperties == null) { 338 schemaGeneratorProperties = new Properties (); 339 cmpResource.setSchemaGeneratorProperties(schemaGeneratorProperties); 340 } 341 342 schemaGeneratorProperties.setProperty(DatabaseConstants.JAVA_TO_DB_FLAG, 343 String.valueOf(value)); 344 345 isJavaToDatabaseFlag = value; 346 } 347 348 355 private SunCmpMappings getSunCmpMappings(File cmpMappingFile) 356 throws IOException , Schema2BeansException, GeneratorException { 357 InputStream is = null; 358 BufferedInputStream iasMapping = null; 359 SunCmpMappings sunCmpMapping = null; 360 361 if (cmpMappingFile.length() == 0) { 362 throw JDOCodeGeneratorHelper.createGeneratorException( 363 "CMG.BeansFileSizeIsZero", bundle); } 365 366 try { 367 is = new FileInputStream (cmpMappingFile); 368 iasMapping = new BufferedInputStream (is); 369 sunCmpMapping = SunCmpMappings.createGraph(iasMapping); 370 } catch (IOException ex) { 371 throw ex; 372 } finally { 373 if (is != null) { 374 try { 375 is.close(); 376 } catch(Exception ex) { 377 if (logger.isLoggable(Logger.FINE)) 378 logger.fine(ex.toString()); 379 } 380 } 381 if (iasMapping != null) { 382 try { 383 iasMapping.close(); 384 } catch(Exception ex) { 385 if (logger.isLoggable(Logger.FINE)) 386 logger.fine(ex.toString()); 387 } 388 } 389 } 390 391 try { 392 sunCmpMapping.validate(); 393 } catch (ValidateException ex) { 394 throw JDOCodeGeneratorHelper.createGeneratorException( 395 "CMG.InvalidSunCmpMappingsFile", bundle, ex); } 397 398 return sunCmpMapping; 399 } 400 401 406 private static File getSunCmpMappingFile(String filesPath) { 407 String cmpMappingFile = (new StringBuffer (filesPath). 408 append(File.separator). 409 append(MappingFile.DEFAULT_LOCATION_IN_EJB_JAR)).toString(); 410 411 if (cmpMappingFile.lastIndexOf(File.separatorChar) != -1) { 414 String dirs = cmpMappingFile.substring( 415 0, cmpMappingFile.lastIndexOf(File.separatorChar)); 416 File fileDirs = new File (dirs); 417 if (!fileDirs.exists()) 418 fileDirs.mkdirs(); 419 } 420 421 return new File (cmpMappingFile); 422 } 423 424 425 433 private void writeSunCmpMappingFile(Set mappingClasses, File cmpMappingFile) 434 throws IOException , ConversionException, Schema2BeansException { 435 Map mappingMap = new HashMap (); 440 AbstractNameMapper nameMapper = getNameMapper(); 441 Iterator iter = mappingClasses.iterator(); 442 while (iter.hasNext()) { 443 MappingClassElement mappingClass = (MappingClassElement)iter.next(); 444 String ejbName = nameMapper.getEjbNameForPersistenceClass( 445 mappingClass.getName()); 446 mappingMap.put(ejbName, mappingClass); 447 } 448 MappingFile mf = new MappingFile(); 449 OutputStream sunCmpMapping = null; 450 try { 451 sunCmpMapping = new FileOutputStream ( 452 cmpMappingFile); 453 mf.fromMappingClasses(sunCmpMapping, mappingMap, 454 getConversionHelper()); 455 } catch (IOException ex) { 456 throw ex; 457 } finally { 458 try { 459 if (sunCmpMapping != null) { 460 sunCmpMapping.close(); 461 } 462 } catch (IOException ex) { 463 if (logger.isLoggable(Logger.FINE)) 464 logger.fine(ex.toString()); 465 } 466 } 467 } 468 469 475 private static void writeSchemaFile(SchemaElement schema, File filePath) 476 throws IOException { 477 OutputStream schemaStream = null; 478 try { 479 schemaStream = new FileOutputStream ( 480 new File (filePath, NameUtil.getSchemaResourceName( 481 schema.getName().getName()))); 482 schema.save(schemaStream); 483 } catch (IOException ex) { 484 throw ex; 485 } finally { 486 try { 487 if (schemaStream != null) { 488 schemaStream.close(); 489 } 490 } catch (IOException ex) { 491 if (logger.isLoggable(Logger.FINE)) 492 logger.fine(ex.toString()); 493 } 494 } 495 } 496 497 506 protected boolean isPropertyDefined(String propertyValue) { 507 return (super.isPropertyDefined(propertyValue) && 508 !Constants.UNDEFINED.equals(propertyValue)); 509 } 510 511 514 private class Results { 515 private final String useUniqueTableNames; 516 private final String dbVendorName; 517 private final Properties userPolicy; 518 519 523 private final boolean javaToDatabaseArgs; 524 525 Results(String useUniqueTableNames, String dbVendorName, 526 Properties userPolicy, boolean javaToDatabaseArgs) { 527 this.useUniqueTableNames = useUniqueTableNames; 528 this.dbVendorName = dbVendorName; 529 this.userPolicy = userPolicy; 530 this.javaToDatabaseArgs = javaToDatabaseArgs; 531 } 532 533 536 537 public String getUseUniqueTableNames() { 538 return useUniqueTableNames; 539 } 540 541 544 public boolean hasUniqueTableNames() { 545 return isPropertyDefined(useUniqueTableNames); 546 } 547 548 552 public boolean hasJavaToDatabaseArgs() { 553 return javaToDatabaseArgs; 554 } 555 556 557 public String getDatabaseVendorName() { 558 return dbVendorName; 559 } 560 561 562 public Properties getUserPolicy() { 563 return userPolicy; 564 } 565 } 566 567 575 private Results getDeploymentArguments( 576 EjbcContext ejbcContext, 577 ResourceReferenceDescriptor cmpResource, 578 boolean connectToDatabase) { 579 580 String useUniqueTableNames = null; 581 String dbVendorName = null; 582 Properties userPolicy = null; 583 584 boolean javaToDatabaseArgs = false; 587 588 if (null == ejbcContext) { 591 dbVendorName = cmpResource.getDatabaseVendorName(); 592 593 } else { 594 Properties cliOverrides = ejbcContext.getOptionalArguments(); 597 useUniqueTableNames = cliOverrides.getProperty( 598 Constants.CMP_UNIQUE_TABLE_NAMES); 599 600 javaToDatabaseArgs =isPropertyDefined(useUniqueTableNames); 604 605 dbVendorName = cliOverrides.getProperty(Constants.CMP_DB_VENDOR_NAME); 606 607 javaToDatabaseArgs |= isPropertyDefined(dbVendorName); 608 609 if (null == dbVendorName || dbVendorName.equals(Constants.UNDEFINED)) { 612 dbVendorName = cmpResource.getDatabaseVendorName(); 613 } 614 615 if (null == dbVendorName && connectToDatabase) { 618 try { 619 Connection conn = DeploymentHelper.getConnection( 620 cmpResource.getJndiName()); 621 dbVendorName = conn.getMetaData().getDatabaseProductName(); 622 } catch (Exception ex) { 623 } 625 } 626 String createTables = 627 cliOverrides.getProperty(Constants.CMP_CREATE_TABLES); 628 javaToDatabaseArgs |= isPropertyDefined(createTables); 629 630 String dropAndCreateTables = 631 cliOverrides.getProperty(Constants.CMP_DROP_AND_CREATE_TABLES); 632 javaToDatabaseArgs |= isPropertyDefined(dropAndCreateTables); 633 634 } 635 636 if (null == dbVendorName) { 637 dbVendorName = DBVendorTypeHelper.DEFAULT_DB; 638 } else { 639 dbVendorName = DBVendorTypeHelper.getDBType(dbVendorName); 640 } 641 642 userPolicy = cmpResource.getSchemaGeneratorProperties(); 643 644 return new Results(useUniqueTableNames, dbVendorName, userPolicy, javaToDatabaseArgs); 645 } 646 647 658 private ResourceReferenceDescriptor checkOrCreateCMPResource( 659 boolean mappedBeans) 660 throws GeneratorException { 661 ResourceReferenceDescriptor cmpResource = 662 bundle.getCMPResourceReference(); 663 if (mappedBeans) { 664 if (cmpResource == null) { 665 throw JDOCodeGeneratorHelper.createGeneratorException( 668 "EXC_MissingCMPResource", bundle); } 670 } else { 671 if (cmpResource == null) { 672 673 cmpResource = new ResourceReferenceDescriptor(); 675 cmpResource.setJndiName("jdbc/__default"); 676 cmpResource.setDatabaseVendorName(DBVendorTypeHelper.DERBY); 677 cmpResource.setCreateTablesAtDeploy(true); 678 cmpResource.setDropTablesAtUndeploy(true); 679 bundle.setCMPResourceReference(cmpResource); 680 } 681 } 682 return cmpResource; 683 } 684 685 697 private void ensureDBSchemaExistence( 698 ResourceReferenceDescriptor cmpResource, 699 SunCmpMappings sunCmpMappings, 700 String inputFilesPath, 701 File classout) 702 throws DBException, SQLException , GeneratorException { 703 704 String generatedSchemaName = getInfoHelper().getSchemaNameToGenerate(); 705 Set tables = new HashSet (); 706 int size = sunCmpMappings.sizeSunCmpMapping(); 707 708 for (int i = 0; i < size; i++) { 713 SunCmpMapping sunCmpMapping = sunCmpMappings.getSunCmpMapping(i); 714 715 String schemaName = sunCmpMapping.getSchema(); 716 if (StringHelper.isEmpty(schemaName)) { 717 if (!isVerifyFlag) { 718 addAllTables(sunCmpMapping, tables); 720 sunCmpMapping.setSchema(generatedSchemaName); 721 } else { 722 getConversionHelper().setEnsureValidation(false); 725 } 726 727 } else { 728 File dbschemaFile = new File ( 729 new StringBuffer (inputFilesPath) 730 .append(File.separator) 731 .append(schemaName) 732 .append(DBSCHEMA_EXTENSION).toString()); 733 if (! (dbschemaFile.exists() 734 && dbschemaFile.isFile() 735 && dbschemaFile.canRead())) { 736 throw new GeneratorException( 737 I18NHelper.getMessage( 738 messages, "CMG.MissingDBSchema", bundle.getApplication().getRegistrationName(), 740 JDOCodeGeneratorHelper.getModuleName(bundle), 741 schemaName)); 742 } 743 } 744 } 745 746 if (tables.size() > 0) { 749 String userSchema = null; 750 Connection con = DeploymentHelper.getConnection(cmpResource.getJndiName()); 751 DatabaseMetaData dmd = con.getMetaData(); 752 if (DBVendorTypeHelper.requireUpperCaseSchema(dmd)) { 753 userSchema = dmd.getUserName().trim().toUpperCase(); 754 } 755 756 ConnectionProvider cp = new ConnectionProvider(con, dmd.getDriverName().trim()); 757 if (userSchema != null) { 758 cp.setSchema(userSchema); 759 } 760 761 OutputStream outstream = null; 762 763 try { 764 SchemaElementImpl outSchemaImpl = new SchemaElementImpl(cp); 765 SchemaElement schemaElement = new SchemaElement(outSchemaImpl); 766 schemaElement.setName(DBIdentifier.create(generatedSchemaName)); 767 768 if(dmd.getDatabaseProductName().compareToIgnoreCase("MYSQL") == 0) 769 outSchemaImpl.initTables(cp, new LinkedList (tables), new LinkedList (), true); 770 else 771 outSchemaImpl.initTables(cp, new LinkedList (tables), new LinkedList (), false); 772 outstream = new FileOutputStream ( 773 new File (classout, 774 new StringBuffer (generatedSchemaName) 775 .append(DBSCHEMA_EXTENSION).toString())); 776 777 schemaElement.save(outstream); 781 782 } catch (IOException ex) { 783 throw JDOCodeGeneratorHelper.createGeneratorException( 785 "CMG.CannotSaveDBSchema", bundle, ex); } finally { 787 cp.closeConnection(); 788 try { 789 if (outstream != null) { 790 outstream.close(); 791 } 792 } catch (IOException ex) { 793 if (logger.isLoggable(Logger.FINE)) 794 logger.fine(ex.toString()); 795 } 796 } 797 } 798 } 799 800 807 private void addAllTables(SunCmpMapping sunCmpMapping, Set tables) { 808 EntityMapping[] beans = sunCmpMapping.getEntityMapping(); 809 for (int i = 0; i < beans.length; i++) { 810 addTableName(beans[i].getTableName(), tables); 812 813 CmpFieldMapping[] cmpfields = beans[i].getCmpFieldMapping(); 816 for (int j = 0; j < cmpfields.length; j++) { 817 String [] names = cmpfields[j].getColumnName(); 819 for (int jj = 0; jj < names.length; jj++) { 820 addRelatedTableName(names[jj], tables); 821 } 822 } 823 824 CmrFieldMapping[] cmrfields = beans[i].getCmrFieldMapping(); 826 for (int j = 0; j < cmrfields.length; j++) { 827 ColumnPair[] pairs = cmrfields[j].getColumnPair(); 829 for (int jj = 0; jj < pairs.length; jj++) { 830 String [] names = pairs[jj].getColumnName(); 831 for (int jjj = 0; jjj < names.length; jjj++) { 832 addRelatedTableName(names[jjj], tables); 833 } 834 } 835 } 836 } 837 } 838 839 846 private void addTableName(String name, Set tables) { 847 if (!StringHelper.isEmpty(name)) { 848 if (logger.isLoggable(Logger.FINE)){ 849 logger.fine("Adding Table to Capture Set: " + name); } 851 852 tables.add(name); 853 } 854 } 855 856 863 private void addRelatedTableName(String columnName, Set tables) { 864 if (!StringHelper.isEmpty(columnName)) { 865 int l = columnName.indexOf(DOT); 866 if (l > 0) { 867 addTableName(columnName.substring(0, l), tables); 868 } 869 } 870 } 871 } 872 | Popular Tags |