KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > ejb > ejbc > MappingGenerator


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * MappingGenerator.java
26  *
27  * Created on Aug 18, 2003
28  */

29
30 package com.sun.jdo.spi.persistence.support.ejb.ejbc;
31
32 import java.io.BufferedInputStream JavaDoc;
33 import java.io.File JavaDoc;
34 import java.io.FileInputStream JavaDoc;
35 import java.io.FileOutputStream JavaDoc;
36 import java.io.OutputStream JavaDoc;
37 import java.io.InputStream JavaDoc;
38 import java.io.IOException JavaDoc;
39
40 import java.util.Iterator JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Properties JavaDoc;
43 import java.util.ResourceBundle JavaDoc;
44 import java.util.Set JavaDoc;
45 import java.util.HashSet JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.List JavaDoc;
48 import java.util.LinkedList JavaDoc;
49
50 import java.sql.Connection JavaDoc;
51 import java.sql.DatabaseMetaData JavaDoc;
52 import java.sql.SQLException JavaDoc;
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 /*
102  * This class will generate mapping classes from sun-cmp-mappings.xml
103  * and dbschema if they are available in the jar, or it will generate mapping
104  * classes based on ejb-jar.xml, bean classes and policy by invoking the
105  * database generation backend.
106  *
107  * @author Jie Leng
108  */

109 public class MappingGenerator extends
110     com.sun.jdo.api.persistence.mapping.ejb.MappingGenerator {
111
112     // XXX To be removed when all callers are switched to use
113
// DatabaseConstants.JAVA_TO_DB_FLAG directly.
114
public static final String JavaDoc JAVA_TO_DB_FLAG = DatabaseConstants.JAVA_TO_DB_FLAG;
115
116     private static final String JavaDoc DBSCHEMA_EXTENSION = ".dbschema"; // NOI18N
117
private static final char DOT = '.'; // NOI18N
118

119      /** The logger */
120     private static final Logger logger = LogHelperEJBCompiler.getLogger();
121
122     private final EjbBundleDescriptor bundle;
123
124     private String JavaDoc dbVendorName = null;
125     private boolean isJavaToDatabaseFlag = false;
126     private boolean isVerifyFlag = false;
127         
128     /**
129      * I18N message handler
130      */

131     private final static ResourceBundle JavaDoc messages = I18NHelper.loadBundle(
132             MappingGenerator.class);
133
134     /**
135      * Constructor
136      * @param bundle an ejb bundle
137      * @param model a model containing mapping class and
138      * persistence class information
139      * @param nameMapper a nameMapper for name lookup
140      * @param loader a class loader
141      */

142     public MappingGenerator(EjbBundleDescriptor bundle, Model model,
143             NameMapper nameMapper, ClassLoader JavaDoc loader) {
144         super(new EJBBundleInfoHelper(bundle, nameMapper, model, null), loader, false);
145         this.bundle = bundle;
146     }
147
148     /**
149      * This method will load mapping classes if there is sun-cmp-mappings.xml,
150      * otherwise it will call the database generation backend to create
151      * mapping classes and schema. It also generates *.dbschema and
152      * sun-cmp-mappings.xml in application dir if it is
153      * in creating mapping classes mode.
154      * @param ejbcContext an object containing CLI options for
155      * the database generation backend
156      * @param inputFilesPath the directory where sun-cmp-mappings.xml is located
157      * @param generatedXmlsPath the directory where the generated files are located
158      @ @param classout the directory where the classes are located
159      * @param ignoreSunDeploymentDescriptors use java2db generation if set to <code>true</code>.
160      * @return a SchemaElement for mapping classes mapped to
161      * @throws IOException
162      * @throws DBException
163      * @throws ModelException
164      * @throws Schema2BeansException
165      * @throws SQLException
166      * @throws GeneratorException
167      * @throws ConversionException
168      */

169     public SchemaElement generateMapping(
170             EjbcContext ejbcContext, String JavaDoc inputFilesPath,
171             String JavaDoc generatedXmlsPath, File JavaDoc classout,
172             boolean ignoreSunDeploymentDescriptors)
173             throws IOException JavaDoc, DBException, ModelException,
174             Schema2BeansException, SQLException JavaDoc, GeneratorException,
175             ConversionException {
176
177         SchemaElement schema = null;
178         if (ejbcContext == null)
179             isVerifyFlag = true;
180
181         File JavaDoc cmpMappingFile = getSunCmpMappingFile(inputFilesPath);
182         boolean mappedBeans = !ignoreSunDeploymentDescriptors
183                 && cmpMappingFile.exists();
184         ResourceReferenceDescriptor cmpResource = checkOrCreateCMPResource(
185                 mappedBeans);
186
187         // Remember whether or not this mapping was created by Java2DB.
188
isJavaToDatabaseFlag = DeploymentHelper.isJavaToDatabase(
189                 cmpResource.getSchemaGeneratorProperties());
190
191         // We *must* get a vendor name if either the beans are not mapped, or
192
// they are mapped and the javaToDatabase flag is set.
193
boolean mustHaveDBVendorName =
194             !mappedBeans || (mappedBeans && isJavaToDatabaseFlag);
195         
196         // Read deployment settings from the deployment descriptor
197
// and CLI options.
198
Results deploymentArguments = getDeploymentArguments(
199                 ejbcContext, cmpResource, mustHaveDBVendorName);
200         dbVendorName = deploymentArguments.getDatabaseVendorName();
201
202         if (mappedBeans) {
203             // If sun-cmp-mappings.xml exists and we are doing a deployment,
204
// validate some arguments and make sure we have dbschema.
205

206             // If it is from verify, skip deployment arguments check.
207
if (!isVerifyFlag) {
208                 String JavaDoc warning = null; // Warning for user, if required.
209

210                 if (isJavaToDatabaseFlag) {
211
212                     // If beans were already mapped, we will generate tables, but
213
// they will be as per the existing mapping. So if the user
214
// gave --uniquetablenames, warn them that we will not take
215
// that flag into account. I.e., the tables will be generated
216
// as per the mapping.
217
if (deploymentArguments.hasUniqueTableNames()) {
218                         warning =
219                             I18NHelper.getMessage(
220                                 messages,
221                                 "EXC_DisallowJava2DBUniqueTableNames", //NOI18N
222
bundle.getApplication().getRegistrationName(),
223                                 JDOCodeGeneratorHelper.getModuleName(bundle));
224                         logger.warning(warning);
225                     }
226                 } else if (deploymentArguments.hasJavaToDatabaseArgs()) {
227
228                     // If beans are already mapped but the user gave any Java2DB
229
// command line arguments, warn the user that these args
230
// should not be used when module is already mapped.
231
warning =
232                         I18NHelper.getMessage(
233                             messages,
234                             "EXC_DisallowJava2DBCLIOverrides", //NOI18N
235
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 JavaDoc msg = status.getStageStatusMessage();
246                     msg = (msg == null) ? warning : (msg + "\n" + warning); // NOI18N
247
status.setStageStatusMessage(msg);
248                 }
249             }
250                
251             // Sun-cmp-mapping.xml exists, use normal MappingClass loading
252
SunCmpMappings sunCmpMappings = getSunCmpMappings(cmpMappingFile);
253
254             // Ensure that there is a dbschema for each element of
255
// sunCmpMappings.
256
ensureDBSchemaExistence(cmpResource, sunCmpMappings, inputFilesPath,
257                 classout);
258
259             // load real mapping model and jdo model in memory
260
Map JavaDoc mappingClasses = loadMappingClasses(sunCmpMappings, getClassLoader());
261
262             // Get schema from one of the mapping classes.
263
// The mapping class element may be null if there is inconsistency
264
// in sun-cmp-mappings.xml and ejb-jar.xml. For example,
265
// the bean has mapping information in sun-cmp-mappings.xml but
266
// no definition in the ejb-jar.xml.
267
// So iterate over the mappings until the 1st non-null is found.
268
MappingClassElement mc = null;
269             Iterator JavaDoc 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 " // NOI18N
280
+ cmpResource.getJndiName()
281                             + ", isJavaToDatabase=" + isJavaToDatabaseFlag); // NOI18N
282
}
283         }
284         else {
285             // Generate mapping file and dbschema, since either
286
// sun-cmp-mappings.xml does not exist (e.g. user didn't yet map)
287
// or ejbcContext is null (e.g. running under auspices of AVK).
288
DatabaseGenerator.Results results = generateMappingClasses(
289                     dbVendorName, deploymentArguments.getUseUniqueTableNames(),
290                     deploymentArguments.getUserPolicy(), inputFilesPath);
291
292             // java2db from verifier should not save anything to disk
293
if (!isVerifyFlag) {
294                 // save SunCmpMapping to sun-cmp-mappings.xml
295
// in generated XML dir
296
writeSunCmpMappingFile(results.getMappingClasses(),
297                     getSunCmpMappingFile(generatedXmlsPath));
298
299                 schema = results.getSchema();
300
301                 // save schema to dbschema file in generated XML dir
302
writeSchemaFile(schema, classout);
303
304                 setJavaToDatabase(cmpResource, true);
305             }
306         }
307
308         return schema;
309     }
310
311     public String JavaDoc getDatabaseVendorName() {
312         return dbVendorName;
313     }
314
315     /**
316      * Returns javatodb flag in cmpResource.
317      * @return true if there is name as "javatodb" and value as "true"
318      */

319     public boolean isJavaToDatabase() {
320         return isJavaToDatabaseFlag;
321     }
322
323     /**
324      * Set javatodb flag into SchemaGeneratorProperties
325      * @param cmpResource a ResourceReferenceDescriptor
326      * @param value a string containing true or false
327      */

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"); // NOI18N
333
}
334
335         Properties JavaDoc schemaGeneratorProperties = cmpResource.
336                 getSchemaGeneratorProperties();
337         if (schemaGeneratorProperties == null) {
338             schemaGeneratorProperties = new Properties JavaDoc();
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     /**
349      * Loads sun-cmp-mapping.xml into memory as SunCmpMappings
350      * @param cmpMappingFile a file of sun-cmp-mappings.xml
351      * @return a SunCmpMappings object
352      * @throws IOException
353      * @throws Schema2BeansException
354      */

355     private SunCmpMappings getSunCmpMappings(File JavaDoc cmpMappingFile)
356         throws IOException JavaDoc, Schema2BeansException, GeneratorException {
357         InputStream JavaDoc is = null;
358         BufferedInputStream JavaDoc iasMapping = null;
359         SunCmpMappings sunCmpMapping = null;
360
361         if (cmpMappingFile.length() == 0) {
362             throw JDOCodeGeneratorHelper.createGeneratorException(
363                     "CMG.BeansFileSizeIsZero", bundle); // NOI18N
364
}
365
366         try {
367             is = new FileInputStream JavaDoc(cmpMappingFile);
368             iasMapping = new BufferedInputStream JavaDoc(is);
369             sunCmpMapping = SunCmpMappings.createGraph(iasMapping);
370         } catch (IOException JavaDoc ex) {
371             throw ex;
372         } finally {
373             if (is != null) {
374                 try {
375                     is.close();
376                 } catch(Exception JavaDoc 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 JavaDoc 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); // NOI18N
396
}
397
398         return sunCmpMapping;
399     }
400
401     /**
402      * Gets sun-cmp-mappings.xml file
403      * @param filesPath a string consisting file path
404      * @return a file of sun-cmp-mappings.xml
405      */

406     private static File JavaDoc getSunCmpMappingFile(String JavaDoc filesPath) {
407         String JavaDoc cmpMappingFile = (new StringBuffer JavaDoc(filesPath).
408                 append(File.separator).
409                 append(MappingFile.DEFAULT_LOCATION_IN_EJB_JAR)).toString();
410
411         // if the file contains directory structure, we need
412
// to create those directories if they do not exist.
413
if (cmpMappingFile.lastIndexOf(File.separatorChar) != -1) {
414             String JavaDoc dirs = cmpMappingFile.substring(
415                 0, cmpMappingFile.lastIndexOf(File.separatorChar));
416             File JavaDoc fileDirs = new File JavaDoc(dirs);
417             if (!fileDirs.exists())
418                 fileDirs.mkdirs();
419         }
420
421         return new File JavaDoc(cmpMappingFile);
422     }
423     
424
425     /**
426      * Writes to sun-cmp-mappings.xml from mappings classes
427      * @param mappingClasses a set of mapping classes
428      * @param cmpMappingFile corresponds to sun-cmp-mappings.xml
429      * @throws IOException
430      * @throws ConversionException
431      * @throws Schema2BeansException
432      */

433     private void writeSunCmpMappingFile(Set JavaDoc mappingClasses, File JavaDoc cmpMappingFile)
434         throws IOException JavaDoc, ConversionException, Schema2BeansException {
435         // Construct the input to MappingFile.fromMappingClasses(): a Map
436
// object containing ejbName and MappingClassElement. Use the
437
// elements of iteration and NameMapper to create the input for
438
// MappingFile.
439
Map JavaDoc mappingMap = new HashMap JavaDoc();
440         AbstractNameMapper nameMapper = getNameMapper();
441         Iterator JavaDoc iter = mappingClasses.iterator();
442         while (iter.hasNext()) {
443             MappingClassElement mappingClass = (MappingClassElement)iter.next();
444             String JavaDoc ejbName = nameMapper.getEjbNameForPersistenceClass(
445                     mappingClass.getName());
446             mappingMap.put(ejbName, mappingClass);
447         }
448         MappingFile mf = new MappingFile();
449         OutputStream JavaDoc sunCmpMapping = null;
450         try {
451             sunCmpMapping = new FileOutputStream JavaDoc(
452                 cmpMappingFile);
453             mf.fromMappingClasses(sunCmpMapping, mappingMap,
454                 getConversionHelper());
455         } catch (IOException JavaDoc ex) {
456             throw ex;
457         } finally {
458             try {
459                 if (sunCmpMapping != null) {
460                     sunCmpMapping.close();
461                 }
462             } catch (IOException JavaDoc ex) {
463                 if (logger.isLoggable(Logger.FINE))
464                     logger.fine(ex.toString());
465             }
466         }
467     }
468
469     /**
470      * Writes to *.dbschema file from schema
471      * @param schema a SchemaElement
472      * @param filePath a directory where *.dbschema is located
473      * @throws IOException
474      */

475     private static void writeSchemaFile(SchemaElement schema, File JavaDoc filePath)
476             throws IOException JavaDoc {
477         OutputStream JavaDoc schemaStream = null;
478         try {
479             schemaStream = new FileOutputStream JavaDoc(
480                 new File JavaDoc(filePath, NameUtil.getSchemaResourceName(
481                 schema.getName().getName())));
482             schema.save(schemaStream);
483         } catch (IOException JavaDoc ex) {
484            throw ex;
485         } finally {
486             try {
487                 if (schemaStream != null) {
488                     schemaStream.close();
489                 }
490             } catch (IOException JavaDoc ex) {
491                if (logger.isLoggable(Logger.FINE))
492                     logger.fine(ex.toString());
493             }
494         }
495     }
496
497     /**
498      * Returns <code>true</code> if the specified propertyValue represents
499      * a defined value, <code>false</code> otherwise. This implementation
500      * returns <code>true</code> if the value is not empty and does not equal
501      * Constants.UNDEFINED.
502      * @param propertyValue the value to be tested for defined
503      * @return <code>true</code> if the specified propertyValue represents
504      * a defined value, <code>false</code> otherwise
505      */

506     protected boolean isPropertyDefined(String JavaDoc propertyValue) {
507         return (super.isPropertyDefined(propertyValue) &&
508             !Constants.UNDEFINED.equals(propertyValue));
509     }
510
511     /**
512      * Contains the results of getDeploymentArguments()
513      */

514     private class Results {
515         private final String JavaDoc useUniqueTableNames;
516         private final String JavaDoc dbVendorName;
517         private final Properties JavaDoc userPolicy;
518
519         /**
520          * If true, then the user explicitly provided one or more command line
521          * args that are specific to Java2DB.
522          */

523         private final boolean javaToDatabaseArgs;
524
525     Results(String JavaDoc useUniqueTableNames, String JavaDoc dbVendorName,
526                 Properties JavaDoc userPolicy, boolean javaToDatabaseArgs) {
527             this.useUniqueTableNames = useUniqueTableNames;
528             this.dbVendorName = dbVendorName;
529             this.userPolicy = userPolicy;
530             this.javaToDatabaseArgs = javaToDatabaseArgs;
531         }
532
533         // XXX Get rid of getUseUniqueTableNames from all call sites that need a
534
// boolean (probably all of them), using hasUniqueTableNames instead
535

536         /** @return useUniqueTableNames */
537         public String JavaDoc getUseUniqueTableNames() {
538             return useUniqueTableNames;
539         }
540
541         /**
542          * @return true if --uniquetablenames was given on the command line.
543          */

544         public boolean hasUniqueTableNames() {
545             return isPropertyDefined(useUniqueTableNames);
546         }
547
548         /**
549          * Returns true if any Java2DB arguments were given on the command
550          * line.
551          * @return javaToDatabaseArgs */

552         public boolean hasJavaToDatabaseArgs() {
553             return javaToDatabaseArgs;
554         }
555
556         /** @return dbVendorName */
557         public String JavaDoc getDatabaseVendorName() {
558             return dbVendorName;
559         }
560
561         /** @return userPolicy */
562         public Properties JavaDoc getUserPolicy() {
563             return userPolicy;
564         }
565     }
566
567     /** Reads deployment settings from the deployment descriptor and CLI options
568      * and populates the corresponding variables.
569      * @param ejbcContext CLI arguments are obtained from here.
570      * @param cmpResource Parameters from deployment descriptor are obtained
571      * from here.
572      * @param connectToDatabase If true, then connect to database to get
573      * database vendor name if not otherwise available.
574      */

575     private Results getDeploymentArguments(
576             EjbcContext ejbcContext,
577             ResourceReferenceDescriptor cmpResource,
578             boolean connectToDatabase) {
579
580         String JavaDoc useUniqueTableNames = null;
581         String JavaDoc dbVendorName = null;
582         Properties JavaDoc userPolicy = null;
583
584         //Indicates that one or more Java2DB arguments were given on the command
585
//line.
586
boolean javaToDatabaseArgs = false;
587
588         // If ejbcContext is not available, then use what is specified by
589
// cmpResource.
590
if (null == ejbcContext) {
591             dbVendorName = cmpResource.getDatabaseVendorName();
592
593         } else {
594             // Otherwise, get the vendor name from one of the CLI overrides,
595
// cmpResource, or the actual database (in that order).
596
Properties JavaDoc cliOverrides = ejbcContext.getOptionalArguments();
597             useUniqueTableNames = cliOverrides.getProperty(
598                     Constants.CMP_UNIQUE_TABLE_NAMES);
599
600             // In javaToDatabaseArgs, we collect whether or not we have seen
601
// any of the java to database - related arguments, starting with
602
// --uniquetablenames.
603
javaToDatabaseArgs =isPropertyDefined(useUniqueTableNames);
604
605             dbVendorName = cliOverrides.getProperty(Constants.CMP_DB_VENDOR_NAME);
606
607             javaToDatabaseArgs |= isPropertyDefined(dbVendorName);
608
609             // XXX This check can be removed when DeployCommand guarantees to
610
// not return UNDEFINED.
611
if (null == dbVendorName || dbVendorName.equals(Constants.UNDEFINED)) {
612                 dbVendorName = cmpResource.getDatabaseVendorName();
613             }
614
615             // If there is no CLI override, and nothing specified in the
616
// cmp-resource, try to get the dbvendorname from the database.
617
if (null == dbVendorName && connectToDatabase) {
618                 try {
619                     Connection JavaDoc conn = DeploymentHelper.getConnection(
620                             cmpResource.getJndiName());
621                     dbVendorName = conn.getMetaData().getDatabaseProductName();
622                 } catch (Exception JavaDoc ex) {
623                     // Ignore exceptions and use default.
624
}
625             }
626             String JavaDoc createTables =
627                 cliOverrides.getProperty(Constants.CMP_CREATE_TABLES);
628             javaToDatabaseArgs |= isPropertyDefined(createTables);
629
630             String JavaDoc 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     /**
648      * Check if cmp resource is specified in the deployment descriptor.
649      * If the beans are mapped (sun-cmp-mapping.xml is present), the cmp
650      * resource must be present, otherwise (in java2db case) we will create
651      * a default one. If it's java2db, we will also parse the CLI overrides,
652      * as the cmp resource provides the default values.
653      *
654      * @param mappedBeans true if beans are mapped in this module.
655      * @throws GeneratorException if beans are mapped but cmp resource is not
656      * specified.
657      */

658     private ResourceReferenceDescriptor checkOrCreateCMPResource(
659             boolean mappedBeans)
660             throws GeneratorException {
661         ResourceReferenceDescriptor cmpResource =
662                 bundle.getCMPResourceReference();
663         if (mappedBeans) {
664             if (cmpResource == null) {
665                 // If mapping exists, the cmpResource must specify a
666
// database or a PMF JNDI name.
667
throw JDOCodeGeneratorHelper.createGeneratorException(
668                         "EXC_MissingCMPResource", bundle); //NOI18N
669
}
670         } else {
671             if (cmpResource == null) {
672
673                 // In JavaToDB case we can deploy to the default jdbc-resource.
674
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     /**
686     * Check that there is a dbschema for each element of the SunCmpMappings.
687     * For those which are missing, create a corresponding .dbschema file.
688     * @param cmpResource Provides JNDI name for getting database connection
689     * @param sunCmpMappings SunCmpMappings which is checked for having schema
690     * @param inputFilesPath the directory where this bundle's files are located
691     * @param classout the directory where the classes are located
692     * @exception DBException Thrown if database model throws it
693     * @exception IOException Thrown if .dbschema file cannot be created.
694     * @exception SQLException Thrown if we cannot get get required info from
695     * the database.
696     */

697     private void ensureDBSchemaExistence(
698             ResourceReferenceDescriptor cmpResource,
699             SunCmpMappings sunCmpMappings,
700             String JavaDoc inputFilesPath,
701             File JavaDoc classout)
702             throws DBException, SQLException JavaDoc, GeneratorException {
703
704         String JavaDoc generatedSchemaName = getInfoHelper().getSchemaNameToGenerate();
705         Set JavaDoc tables = new HashSet JavaDoc();
706         int size = sunCmpMappings.sizeSunCmpMapping();
707
708         // Sweep through the mappings to check dbschema existence. If a
709
// mapping does not have a dbschema, get a list of tables to be
710
// captured, then capture them, create the corresponding dbschema,
711
// and save it.
712
for (int i = 0; i < size; i++) {
713             SunCmpMapping sunCmpMapping = sunCmpMappings.getSunCmpMapping(i);
714
715             String JavaDoc schemaName = sunCmpMapping.getSchema();
716             if (StringHelper.isEmpty(schemaName)) {
717                 if (!isVerifyFlag) {
718                     // The tables in this section need to be captured.
719
addAllTables(sunCmpMapping, tables);
720                     sunCmpMapping.setSchema(generatedSchemaName);
721                 } else {
722                     // If it is from verifier, capture schema internally
723
// to perform sun-cmp-mappings.xml and EJB validation
724
getConversionHelper().setEnsureValidation(false);
725                 }
726                  
727             } else {
728                 File JavaDoc dbschemaFile = new File JavaDoc(
729                         new StringBuffer JavaDoc(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", // NOI18N
739
bundle.getApplication().getRegistrationName(),
740                             JDOCodeGeneratorHelper.getModuleName(bundle),
741                             schemaName));
742                 }
743             }
744         }
745
746         // If there were tables to be captured, they will be in the list.
747
// Now we need to go and capture those tables.
748
if (tables.size() > 0) {
749             String JavaDoc userSchema = null;
750             Connection JavaDoc con = DeploymentHelper.getConnection(cmpResource.getJndiName());
751             DatabaseMetaData JavaDoc 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 JavaDoc 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 JavaDoc(tables), new LinkedList JavaDoc(), true);
770                 else
771                     outSchemaImpl.initTables(cp, new LinkedList JavaDoc(tables), new LinkedList JavaDoc(), false);
772                 outstream = new FileOutputStream JavaDoc(
773                         new File JavaDoc(classout,
774                         new StringBuffer JavaDoc(generatedSchemaName)
775                             .append(DBSCHEMA_EXTENSION).toString()));
776
777                 // XXX Unfortunately, if SchemaElement.save gets an
778
// IOException, it prints the stack trace but does not
779
// let us handle it :-(
780
schemaElement.save(outstream);
781
782             } catch (IOException JavaDoc ex) {
783                 // Catch FileNotFound, etc.
784
throw JDOCodeGeneratorHelper.createGeneratorException(
785                         "CMG.CannotSaveDBSchema", bundle, ex); // NOI18N
786
} finally {
787                 cp.closeConnection();
788                 try {
789                     if (outstream != null) {
790                         outstream.close();
791                     }
792                 } catch (IOException JavaDoc ex) {
793                     if (logger.isLoggable(Logger.FINE))
794                         logger.fine(ex.toString());
795                 }
796             }
797         }
798     }
799
800     /**
801      * Adds all table names referenced by this <code>SunCmpMapping</code> element
802      * to this Set.
803      *
804      * @param sunCmpMapping the SunCmpMapping element to check.
805      * @param tables the Set to update.
806      */

807     private void addAllTables(SunCmpMapping sunCmpMapping, Set JavaDoc tables) {
808         EntityMapping[] beans = sunCmpMapping.getEntityMapping();
809         for (int i = 0; i < beans.length; i++) {
810             // Always add the table name.
811
addTableName(beans[i].getTableName(), tables);
812
813             // Check if there are table names specified in the
814
// cmp-field-mapping.
815
CmpFieldMapping[] cmpfields = beans[i].getCmpFieldMapping();
816             for (int j = 0; j < cmpfields.length; j++) {
817                 // There might be more than one column-name for each cmp field.
818
String JavaDoc[] names = cmpfields[j].getColumnName();
819                 for (int jj = 0; jj < names.length; jj++) {
820                     addRelatedTableName(names[jj], tables);
821                 }
822             }
823
824             // Check the table names specified in the cmr-field-mapping.
825
CmrFieldMapping[] cmrfields = beans[i].getCmrFieldMapping();
826             for (int j = 0; j < cmrfields.length; j++) {
827                 // There might be more than one column-pair for each cmr field.
828
ColumnPair[] pairs = cmrfields[j].getColumnPair();
829                 for (int jj = 0; jj < pairs.length; jj++) {
830                     String JavaDoc[] 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     /**
840      * Add a valid (not null and not all spaces) table name to the
841      * Set of known table names.
842      *
843      * @param name the table name to add if it's a valid name.
844      * @param tables the Set to update.
845      */

846     private void addTableName(String JavaDoc name, Set JavaDoc tables) {
847         if (!StringHelper.isEmpty(name)) {
848             if (logger.isLoggable(Logger.FINE)){
849                 logger.fine("Adding Table to Capture Set: " + name); // NOI18N
850
}
851
852             tables.add(name);
853         }
854     }
855
856     /**
857      * Adds a table name, if it is specified as a part of the column name,
858      * to the Set of known table names.
859      *
860      * @param columnName the name of the column to use.
861      * @param tables the Set to update.
862      */

863     private void addRelatedTableName(String JavaDoc columnName, Set JavaDoc 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