Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
// Portion Copyright [2018] Payara Foundation and/or affiliates
/*
* MappingPolicy.java
*
* Created on Jan 14, 2003
*/
package com.sun.jdo.spi.persistence.generator.database;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.Types;
import org.glassfish.persistence.common.I18NHelper;
import org.glassfish.common.util.StringHelper;
import com.sun.jdo.spi.persistence.utility.logging.Logger;
import org.glassfish.persistence.common.database.DBVendorTypeHelper;
import org.glassfish.persistence.common.DatabaseConstants;
// XXX Capitalization of acronyms such as Jdbc vs. JDBC is inconsistent
// throught out this package.
/**
* Describes how Java classes and their fields are to be mapped to database
* tables and columns
*/
public class MappingPolicy implements Cloneable {
//
// The names of many properties in our .properties files are composed of
// different pieces, here called "bases", followed by "indicators". The
// idea is that a base may have multiple indicators. In a way, they are
// kind of like instances of structs, with each base naming an instance
// and each indicator naming an accessor to a value in the struct.
//
// The concatenation of bases and indicators is just another String,
// which you can look up in a Properties object to get a value.
//
// Note that some property names have more than one base concatenated.
// See SQL92.properties for examples.
//
/** @see DatabaseGenerationConstants#DOT */
static final char DOT = DatabaseGenerationConstants.DOT;
//
// Base names of properties which describe how class and field names are
// to be represented in a database.
//
/** Base name to denote a class. */
private static final String CLASS_BASE = "{class-name}"; //NOI18N
/** Base name to denote a field. */
private static final String FIELD_BASE = "{field-name}"; //NOI18N
/** Base name to denote a relationship field. */
private static final String RELATIONSHIP_BASE =
"{relationship-field-name}"; //NOI18N
/** Represents a '.' in a regular expression */
private static String REGEXP_DOT = "\\."; // NOI18N
/** Synonym for DatabaseGenerationConstants.INDICATOR_JDBC_PREFIX. */
private static final String INDICATOR_JDBC_PREFIX =
DatabaseGenerationConstants.INDICATOR_JDBC_PREFIX;
/**
* Base name to denote maximum length of a name in a database. We
* support different maximum lengths for table, column, and constraint
* names.
*/
private static final String INDICATOR_MAXIMUM_LENGTH =
DatabaseGenerationConstants.INDICATOR_MAXIMUM_LENGTH;
//
// Indicator names for properties which describe how class and field
// names are to be represented in a database.
//
/** Indicator that property is for a table name. */
private static final String INDICATOR_TABLE_NAME =
"table-name"; //NOI18N
/** Indicator that property is for a column name. */
private static final String INDICATOR_COLUMN_NAME =
"column-name"; //NOI18N
/** Indicator that property is for a join table name. */
private static final String INDICATOR_JOIN_TABLE_NAME =
"join-table-name"; //NOI18N
/** Indicator that property is for a constraint name. */
private static final String INDICATOR_CONSTRAINT_NAME =
"constraint-name"; //NOI18N
//
// These are complete property names composed of bases and indicators.
//
/** Prefix of properties that denote classes. */
private static final String CLASS_PREFIX =
CLASS_BASE + DOT;
/** Prefix of properties that denote classes. */
private static final String RELATIONSHIP_PREFIX =
CLASS_PREFIX + RELATIONSHIP_BASE + DOT;
/** Name of property that provides default field-to-column name mapping. */
private static final String DEFAULT_COLUMN_KEY =
CLASS_PREFIX + FIELD_BASE + DOT + INDICATOR_COLUMN_NAME;
/** Name of property that provides default jointable name mapping. */
private static final String DEFAULT_JOIN_TABLE_KEY =
RELATIONSHIP_PREFIX + INDICATOR_JOIN_TABLE_NAME;
/** Name of property that provides default constraint name mapping. */
private static final String DEFAULT_CONSTRAINT_KEY =
RELATIONSHIP_PREFIX + INDICATOR_CONSTRAINT_NAME;
/** Name of property that provides default class-to-table name mapping. */
private static final String DEFAULT_TABLE_KEY =
CLASS_PREFIX + INDICATOR_TABLE_NAME;
//
// Now, here are values of properties which indicate how table and column
// names are to be generated. I.e., in our .properties files, these are
// potential values for some property names composed of the above bases
// and indicators.
//
/** Property value indicating table name must be same as class name. */
private static final String TABLE_NAME_AS_CLASSNAME =
"{className}"; //NOI18N
/** Property value indicating table name must be upper case. */
private static final String TABLE_NAME_UPPERCASE =
TABLE_NAME_AS_CLASSNAME.toUpperCase();
/** Property value indicating table name must be uppercase and unique. */
private static final String TABLE_NAME_HASH_UPPERCASE =
"{HASH-CLASSNAME}"; //NOI18N
/** Property value indicating colum name must be same as field name. */
private static final String COLUMN_NAME_AS_FIELDNAME =
"{fieldName}"; //NOI18N
/** Property value indicating column name must be uppercase. */
private static final String COLUMN_NAME_UPPERCASE =
COLUMN_NAME_AS_FIELDNAME.toUpperCase();
/** Property value indicating join table name must be uppercase. */
private static final String JOIN_TABLE_NAME_UPPERCASE =
"{CLASSNAMES}"; //NOI18N
/** Property value indicating constraint name must be uppercase. */
private static final String CONSTRAINT_NAME_UPPERCASE =
"{FIELDNAMES}"; //NOI18N
//
// Here are indicators for properties that direct how vendor-dependent
// SQL is generated.
//
/** Indicator that property is for formatting SQL */
private static final String INDICATOR_SQL_FORMAT = "sql-format"; //NOI18N
/** The indicator for a statement separator. */
private static final String STATEMENT_SEPARATOR_INDICATOR =
"statementSeparator"; // NOI18N
/** The indicator for starting a "create table". */
private static final String CREATE_TABLE_START_INDICATOR =
"createTableStart"; // NOI18N
/** The indicator for ending a "create table". */
private static final String CREATE_TABLE_END_INDICATOR =
"createTableEnd"; // NOI18N
/** The indicator for "create index". Added for Symfoware support as */
/** indexes on primary keys are mandatory */
private static final String CREATE_INDEX_INDICATOR =
"createIndex"; // NOI18N
/** The indicator for starting a "drop table". */
private static final String DROP_TABLE_INDICATOR =
"dropTable"; // NOI18N
/** The indicator for "add constraint". */
private static final String ALTER_TABLE_ADD_CONSTRAINT_START_INDICATOR =
"alterTableAddConstraintStart"; // NOI18N
/** The indicator for "drop constraint". */
private static final String ALTER_TABLE_DROP_CONSTRAINT_INDICATOR =
"alterTableDropConstraint"; // NOI18N
/** The indicator for adding a primary key constraint. */
private static final String PRIMARY_KEY_CONSTRAINT_INDICATOR =
"primaryKeyConstraint"; // NOI18N
/** The indicator for adding a foreign key constraint. */
private static final String FOREIGN_KEY_CONSTRAINT_INDICATOR =
"foreignKeyConstraint"; // NOI18N
/** The indicator for verbose nullability. */
private static final String COLUMN_NULLABILITY_INDICATOR =
"columnNullability"; // NOI18N
/** The indicator for information used with LOB columns. */
private static final String LOB_LOGGING_INDICATOR =
"LOBLogging"; // NOI18N
//
// The remaining constants are neither bases nor indicators.
//
/** Prefix of column names which are primary key columns. */
private static final String PK_PREFIX = "PK_"; //NOI18N
/** Prefix of column names which are foreign key columns. */
private static final String FK_PREFIX = "FK_"; //NOI18N
/** Name of the "global" namespace. */
private static final String GLOBAL_NAMING_SPACE = "GLOBAL"; //NOI18N
/** Property name which indicates unique table names should be generated. */
public static final String USE_UNIQUE_TABLE_NAMES = "use-unique-table-names"; // NOI18N
/** Property name which indicates reserved words. */
private static final String RESERVED_WORDS = "reserved-words";// NOI18N
/** When appended to a reserved word, causes it to be not-reserved. */
private static final String RESERVED_WORD_UNRESERVER = "9"; // NOI18N
/**
* Maximum length of the counter used to create unique names with a
* numeric id. Note that this length includes a NAME_SEPARATOR, so that
* we allow for 3 digits total.
*/
private static final int MAX_LEN_COUNTER = 4;
/** Number of chars to change a reserved word into * unreserved. */
private static final int MAX_LEN_RESERVED = 1;
/**
* Name of subdirectory in which db vendor - specific properties files
* are located.
*/
private static final String PROPERTY_FILE_DIR =
"com/sun/jdo/spi/persistence/generator/database/"; // NOI18N
/** Extension used by properties files. */
private static final String PROPERTY_FILE_EXT = ".properties"; // NOI18N
//
// The above are all constants; below things get "interesting".
//
/** This is the set of all default properties. */
private static final Properties defaultProps = new Properties();
//
// XXX Consider getting these String-Integer and Integer-String maps into
// SQLTypeUtil, which is in the dbschema module. Or not: we support only a
// subset of java.sql.types, and (presumably) the dbschema module would
// provide mappings for all types.
//
// Note also that is code in MappingGenerator of a "SQLTypeUtil" nature.
//
/**
* Map from String names to the Integer-boxed values from
* java.sql.Types.
*/
private static final Map jdbcTypes = new HashMap();
/**
* Maps from Integer-boxed values from java.sql.Types to String names.
*/
private static final Map jdbcTypeNames = new HashMap();
/**
* Global counter for creating unique names in each of the namespaces.
* Note that a single counter is used across all namespaces.
*/
private int counter = 0;
/**
* Map from namespaces to Set of names defined in each namespace. Used
* to ensure uniqueness within namespaces.
*/
private Map namespaces = new HashMap();
/**
* Indicates whether or not generated table names should include a
* unique value as part of their names.
*/
private boolean uniqueTableName = false;
/**
* Set of reserved words for a particular policy.
*/
private final Set reservedWords = new TreeSet();
/**
* Set of reserved words for the default database.
*/
private static Set defaultReservedWords;
/**
* Map from the string names of the java types (e.g. "java.lang.String")
* to a JDBCInfo of information about the corresponding java.sql.Types
* type. Different for different dbvendor types, but the same instance,
* per dbvendor, is shared by all MappingPolicy instances.
*/
private final Map dbJdbcInfoMap = new HashMap();
/**
* Similar to {@link #dbJdbcInfoMap}, but is reinitialized by each
* clone(). Contains user-provided overrides of the information in
* dbjdbcInfoMap.
*/
private Map userJdbcInfoMap = new HashMap();
/**
* Map from a boxed value based on fields in java.sql.Types to the String
* name of a SQL type.
*/
private final Map sqlInfo = new HashMap();
//
// Maximum lengths for table, column, and constraint names are
// vendor-specific.
//
/** Maximum length of the name of a table. */
private int tableNameMaxLength;
/** Maximum length of the name of a column. */
private int columnNameMaxLength;
/** Maximum length of the name of a constraint. */
private int constraintNameMaxLength;
//
// Strings to represent vendor-specific SQL that starts a table,
// separates statements, etc.
//
/** The SQL for a statement separator. */
private String statementSeparator;
/** The SQL for starting a "create table". */
private String createTableStart;
/** The SQL for ending a "create table". */
private String createTableEnd;
/** The SQL for "create index". */
private String createIndex;
/** The SQL for "drop table". */
private String dropTable;
/** The SQL for "add constraint". */
private String alterTableAddConstraintStart;
/** The SQL for "drop constraint". */
private String alterTableDropConstraint;
/** The SQL for adding a primary key constraint. */
private String primaryKeyConstraint;
/** The SQL for adding a foreign key constraint. */
private String foreignKeyConstraint;
/** The SQL for indicating column nullability */
private String columnNullability;
/** The SQL for indicating LOB column logging */
private String lobLogging = "";
/**
* Map from the encoded name of a policy to its value. For example, a
* class name's naming policy would be encoded as
* ".table-name".
*/
// XXX Consider renaming this.
private final Map namingPolicy = new HashMap();
/** Map from database vendor names to instances of MappingPolicy. */
private static final Map instances = new HashMap();
/** Logger for warning & error messages */
private static final Logger logger =
LogHelperDatabaseGenerator.getLogger();
/** I18N message handler */
private final static ResourceBundle messages =
I18NHelper.loadBundle(MappingPolicy.class);
//
// Initialize the JDBC String to Integer map and the default (SQL92)
// MappingPolicy.
//
// XXX Why initialize the SQL policy, when there's a good chance it won't
// ever be used? Do we really want to support unrecognized databases?
// See comment in getMappingPolicy. The default properties, on the other
// hand, *do* need to be loaded.
// XXX We need to decide what happens when an unrecognized dbvendorname
// is given: Error? Warning, continue running?
static {
// Initialize jdbcType map.
jdbcTypes.put("BIGINT", new Integer(Types.BIGINT)); // NOI18N
jdbcTypes.put("BIT", new Integer(Types.BIT)); // NOI18N
jdbcTypes.put("BLOB", new Integer(Types.BLOB)); // NOI18N
jdbcTypes.put("CHAR", new Integer(Types.CHAR)); // NOI18N
jdbcTypes.put("CLOB", new Integer(Types.CLOB)); // NOI18N
jdbcTypes.put("DATE", new Integer(Types.DATE)); // NOI18N
jdbcTypes.put("DECIMAL", new Integer(Types.DECIMAL)); // NOI18N
jdbcTypes.put("DOUBLE", new Integer(Types.DOUBLE)); // NOI18N
jdbcTypes.put("INTEGER", new Integer(Types.INTEGER)); // NOI18N
jdbcTypes.put("LONGVARBINARY", new Integer(Types.LONGVARBINARY)); // NOI18N
jdbcTypes.put("LONGVARCHAR", new Integer(Types.LONGVARCHAR)); // NOI18N
jdbcTypes.put("NULL", new Integer(Types.NULL)); // NOI18N
jdbcTypes.put("REAL", new Integer(Types.REAL)); // NOI18N
jdbcTypes.put("SMALLINT", new Integer(Types.SMALLINT)); // NOI18N
jdbcTypes.put("TIME", new Integer(Types.TIME)); // NOI18N
jdbcTypes.put("TIMESTAMP", new Integer(Types.TIMESTAMP)); // NOI18N
jdbcTypes.put("TINYINT", new Integer(Types.TINYINT)); // NOI18N
jdbcTypes.put("VARCHAR", new Integer(Types.VARCHAR)); // NOI18N
jdbcTypeNames.put(new Integer(Types.BIGINT), "BIGINT"); // NOI18N
jdbcTypeNames.put(new Integer(Types.BIT), "BIT"); // NOI18N
jdbcTypeNames.put(new Integer(Types.BLOB), "BLOB"); // NOI18N
jdbcTypeNames.put(new Integer(Types.CHAR), "CHAR"); // NOI18N
jdbcTypeNames.put(new Integer(Types.CLOB), "CLOB"); // NOI18N
jdbcTypeNames.put(new Integer(Types.DATE), "DATE"); // NOI18N
jdbcTypeNames.put(new Integer(Types.DECIMAL), "DECIMAL"); // NOI18N
jdbcTypeNames.put(new Integer(Types.DOUBLE), "DOUBLE"); // NOI18N
jdbcTypeNames.put(new Integer(Types.INTEGER), "INTEGER"); // NOI18N
jdbcTypeNames.put(new Integer(Types.LONGVARBINARY), "LONGVARBINARY"); // NOI18N
jdbcTypeNames.put(new Integer(Types.LONGVARCHAR), "LONGVARCHAR"); // NOI18N
jdbcTypeNames.put(new Integer(Types.NULL), "NULL"); // NOI18N
jdbcTypeNames.put(new Integer(Types.REAL), "REAL"); // NOI18N
jdbcTypeNames.put(new Integer(Types.SMALLINT), "SMALLINT"); // NOI18N
jdbcTypeNames.put(new Integer(Types.TIME), "TIME"); // NOI18N
jdbcTypeNames.put(new Integer(Types.TIMESTAMP), "TIMESTAMP"); // NOI18N
jdbcTypeNames.put(new Integer(Types.TINYINT), "TINYINT"); // NOI18N
jdbcTypeNames.put(new Integer(Types.VARCHAR), "VARCHAR"); // NOI18N
try {
// Create and load the default mapping policy.
new MappingPolicy();
} catch (Throwable ex) {
logger.log(Logger.SEVERE,
I18NHelper.getMessage(
messages,
"EXC_MappingPolicyNotFound", //NOI18N
DBVendorTypeHelper.DEFAULT_DB));
}
}
/**
* Create the default MappingPolicy instance.
*/
// This should be invoked only once per JVM. See the class static
// block of code above.
private MappingPolicy() throws IOException {
load(getPropertyFileName(DBVendorTypeHelper.DEFAULT_DB),
defaultProps, false);
init(defaultProps);
// The DEFAULT_DB has reserved words for the default database type.
// Other databases can access those same values through the
// defaultReservedWords set.
defaultReservedWords = reservedWords;
instances.put(DBVendorTypeHelper.DEFAULT_DB, this);
if (logger.isLoggable(Logger.FINEST)) {
logger.finest("new MappingPolicy():\n" + toString()); // NOI18N
}
}
/**
* Create a MappingPolicy for the named database type.
* @param databaseType Name of the database for which a MappingPolicy is
* created. The name must conform to one of the .properties files in
* this package.
*/
// This should be invoked only once per databaseType per JVM. See
// {@link #getMappingPolicy}.
private MappingPolicy(String databaseType) throws IOException {
Properties mergedProp = new Properties(defaultProps);
load(getPropertyFileName(databaseType), mergedProp, false);
init(mergedProp);
instances.put(databaseType, this);
if (logger.isLoggable(Logger.FINEST)) {
logger.finest("new MappingPolicy(" // NOI18N
+ databaseType + "):\n" + toString()); // NOI18N
}
}
/**
* Returns a vendor-specifc MappingPolicy instance. This method always
* returns a copy (clone) of the known MappingPolicy to allow for
* user-specific overrides.
* @param databaseType a database vendor name as a String.
* @return MappingPolicy instance corresponding to the provided
* database vendor name.
* @throws IOException if there are problems reading the vendor-
* specific mappinng policy file
*/
public synchronized static MappingPolicy getMappingPolicy(
String databaseType) throws IOException {
if (logger.isLoggable(Logger.FINE)) {
logger.fine("get MappingPolicy"+databaseType); // NOI18N
}
MappingPolicy mappingPolicy = null;
try {
if (databaseType == null) {
databaseType = DBVendorTypeHelper.DEFAULT_DB;
// XXX FIXME Need to log a warning and report to user that we
// are *not* using databaseType given, that we are using
// SQL92 instead, and provide list of recognized names.
}
mappingPolicy = (MappingPolicy) instances.get(databaseType);
if (mappingPolicy == null) {
mappingPolicy = new MappingPolicy(databaseType);
}
mappingPolicy = (MappingPolicy) mappingPolicy.clone();
} catch (CloneNotSupportedException ec) {
// ignore it because it will not happen
}
return mappingPolicy;
}
/**
* Clones the vendor-specific policy for generator session. Replace the
* namespaces map in the clone, so that each instance has its own.
* @return clone of this MappingPolicy
* @throws CloneNotSupportedException never thrown
*/
protected Object clone() throws CloneNotSupportedException {
MappingPolicy mappingPolicyClone = (MappingPolicy) super.clone();
mappingPolicyClone.namespaces = new HashMap();
mappingPolicyClone.uniqueTableName = false;
mappingPolicyClone.userJdbcInfoMap = new HashMap();
return mappingPolicyClone;
}
/**
* Initializes the given properties from the given resourceName.
* @param resourceName Name of the resource to open, expected to contain
* properties in text form.
* @param properties Properties that are to be loaded.
* @param override If true, treat resourceName as a filename
* from which to read; if false, treat resourceName as the
* name of a resource accessed via the class loader which loaded the
* MappingPolicy class.
*/
private synchronized void load(
final String resourceName, Properties properties, boolean override)
throws IOException {
if (logger.isLoggable(Logger.FINE)) {
logger.fine("load resource:" + resourceName); // NOI18N
}
try (InputStream bin = new BufferedInputStream(getInputStream(resourceName, override))) {
properties.load(bin);
if (logger.isLoggable(Logger.FINE)) {
logger.fine("load "+resourceName + " successfuly"); // NOI18N
}
}
}
private InputStream getInputStream(String resourceName, boolean override) throws IOException {
InputStream in;
if (override) {
in = new FileInputStream(resourceName);
} else {
final ClassLoader loader =
MappingPolicy.class.getClassLoader();
in = (InputStream) AccessController.doPrivileged(
(PrivilegedAction