/** Loads the load groups of cmp fields from the xml element */ private void loadLoadGroupsXml(Element element) throws DeploymentException { Element loadGroupsElement = MetaData.getOptionalChild(element, "load-groups"); if (loadGroupsElement == null) { // no info, default work already done in constructor return; } // only allowed for cmp 2.x if (isCMP1x) { throw new DeploymentException("load-groups are only allowed " + "for CMP 2.x"); } // load each group Iterator groups = MetaData.getChildrenByTagName(loadGroupsElement, "load-group"); while (groups.hasNext()) { Element groupElement = (Element) groups.next(); // get the load-group-name String loadGroupName = MetaData.getUniqueChildContent(groupElement, "load-group-name"); if (loadGroups.containsKey(loadGroupName)) { throw new DeploymentException( "Load group already defined: " + " load-group-name=" + loadGroupName); } if (loadGroupName.equals("*")) { throw new DeploymentException( "The * load group is automatically " + "defined and can't be overriden"); } ArrayList group = new ArrayList(); // add each field Iterator fields = MetaData.getChildrenByTagName(groupElement, "field-name"); while (fields.hasNext()) { String fieldName = MetaData.getElementContent((Element) fields.next()); // check if the field is a cmp field that it is not a pk memeber JDBCCMPFieldMetaData field = getCMPFieldByName(fieldName); if (field != null && field.isPrimaryKeyMember()) { throw new DeploymentException( "Primary key fields can not be" + " a member of a load group: " + " load-group-name=" + loadGroupName + " field-name=" + fieldName); } group.add(fieldName); } loadGroups.put(loadGroupName, Collections.unmodifiableList(group)); } }
/** * Constructs entity meta data with the data contained in the entity xml element from a * jbosscmp-jdbc xml file. Optional values of the xml element that are not present are loaded from * the defalutValues parameter. * * @param jdbcApplication the application in which this entity is defined * @param element the xml Element which contains the metadata about this entity * @param defaultValues the JDBCEntityMetaData which contains the values for optional elements of * the element * @throws DeploymentException if the xml element is not semantically correct */ public JDBCEntityMetaData( JDBCApplicationMetaData jdbcApplication, Element element, JDBCEntityMetaData defaultValues) throws DeploymentException { // store passed in application... application in defaultValues may // be different because jdbcApplication is imutable this.jdbcApplication = jdbcApplication; // set default values entityName = defaultValues.getName(); entityClass = defaultValues.getEntityClass(); primaryKeyClass = defaultValues.getPrimaryKeyClass(); isCMP1x = defaultValues.isCMP1x; primaryKeyFieldName = defaultValues.getPrimaryKeyFieldName(); homeClass = defaultValues.getHomeClass(); remoteClass = defaultValues.getRemoteClass(); localHomeClass = defaultValues.getLocalHomeClass(); localClass = defaultValues.getLocalClass(); queryFactory = new JDBCQueryMetaDataFactory(this); if (isCMP1x) { abstractSchemaName = (defaultValues.getAbstractSchemaName() == null ? entityName : defaultValues.getAbstractSchemaName()); } else { abstractSchemaName = defaultValues.getAbstractSchemaName(); } // datasource name String dataSourceNameString = MetaData.getOptionalChildContent(element, "datasource"); if (dataSourceNameString != null) { dataSourceName = dataSourceNameString; } else { dataSourceName = defaultValues.getDataSourceName(); } // get the datasource mapping for this datasource (optional, but always // set in standardjbosscmp-jdbc.xml) String datasourceMappingString = MetaData.getOptionalChildContent(element, "datasource-mapping"); if (datasourceMappingString != null) { datasourceMappingName = datasourceMappingString; datasourceMapping = jdbcApplication.getTypeMappingByName(datasourceMappingString); if (datasourceMapping == null) { throw new DeploymentException( "Error in jbosscmp-jdbc.xml : " + "datasource-mapping " + datasourceMappingString + " not found"); } } else if (defaultValues.datasourceMappingName != null && defaultValues.datasourceMapping != null) { datasourceMappingName = null; datasourceMapping = defaultValues.datasourceMapping; } else { datasourceMappingName = null; datasourceMapping = obtainTypeMappingFromLibrary(dataSourceName); } // get table name String tableStr = MetaData.getOptionalChildContent(element, "table-name"); if (tableStr != null) { tableName = tableStr; } else { tableName = defaultValues.getDefaultTableName(); } // create table? If not provided, keep default. String createStr = MetaData.getOptionalChildContent(element, "create-table"); if (createStr != null) { createTable = Boolean.valueOf(createStr).booleanValue(); } else { createTable = defaultValues.getCreateTable(); } // remove table? If not provided, keep default. String removeStr = MetaData.getOptionalChildContent(element, "remove-table"); if (removeStr != null) { removeTable = Boolean.valueOf(removeStr).booleanValue(); } else { removeTable = defaultValues.getRemoveTable(); } // alter table? If not provided, keep default. String alterStr = MetaData.getOptionalChildContent(element, "alter-table"); if (alterStr != null) { alterTable = Boolean.valueOf(alterStr).booleanValue(); } else { alterTable = defaultValues.getAlterTable(); } // get the SQL command to execute after table creation Element posttc = MetaData.getOptionalChild(element, "post-table-create"); if (posttc != null) { Iterator it = MetaData.getChildrenByTagName(posttc, "sql-statement"); tablePostCreateCmd = new ArrayList(); while (it.hasNext()) { Element etmp = (Element) it.next(); tablePostCreateCmd.add(MetaData.getElementContent(etmp)); } } else { tablePostCreateCmd = defaultValues.getDefaultTablePostCreateCmd(); } // read-only String readOnlyStr = MetaData.getOptionalChildContent(element, "read-only"); if (readOnlyStr != null) { readOnly = Boolean.valueOf(readOnlyStr).booleanValue(); } else { readOnly = defaultValues.isReadOnly(); } // read-time-out String readTimeOutStr = MetaData.getOptionalChildContent(element, "read-time-out"); if (readTimeOutStr != null) { try { readTimeOut = Integer.parseInt(readTimeOutStr); } catch (NumberFormatException e) { throw new DeploymentException( "Invalid number format in " + "read-time-out '" + readTimeOutStr + "': " + e); } } else { readTimeOut = defaultValues.getReadTimeOut(); } String sForUpStr = MetaData.getOptionalChildContent(element, "row-locking"); if (sForUpStr != null) { rowLocking = !isReadOnly() && (Boolean.valueOf(sForUpStr).booleanValue()); } else { rowLocking = defaultValues.hasRowLocking(); } // primary key constraint? If not provided, keep default. String pkStr = MetaData.getOptionalChildContent(element, "pk-constraint"); if (pkStr != null) { primaryKeyConstraint = Boolean.valueOf(pkStr).booleanValue(); } else { primaryKeyConstraint = defaultValues.hasPrimaryKeyConstraint(); } // list-cache-max String listCacheMaxStr = MetaData.getOptionalChildContent(element, "list-cache-max"); if (listCacheMaxStr != null) { try { listCacheMax = Integer.parseInt(listCacheMaxStr); } catch (NumberFormatException e) { throw new DeploymentException( "Invalid number format in read-" + "ahead list-cache-max '" + listCacheMaxStr + "': " + e); } if (listCacheMax < 0) { throw new DeploymentException( "Negative value for read ahead " + "list-cache-max '" + listCacheMaxStr + "'."); } } else { listCacheMax = defaultValues.getListCacheMax(); } // fetch-size String fetchSizeStr = MetaData.getOptionalChildContent(element, "fetch-size"); if (fetchSizeStr != null) { try { fetchSize = Integer.parseInt(fetchSizeStr); } catch (NumberFormatException e) { throw new DeploymentException( "Invalid number format in " + "fetch-size '" + fetchSizeStr + "': " + e); } if (fetchSize < 0) { throw new DeploymentException( "Negative value for fetch size " + "fetch-size '" + fetchSizeStr + "'."); } } else { fetchSize = defaultValues.getFetchSize(); } String compiler = MetaData.getOptionalChildContent(element, "ql-compiler"); if (compiler == null) { qlCompiler = defaultValues.qlCompiler; } else { try { qlCompiler = GetTCLAction.getContextClassLoader().loadClass(compiler); } catch (ClassNotFoundException e) { throw new DeploymentException("Failed to load compiler implementation: " + compiler); } } // throw runtime exceptions ? If not provided, keep default. String throwRuntimeExceptionsStr = MetaData.getOptionalChildContent(element, "throw-runtime-exceptions"); if (throwRuntimeExceptionsStr != null) { throwRuntimeExceptions = Boolean.valueOf(throwRuntimeExceptionsStr).booleanValue(); } else { throwRuntimeExceptions = defaultValues.getThrowRuntimeExceptions(); } // // cmp fields // // update all existing queries with the new read ahead value for (Iterator cmpFieldIterator = defaultValues.cmpFields.iterator(); cmpFieldIterator.hasNext(); ) { JDBCCMPFieldMetaData cmpField = new JDBCCMPFieldMetaData(this, (JDBCCMPFieldMetaData) cmpFieldIterator.next()); cmpFields.add(cmpField); cmpFieldsByName.put(cmpField.getFieldName(), cmpField); } // apply new configurations to the cmpfields for (Iterator i = MetaData.getChildrenByTagName(element, "cmp-field"); i.hasNext(); ) { Element cmpFieldElement = (Element) i.next(); String fieldName = MetaData.getUniqueChildContent(cmpFieldElement, "field-name"); JDBCCMPFieldMetaData oldCMPField = (JDBCCMPFieldMetaData) cmpFieldsByName.get(fieldName); if (oldCMPField == null) { throw new DeploymentException("CMP field not found : fieldName=" + fieldName); } JDBCCMPFieldMetaData cmpFieldMetaData = new JDBCCMPFieldMetaData(this, cmpFieldElement, oldCMPField); // replace the old cmp meta data with the new cmpFieldsByName.put(fieldName, cmpFieldMetaData); int index = cmpFields.indexOf(oldCMPField); cmpFields.remove(oldCMPField); cmpFields.add(index, cmpFieldMetaData); } // unknown primary key field if (primaryKeyClass == java.lang.Object.class) { Element upkElement = MetaData.getOptionalChild(element, "unknown-pk"); if (upkElement != null) { // assume now there is only one upk field JDBCCMPFieldMetaData oldUpkField = null; for (Iterator iter = cmpFields.iterator(); iter.hasNext(); ) { JDBCCMPFieldMetaData cmpField = (JDBCCMPFieldMetaData) iter.next(); if (cmpField.isUnknownPkField()) { oldUpkField = cmpField; break; } } // IMO, this is a redundant check if (oldUpkField == null) { oldUpkField = new JDBCCMPFieldMetaData(this); } JDBCCMPFieldMetaData upkField = new JDBCCMPFieldMetaData(this, upkElement, oldUpkField); // remove old upk field cmpFieldsByName.remove(oldUpkField.getFieldName()); cmpFieldsByName.put(upkField.getFieldName(), upkField); int oldUpkFieldInd = cmpFields.indexOf(oldUpkField); cmpFields.remove(oldUpkField); cmpFields.add(oldUpkFieldInd, upkField); } } // load-loads loadGroups.putAll(defaultValues.loadGroups); loadLoadGroupsXml(element); // eager-load Element eagerLoadGroupElement = MetaData.getOptionalChild(element, "eager-load-group"); if (eagerLoadGroupElement != null) { String eagerLoadGroupTmp = MetaData.getElementContent(eagerLoadGroupElement); if (eagerLoadGroupTmp != null && eagerLoadGroupTmp.trim().length() == 0) { eagerLoadGroupTmp = null; } if (eagerLoadGroupTmp != null && !eagerLoadGroupTmp.equals("*") && !loadGroups.containsKey(eagerLoadGroupTmp)) { throw new DeploymentException( "Eager load group not found: " + "eager-load-group=" + eagerLoadGroupTmp); } eagerLoadGroup = eagerLoadGroupTmp; } else { eagerLoadGroup = defaultValues.getEagerLoadGroup(); } // lazy-loads lazyLoadGroups.addAll(defaultValues.lazyLoadGroups); loadLazyLoadGroupsXml(element); // read-ahead Element readAheadElement = MetaData.getOptionalChild(element, "read-ahead"); if (readAheadElement != null) { readAhead = new JDBCReadAheadMetaData(readAheadElement, defaultValues.getReadAhead()); } else { readAhead = defaultValues.readAhead; } String value = MetaData.getOptionalChildContent(element, "clean-read-ahead-on-load"); if ("true".equalsIgnoreCase(value)) { cleanReadAheadOnLoad = true; } else if ("false".equalsIgnoreCase(value)) { cleanReadAheadOnLoad = false; } else if (value == null) { cleanReadAheadOnLoad = defaultValues.cleanReadAheadOnLoad; } else { throw new DeploymentException( "Failed to deploy " + entityName + ": allowed values for clean-read-ahead-on-load are true and false but got " + value); } // optimistic locking group Element optimisticLockingEl = MetaData.getOptionalChild(element, "optimistic-locking"); if (optimisticLockingEl != null) { optimisticLocking = new JDBCOptimisticLockingMetaData(this, optimisticLockingEl); } else { optimisticLocking = defaultValues.getOptimisticLocking(); } // audit Element auditElement = MetaData.getOptionalChild(element, "audit"); if (auditElement != null) { audit = new JDBCAuditMetaData(this, auditElement); } else { audit = defaultValues.getAudit(); } // queries // update all existing queries with the new read ahead value for (Iterator queriesIterator = defaultValues.queries.values().iterator(); queriesIterator.hasNext(); ) { JDBCQueryMetaData query = JDBCQueryMetaDataFactory.createJDBCQueryMetaData( (JDBCQueryMetaData) queriesIterator.next(), readAhead, qlCompiler); queries.put(query.getMethod(), query); } // apply new configurations to the queries for (Iterator queriesIterator = MetaData.getChildrenByTagName(element, "query"); queriesIterator.hasNext(); ) { Element queryElement = (Element) queriesIterator.next(); Map newQueries = queryFactory.createJDBCQueryMetaData(queryElement, defaultValues.queries, readAhead); // overrides defaults added above queries.putAll(newQueries); } // get the entity command for this entity Element entityCommandEl = MetaData.getOptionalChild(element, "entity-command"); if (entityCommandEl != null) { // command name in xml String entityCommandName = entityCommandEl.getAttribute("name"); // default entity command // The logic to assign the default value: // - if entity-command isn't specified in the entity element, // then it is assigned from the defaults; // - if command name in entity equals command name in defaults // then it is assigned from the defaults // - else try to find a command in entity-commands with the command // name specified in the entity. // if the match is found it'll be the default, else default is null JDBCEntityCommandMetaData defaultEntityCommand = defaultValues.getEntityCommand(); if ((defaultEntityCommand == null) || (!entityCommandName.equals(defaultEntityCommand.getCommandName()))) { defaultEntityCommand = jdbcApplication.getEntityCommandByName(entityCommandName); } if (defaultEntityCommand != null) { entityCommand = new JDBCEntityCommandMetaData(entityCommandEl, defaultEntityCommand); } else { entityCommand = new JDBCEntityCommandMetaData(entityCommandEl); } } else { entityCommand = defaultValues.getEntityCommand(); } }
/** * Constructs jdbc entity meta data defined in the jdbcApplication and with the data from the * entity meta data which is loaded from the ejb-jar.xml file. * * @param jdbcApplication the application in which this entity is defined * @param entity the entity meta data for this entity that is loaded from the ejb-jar.xml file * @throws DeploymentException if an problem occures while loading the classes or if data in the * ejb-jar.xml is inconsistent with data from jbosscmp-jdbc.xml file */ public JDBCEntityMetaData(JDBCApplicationMetaData jdbcApplication, EntityMetaData entity) throws DeploymentException { this.jdbcApplication = jdbcApplication; entityName = entity.getEjbName(); listCacheMax = 1000; fetchSize = 0; try { entityClass = getClassLoader().loadClass(entity.getEjbClass()); } catch (ClassNotFoundException e) { throw new DeploymentException("entity class not found for ejb-name: " + entityName, e); } try { primaryKeyClass = getClassLoader().loadClass(entity.getPrimaryKeyClass()); } catch (ClassNotFoundException e) { throw new DeploymentException( "could not load primary key class: " + entity.getPrimaryKeyClass()); } isCMP1x = entity.isCMP1x(); if (isCMP1x) { abstractSchemaName = (entity.getAbstractSchemaName() == null ? entityName : entity.getAbstractSchemaName()); } else { abstractSchemaName = entity.getAbstractSchemaName(); } primaryKeyFieldName = entity.getPrimKeyField(); String home = entity.getHome(); if (home != null) { try { homeClass = getClassLoader().loadClass(home); } catch (ClassNotFoundException e) { throw new DeploymentException("home class not found: " + home); } try { remoteClass = getClassLoader().loadClass(entity.getRemote()); } catch (ClassNotFoundException e) { throw new DeploymentException("remote class not found: " + entity.getRemote()); } } else { homeClass = null; remoteClass = null; } String localHome = entity.getLocalHome(); if (localHome != null) { try { localHomeClass = getClassLoader().loadClass(localHome); } catch (ClassNotFoundException e) { throw new DeploymentException("local home class not found: " + localHome); } try { localClass = getClassLoader().loadClass(entity.getLocal()); } catch (ClassNotFoundException e) { throw new DeploymentException("local class not found: " + entity.getLocal()); } } else { // we must have a home or local home if (home == null) { throw new DeploymentException( "Entity must have atleast a home " + "or local home: " + entityName); } localHomeClass = null; localClass = null; } // we replace the . by _ because some dbs die on it... // the table name may be overridden in importXml(jbosscmp-jdbc.xml) tableName = entityName.replace('.', '_'); // Warn: readTimeOut should be setup before cmp fields are created // otherwise readTimeOut in cmp fields will be set to 0 by default dataSourceName = null; datasourceMappingName = null; datasourceMapping = null; createTable = false; removeTable = false; alterTable = false; rowLocking = false; primaryKeyConstraint = false; readOnly = false; readTimeOut = -1; tablePostCreateCmd = null; qlCompiler = null; throwRuntimeExceptions = false; // build the metadata for the cmp fields now in case there is // no jbosscmp-jdbc.xml List nonPkFieldNames = new ArrayList(); for (Iterator i = entity.getCMPFields(); i.hasNext(); ) { String cmpFieldName = (String) i.next(); JDBCCMPFieldMetaData cmpField = new JDBCCMPFieldMetaData(this, cmpFieldName); cmpFields.add(cmpField); cmpFieldsByName.put(cmpFieldName, cmpField); if (!cmpField.isPrimaryKeyMember()) { nonPkFieldNames.add(cmpFieldName); } } // AL: add unknown primary key if primaryKeyClass is Object // AL: this is set up only in this constructor // AL: because, AFAIK, others are called with default value // AL: produced by this one if (primaryKeyClass == java.lang.Object.class) { JDBCCMPFieldMetaData upkField = new JDBCCMPFieldMetaData(this); cmpFields.add(upkField); cmpFieldsByName.put(upkField.getFieldName(), upkField); } // set eager load fields to all group. eagerLoadGroup = "*"; // Create no lazy load groups. By default every thing is eager loaded. // build the metadata for the queries now in case there is no // jbosscmp-jdbc.xml queryFactory = new JDBCQueryMetaDataFactory(this); for (Iterator queriesIterator = entity.getQueries(); queriesIterator.hasNext(); ) { QueryMetaData queryData = (QueryMetaData) queriesIterator.next(); Map newQueries = queryFactory.createJDBCQueryMetaData(queryData); // overrides defaults added above queries.putAll(newQueries); } // Create no relationship roles for this entity, will be added // by the relation meta data readAhead = JDBCReadAheadMetaData.DEFAULT; cleanReadAheadOnLoad = false; entityCommand = null; optimisticLocking = null; audit = null; }