Return-Path: X-Original-To: apmail-db-torque-dev-archive@www.apache.org Delivered-To: apmail-db-torque-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id AC0B0CA9A for ; Sun, 29 Jul 2012 19:48:52 +0000 (UTC) Received: (qmail 96349 invoked by uid 500); 29 Jul 2012 19:48:52 -0000 Delivered-To: apmail-db-torque-dev-archive@db.apache.org Received: (qmail 96286 invoked by uid 500); 29 Jul 2012 19:48:52 -0000 Mailing-List: contact torque-dev-help@db.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Apache Torque Developers List" Reply-To: "Apache Torque Developers List" Delivered-To: mailing list torque-dev@db.apache.org Received: (qmail 96271 invoked by uid 99); 29 Jul 2012 19:48:51 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 29 Jul 2012 19:48:51 +0000 X-ASF-Spam-Status: No, hits=2.2 required=5.0 tests=FILL_THIS_FORM_LOAN,RCVD_IN_DNSWL_LOW,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [62.13.149.56] (HELO outmail149056.authsmtp.com) (62.13.149.56) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 29 Jul 2012 19:48:39 +0000 Received: from mail-c193.authsmtp.com (mail-c193.authsmtp.com [62.13.128.118]) by punt10.authsmtp.com (8.14.2/8.14.2/Kp) with ESMTP id q6TJmIon046370 for ; Sun, 29 Jul 2012 20:48:18 +0100 (BST) Received: from Parzival.local ([62.48.54.223]) (authenticated bits=0) by mail.authsmtp.com (8.14.2/8.14.2) with ESMTP id q6TJm4pf096400 for ; Sun, 29 Jul 2012 20:48:07 +0100 (BST) Message-ID: <50159374.4030203@apache.org> Date: Sun, 29 Jul 2012 21:48:04 +0200 From: Thomas Vandahl User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:12.0) Gecko/20120428 Thunderbird/12.0.1 MIME-Version: 1.0 To: Apache Torque Developers List Subject: Re: BasePeerImpl, was: Re: RFD: RecordMappers, Peers and MapBuilders References: <5006FB9A.7060206@apache.org>, <4FFC850B.1090509@apache.org> <50046802.3070903@apache.org> In-Reply-To: X-Enigmail-Version: 1.4.2 Content-Type: multipart/mixed; boundary="------------080702050307000306090300" X-Server-Quench: 56c6551a-d9b6-11e1-97bb-002264978518 X-AuthReport-Spam: If SPAM / abuse - report it at: http://www.authsmtp.com/abuse X-AuthRoute: OCdyaAgQClZJUiwT EioPDCIGTh8qMAFL GwYeIE5WLUQhWQ4X O15TJVpedloGSkcD CnlxHghLUl1wW3N3 awBVZQ9cZARIXRtu WFZMRkxQFgZ3AxkD AwEeHFh0E38bfD4m ZU9kWnBbEkV4fU5/ RABREz4AYGJhOX1L WRJeagJVJQJXdxgX OE1/VHEPZ2EOYXJl Rl8lBT1jdR9WMylt TwwXDFcKRQJDATcn FVg4EGdnJ2MpFW0J IhchMFI5FV4JP18p dRMZVF8CKFcbDAEW OkhVKjJYI1UMXTFD X-Authentic-SMTP: 61633138303539.1014:706 X-AuthFastPath: 0 (Was 255) X-AuthSMTP-Origin: 62.48.54.223/2525 X-AuthVirus-Status: No virus detected - but ensure you scan with your own anti-virus system. --------------080702050307000306090300 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit On 21.07.12 15:04, Thomas Fox wrote: >> - I'd inject a RecordMapper, the database name and a TableMap on > creation of the >> instance (setters and/or constructor) > +1 Ok, this basically reduces the importance/usability of BasePeer but increases the usability of BasePeerImpl. Maybe, BasePeer can go some day. > >> - Move setDBName() to BasePeerImpl > +1 This shows to simplify things a lot. Especially if you use generated classes with different databases (of the same structure) > >> - Move addSelectColumns() to BasePeerImpl by using >> TableMap.getColumns() > +1 Done. Works fine. >> - Provide some kind of default record >> mapper/default record to make calls like in doSelectVillageRecords() >> work again. > I do not understand this. You want to put the results in a map ? Yes. More or less. There are cases where this is necessary, at least in the code I maintain. > >> - Remove the record mapper and the table map from the >> various method signatures > +1 What I did was to add the doSelect() methods from the generated XXXBasePeerImpl but leave the methods in. They are explicitly used by the doSelectJoin...() methods. Maybe we can make them protected. > >> - Remove the then obsolete methods in the >> generated PeerImpls. > +1 The result is attached. And what remains from BaseAuthorPeerImpl, for example. Actually, only the buildXXX() methods and the fillXXX() methods must be generated, *if* we could make BasePeerImpl abstract or provide some default implementation that throws a RuntimeException of sorts. >> Question: - >> Why do we have deprecated methods in a class that didn't even exist >> in Torque 3.3? Is it just for keeping the old Criteria object alive? > > It could allow for a soft transition form the old to the new criteria > class. > people just change the import but use the deprecated method... > but maybe this scenario will not happen in practice, no idea. I'm afraid this creates more confusion than it solves. The 4.0 release should be expected to be incompatible, and then it's just a matter of Ctrl+O in Eclipse to resolve that changed import. Just my 2 cents. Bye, Thomas --------------080702050307000306090300 Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0"; name="BasePeerImpl.java" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="BasePeerImpl.java" package org.apache.torque.util; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.io.Serializable; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.torque.Column; import org.apache.torque.Database; import org.apache.torque.TooManyRowsException; import org.apache.torque.Torque; import org.apache.torque.TorqueException; import org.apache.torque.adapter.Adapter; import org.apache.torque.adapter.IDMethod; import org.apache.torque.criteria.FromElement; import org.apache.torque.map.ColumnMap; import org.apache.torque.map.DatabaseMap; import org.apache.torque.map.MapHelper; import org.apache.torque.map.TableMap; import org.apache.torque.oid.IdGenerator; import org.apache.torque.om.NumberKey; import org.apache.torque.om.ObjectKey; import org.apache.torque.om.SimpleKey; import org.apache.torque.om.StringKey; import org.apache.torque.om.mapper.RecordMapper; import org.apache.torque.sql.Query; import org.apache.torque.sql.SqlBuilder; /** * This is the base class for all Peer classes in the system. Peer * classes are responsible for isolating all of the database access * for a specific business object. They execute all of the SQL * against the database. Over time this class has grown to include * utility methods which ease execution of cross-database queries and * the implementation of concrete Peers. * * @author Frank Y. Kim * @author John D. McNally * @author Brett McLaughlin * @author Stephen Haberman * @author Martin Poeschl * @author Augustin Vidovic * @author Henning P. Schmiedehausen * @version $Id: BasePeerImpl.java 1359157 2012-07-09 13:23:14Z tfischer $ */ public class BasePeerImpl implements Serializable { /** * Serial Version */ private static final long serialVersionUID = -7702123730779032381L; /** the log */ private static final Log log = LogFactory.getLog(BasePeer.class); /** An injected instance of a record mapper to map JDBC result sets to objects */ private RecordMapper recordMapper = null; /** An injected instance of a table map */ private TableMap tableMap = null; /** An injected instance of the database name */ private String databaseName = null; /** * Default constructor */ public BasePeerImpl() { super(); } /** * Constructor providing the objects to be injected as parameters * * @param recordMapper a record mapper to map JDBC result sets to objects * @param tableMap the default table map * @param databaseName the name of the database */ public BasePeerImpl(RecordMapper recordMapper, TableMap tableMap, String databaseName) { this(); setRecordMapper(recordMapper); setTableMap(tableMap); setDatabaseName(databaseName); } /** * Set the record mapper for this instance * * @param recordMapper the recordMapper to set */ public void setRecordMapper(RecordMapper recordMapper) { this.recordMapper = recordMapper; } /** * Get the record mapper for this instance. * * @return the recordMapper */ public RecordMapper getRecordMapper() { if (recordMapper == null) { throw new RuntimeException("No record mapper injected"); } return recordMapper; } /** * Set the default table map for this instance * * @param tableMap the tableMap to set */ public void setTableMap(TableMap tableMap) { this.tableMap = tableMap; } /** * Get the default table map for this instance * * @return the tableMap */ public TableMap getTableMap() { if (tableMap == null) { throw new RuntimeException("No table map injected"); } return tableMap; } /** * Set the database name for this instance * * @param databaseName the databaseName to set */ public void setDatabaseName(String databaseName) { this.databaseName = databaseName; } /** * Get the database name for this instance * * @return the databaseName */ public String getDatabaseName() { if (databaseName == null) { throw new RuntimeException("No database name injected"); } return databaseName; } /** * Get the list of objects for a ResultSet. Please not that your * resultset MUST return columns in the right order. You can use * getFieldNames() in BaseObject to get the correct sequence. * * @param resultSet the ResultSet * @return the list of objects * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public List resultSet2Objects(java.sql.ResultSet resultSet) throws TorqueException { try { List result = new ArrayList(); RecordMapper mapper = getRecordMapper(); while (resultSet.next()) { result.add(mapper.processRow(resultSet, 0)); } return result; } catch (SQLException e) { throw new TorqueException(e); } } /** * Convenience method to create a String array of criteria keys. * * @param tableName Name of table. * @param columnNames A String[]. * @return A String[]. * * @deprecated This method is not used any more and will be removed in a * future version of Torque. */ @Deprecated public String[] initCriteriaKeys( String tableName, String[] columnNames) { String[] keys = new String[columnNames.length]; for (int i = 0; i < columnNames.length; i++) { keys[i] = tableName + "." + columnNames[i].toUpperCase(); } return keys; } /** * Convenience method that uses straight JDBC to delete multiple * rows. * * @param con A Connection. * @param table The table to delete records from. * @param column The column in the where clause. * @param value The value of the column. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated The value is not SQL escaped. * Better use doDelete(Criteria, String, Connection) * for automatic escaping and more flexibility. * This method will be removed in a future version of Torque. */ @Deprecated public int deleteAll( Connection con, String table, String column, int value) throws TorqueException { Statement statement = null; try { statement = con.createStatement(); StringBuffer query = new StringBuffer(); query.append("DELETE FROM ") .append(table) .append(" WHERE ") .append(column) .append(" = ") .append(value); return statement.executeUpdate(query.toString()); } catch (SQLException e) { throw new TorqueException(e); } finally { if (statement != null) { try { statement.close(); } catch (SQLException e) { throw new TorqueException(e); } } } } /** * Convenience method that uses straight JDBC to delete multiple * rows. This method attempts to get the default database from * the pool. * * @param table The table to delete records from. * @param column The column in the where clause. * @param value The value of the column. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated The value is not SQL escaped. * Better use doDelete(Criteria, String) * for automatic escaping and more flexibility. * This method will be removed in a future version of Torque. */ @Deprecated public int deleteAll(String table, String column, int value) throws TorqueException { Connection con = null; try { // Get a connection to the db. con = Torque.getConnection(Torque.getDefaultDB()); return deleteAll(con, table, column, value); } finally { Torque.closeConnection(con); } } /** * Deletes rows from a database table. * * @param criteria defines the rows to be deleted, not null. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doDelete(org.apache.torque.criteria.Criteria criteria) throws TorqueException { Connection connection = null; try { setDbName(criteria); connection = Transaction.begin(criteria.getDbName()); int deletedRows = doDelete(criteria, connection); Transaction.commit(connection); connection = null; return deletedRows; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Deletes rows from a table. This method is to be used * during a transaction, otherwise use the doDelete(Criteria) method. * * @param criteria defines the rows to be deleted, not null. * @param con the connection to use, not null. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doDelete(org.apache.torque.criteria.Criteria criteria, Connection con) throws TorqueException { correctBooleans(criteria); setDbName(criteria); return doDelete(criteria, getTableMap(), con); } /** * Method to perform deletes based on conditions in a Criteria. * * @param criteria The criteria to use. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated This method causes unexpected results when joins are used. * Please use doDelete( * org.apache.torque.criteria.Criteria, TableMap). * This method will be removed in a future version of Torque. */ @Deprecated protected int doDelete(Criteria criteria) throws TorqueException { return doDelete(criteria, (TableMap) null); } /** * Method to perform deletes based on conditions a Criteria. * * @param criteria The criteria to use. * @param con the Connection to be used for deleting. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated This method causes unexpected results when joins are used. * Please use doDelete( * org.apache.torque.criteria.Criteria, TableMap, Connection). * This method will be removed in a future version of Torque. */ @Deprecated protected int doDelete(Criteria criteria, Connection con) throws TorqueException { if (criteria.values().isEmpty()) { throw new TorqueException("No conditions found in Criteria"); } Criteria.Criterion criterion = criteria.values().iterator().next(); TableMap tableMap = MapHelper.getTableMap( criterion.getColumn(), criteria, null); if (tableMap == null) { throw new TorqueException("Unqualified column name in criteria" + " or table name not found in database map"); } return doDelete(criteria, tableMap, con); } /** * Method to perform deletes based on conditions in a Criteria. * * @param criteria The criteria to use. * @param tableMap the table to delete records from. * If set to null, the name of the table(s) can be extracted from * the criteria, but this can cause unexpected results * when joins are used. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated Please use doDelete( * org.apache.torque.criteria.Criteria, String). * This method will be removed in a future version of Torque. */ @Deprecated public int doDelete(Criteria criteria, TableMap tableMap) throws TorqueException { Connection con = null; try { con = Transaction.begin(criteria.getDbName()); int result = doDelete(criteria, tableMap, con); Transaction.commit(con); con = null; return result; } finally { if (con != null) { Transaction.safeRollback(con); } } } /** * Method to perform deletes based on conditions in a Criteria. * * @param criteria The criteria to use. * @param tableMap the table to delete records from. * If set to null, the name of the table(s) can be extracted from * the criteria, but this can cause unexpected results * when joins are used. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doDelete( org.apache.torque.criteria.Criteria criteria, TableMap tableMap) throws TorqueException { Connection con = null; try { con = Transaction.begin(criteria.getDbName()); int result = doDelete(criteria, tableMap, con); Transaction.commit(con); con = null; return result; } finally { if (con != null) { Transaction.safeRollback(con); } } } /** * Method to perform deletes based on conditions in a Criteria. * * @param criteria The criteria to select the records to be deleted, * not null. * @param tableMap the table to delete records from. * If set to null, the name of the table(s) can be extracted from * the criteria, but this can cause unexpected results * when joins are used. * @param con The database connection for deletion, not null. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated Please use doDelete( * org.apache.torque.criteria.Criteria, String, Connection). * This method will be removed in a future version of Torque. */ @Deprecated public int doDelete( Criteria criteria, TableMap tableMap, Connection connection) throws TorqueException { Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.DELETE); String fullTableName = null; if (tableMap != null) { fullTableName = SqlBuilder.getFullTableName( tableMap.getName(), criteria.getDbName()); } else { Column column = criteria.values().iterator().next().getColumn(); fullTableName = SqlBuilder.getFullTableName( column.getFullTableName(), criteria.getDbName()); } boolean ownTableAdded = false; for (FromElement fromElement : query.getFromClause()) { // Table names are case insensitive in known databases // so use case-insensitive compare if (fullTableName.equalsIgnoreCase(fromElement.getFromExpression())) { ownTableAdded = true; break; } } if (!ownTableAdded) { query.getFromClause().add(new FromElement(fullTableName)); } String sql = query.toString(); PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); List replacements = setPreparedStatementReplacements( preparedStatement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing delete " + sql + ", parameters = " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("delete took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw new TorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Method to perform deletes based on conditions in a Criteria. * * @param criteria The criteria to select the records to be deleted, * not null. * @param tableMap the table to delete records from. * If set to null, the name of the table(s) can be extracted from * the criteria, but this can cause unexpected results * when joins are used. * @param con The database connection for deletion, not null. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doDelete( org.apache.torque.criteria.Criteria criteria, TableMap tableMap, Connection connection) throws TorqueException { Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.DELETE); String fullTableName; if (tableMap == null) { fullTableName = SqlBuilder.guessFullTableFromCriteria(criteria); } else { fullTableName = SqlBuilder.getFullTableName( tableMap.getName(), criteria.getDbName()); } boolean ownTableAdded = false; for (FromElement fromElement : query.getFromClause()) { // Table names are case insensitive in known databases // so use case-insensitive compare if (fullTableName.equalsIgnoreCase(fromElement.getFromExpression())) { ownTableAdded = true; break; } } if (!ownTableAdded) { query.getFromClause().add(new FromElement(fullTableName)); } String sql = query.toString(); PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); List replacements = setPreparedStatementReplacements( preparedStatement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing delete " + sql + ", parameters = " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("delete took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw new TorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Inserts a record into a database table. *

* If the primary key is included in Criteria, then that value will * be used to insert the row. *

* Otherwise, if the primary key can be generated automatically, * the generated key will be used for the insert and will be returned. *

* If no value is given for the primary key is defined and it cannot * be generated automatically or the table has no primary key, * the values will be inserted as specified and null will be returned. * * @param insertValues Contains the values to insert, not null. * * @return the primary key of the inserted row (if the table * has a primary key) or null (if the table does not have * a primary key). * * @throws TorqueException if a database error occurs. */ public ObjectKey doInsert(ColumnValues insertValues) throws TorqueException { String databaseName = insertValues.getDbName(); if (databaseName == null) { TableMap table = insertValues.getTable(); databaseName = table.getDatabaseMap().getDatabase().getName(); } Connection connection = null; try { connection = Transaction.begin(databaseName); ObjectKey id = doInsert(insertValues, connection); Transaction.commit(connection); connection = null; return id; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Inserts a record into a database table. *

* If the primary key is included in Criteria, then that value will * be used to insert the row. *

* Otherwise, if the primary key can be generated automatically, * the generated key will be used for the insert and will be returned. *

* If no value is given for the primary key is defined and it cannot * be generated automatically or the table has no primary key, * the values will be inserted as specified and null will be returned. * * @param insertValues Contains the values to insert, not null. * @param connection the connection to use for the insert, not null. * * @return the primary key of the inserted row (if the table * has a primary key) or null (if the table does not have * a primary key). * * @throws TorqueException if a database error occurs. */ public ObjectKey doInsert( ColumnValues insertValues, Connection connection) throws TorqueException { if (insertValues == null) { throw new TorqueException("insertValues is null"); } if (connection == null) { throw new TorqueException("connection is null"); } TableMap tableMap = insertValues.getTable(); DatabaseMap dbMap = tableMap.getDatabaseMap(); Database database = Torque.getDatabase(dbMap.getDatabase().getName()); Object keyInfo = getIdMethodInfo(tableMap); IdGenerator keyGen = database.getIdGenerator(tableMap.getPrimaryKeyMethod()); SimpleKey id = null; // can currently generate only single column pks, therefore a single // columnMap is ok ColumnMap primaryKey = null; if (keyGen != null) { // fail on multiple pks primaryKey = tableMap.getPrimaryKey(); // primaryKey will be null if there is no primary key // defined for the table we're inserting into. if (keyGen.isPriorToInsert() && primaryKey != null && !insertValues.containsKey( primaryKey)) { id = getId(primaryKey, keyGen, connection, keyInfo); insertValues.put( primaryKey, new JdbcTypedValue(id.getValue(), id.getJdbcType())); } } List columnNames = new ArrayList(); List replacementObjects = new ArrayList(); for (Map.Entry columnValue : insertValues.entrySet()) { Column column = columnValue.getKey(); columnNames.add(column.getColumnName()); JdbcTypedValue value = columnValue.getValue(); replacementObjects.add(value); } String fullTableName = SqlBuilder.getFullTableName( tableMap.getName(), dbMap.getDatabase().getName()); StringBuilder query = new StringBuilder("INSERT INTO ") .append(fullTableName) .append("(") .append(StringUtils.join(columnNames, ",")) .append(") VALUES ("); for (int i = 0; i < columnNames.size(); ++i) { if (i != 0) { query.append(","); } query.append("?"); } query.append(")"); PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(query.toString()); int position = 1; for (JdbcTypedValue replacementObject : replacementObjects) { Object value = replacementObject.getValue(); if (value != null) { if (replacementObject.getJdbcType() != Types.BLOB && replacementObject.getJdbcType() != Types.CLOB) { preparedStatement.setObject( position, value, replacementObject.getJdbcType()); } else { preparedStatement.setObject( position, value); } } else { preparedStatement.setNull( position, replacementObject.getJdbcType()); } position++; } long startTime = System.currentTimeMillis(); log.debug("Executing insert " + query.toString() + " using parameters " + replacementObjects); preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("insert took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; } catch (SQLException e) { throw new TorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } // If the primary key column is auto-incremented, get the id // now. if (keyGen != null && keyGen.isPostInsert() && primaryKey != null && !insertValues.containsKey( primaryKey)) { id = getId(primaryKey, keyGen, connection, keyInfo); } return id; } /** * Returns the idMethodInfo for a given table. * * @param tableMap the table map of the table, not null. * * @return the idMethodInfo, not null. * * @throws TorqueException if the database adapter for the table's database * needs to be accessed but is not configured. */ private Object getIdMethodInfo(TableMap tableMap) throws TorqueException { IDMethod idMethod = tableMap.getPrimaryKeyMethod(); if (IDMethod.NATIVE == idMethod) { String databaseName = tableMap.getDatabaseMap().getDatabase().getName(); Adapter adapter = Torque.getAdapter(databaseName); if (adapter == null) { throw new TorqueException( "missing adapter configuration for database " + databaseName + "check the Torque configuration"); } idMethod = adapter.getIDMethodType(); } Object keyInfo = tableMap.getPrimaryKeyMethodInfo(idMethod); return keyInfo; } /** * Create an Id for insertion in the Criteria * * @param pk ColumnMap for the Primary key * @param keyGen The Id Generator object * @param con The SQL Connection to run the id generation under * @param keyInfo KeyInfo Parameter from the Table map * * @return A simple Key representing the new Id value * @throws TorqueException Possible errors get wrapped in here. */ private SimpleKey getId( ColumnMap pk, IdGenerator keyGen, Connection con, Object keyInfo) throws TorqueException { SimpleKey id = null; try { if (pk != null && keyGen != null) { if (pk.getType() instanceof Number) { id = new NumberKey( keyGen.getIdAsBigDecimal(con, keyInfo)); } else { id = new StringKey(keyGen.getIdAsString(con, keyInfo)); } } } catch (Exception e) { if (e instanceof TorqueException) { throw (TorqueException) e; } else { throw new TorqueException(e); } } return id; } /** * Add all the columns needed to create a new object. * * @param criteria object containing the columns to add. * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public void addSelectColumns(org.apache.torque.criteria.Criteria criteria) throws TorqueException { ColumnMap[] columns = this.tableMap.getColumns(); for (ColumnMap c : columns) { criteria.addSelectColumn(c); } } /** * Selects objects from a database. * * @param criteria object used to create the SELECT statement. * * @return the list of selected objects, not null. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public List doSelect(org.apache.torque.criteria.Criteria criteria) throws TorqueException { if (criteria.getSelectColumns().size() == 0) { addSelectColumns(criteria); } setDbName(criteria); return doSelect( criteria, getRecordMapper(), getTableMap()); } /** * Selects objects from a database * within a transaction. * * @param criteria object used to create the SELECT statement. * @param connection the connection to use, not null. * * @return the list of selected objects, not null. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public List doSelect( org.apache.torque.criteria.Criteria criteria, Connection connection) throws TorqueException { if (criteria.getSelectColumns().size() == 0) { addSelectColumns(criteria); } setDbName(criteria); return doSelect( criteria, getRecordMapper(), getTableMap(), connection); } /** * Selects at most one object from a database. * * @param criteria object used to create the SELECT statement. * * @return the selected Object, or null if no object was selected. * * @throws TorqueException If more than one record is selected or if * an error occurs when processing the query. */ public T doSelectSingleRecord(org.apache.torque.criteria.Criteria criteria) throws TorqueException { List recordList = doSelect(criteria); T record = null; if (recordList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!recordList.isEmpty()) { record = recordList.get(0); } return record; } /** * Selects at most one object from a database * within a transaction. * * @param criteria object used to create the SELECT statement. * @param connection the connection holding the transaction, not null. * * @return the selected Object, or null if no object was selected. * * @throws TorqueException If more than one record is selected or if * an error occurs when processing the query. */ public T doSelectSingleRecord( org.apache.torque.criteria.Criteria criteria, Connection connection) throws TorqueException { List recordList = doSelect(criteria, connection); T record = null; if (recordList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!recordList.isEmpty()) { record = recordList.get(0); } return record; } /** * Selects rows from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. * * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria, * RecordMapper, TableMap). * This method will be removed in a future version of Torque. */ @Deprecated public List doSelect( Criteria criteria, RecordMapper mapper, TableMap defaultTableMap) throws TorqueException { Connection connection = null; try { connection = Transaction.begin(criteria.getDbName()); List result = doSelect( criteria, mapper, defaultTableMap, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Selects rows from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public List doSelect( org.apache.torque.criteria.Criteria criteria, RecordMapper mapper, TableMap defaultTableMap) throws TorqueException { Connection connection = null; try { connection = Transaction.begin(criteria.getDbName()); List result = doSelect( criteria, mapper, defaultTableMap, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Selects rows from a database an maps them to objects. * * @param query the sql query to execute, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, not null. * @param dbName The name of the database to create the connection for, * or null for the default SDB. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public List doSelect( String query, RecordMapper mapper, TableMap defaultTableMap, String dbName) throws TorqueException { if (dbName == null) { dbName = Torque.getDefaultDB(); } Connection connection = null; try { connection = Transaction.begin(dbName); List result = doSelect( query, mapper, defaultTableMap, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Selects rows from a database an maps them to objects. * * @param query the SQL Query to execute, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, not null. * @param connection the database connection, not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public List doSelect( String query, RecordMapper mapper, TableMap defaultTableMap, Connection connection) throws TorqueException { if (connection == null) { throw new NullPointerException("connection is null"); } List result = new ArrayList(); Statement statement = null; ResultSet resultSet = null; try { statement = connection.createStatement(); long startTime = System.currentTimeMillis(); log.debug("Executing query " + query); resultSet = statement.executeQuery(query.toString()); long queryEndTime = System.currentTimeMillis(); log.trace("query took " + (queryEndTime - startTime) + " milliseconds"); while (resultSet.next()) { TT rowResult = mapper.processRow(resultSet, 0); result.add(rowResult); } long mappingEndTime = System.currentTimeMillis(); log.trace("mapping took " + (mappingEndTime - queryEndTime) + " milliseconds"); } catch (SQLException e) { throw new TorqueException(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.warn("error closing resultSet", e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { log.warn("error closing statement", e); } } } return result; } /** * Performs a SQL select using a PreparedStatement. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, TODO or null ???. * @param connection the database connection for selecting records, * not null. * * @return The results of the query, not null. * * @throws TorqueException Error performing database query. * * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria, * RecordMapper, TableMap). * This method will be removed in a future version of Torque. */ @Deprecated public List doSelect( Criteria criteria, RecordMapper mapper, TableMap defaultTableMap, Connection connection) throws TorqueException { correctBooleans(criteria, defaultTableMap); Query query = SqlBuilder.buildQuery(criteria); if (query.getFromClause().isEmpty() && defaultTableMap != null) { String tableName = SqlBuilder.getFullTableName( defaultTableMap.getName(), criteria.getDbName()); query.getFromClause().add(new FromElement(tableName)); } PreparedStatement statement = null; ResultSet resultSet = null; try { statement = connection.prepareStatement(query.toString()); List replacements = setPreparedStatementReplacements( statement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing query " + query + ", parameters = " + replacements); resultSet = statement.executeQuery(); long queryEndTime = System.currentTimeMillis(); log.trace("query took " + (queryEndTime - startTime) + " milliseconds"); long offset; Database database = Torque.getDatabase(criteria.getDbName()); if (database.getAdapter().supportsNativeOffset()) { offset = 0; //database takes care of offset } else { offset = criteria.getOffset(); } long limit; if (database.getAdapter().supportsNativeLimit()) { limit = -1; //database takes care of offset } else { if (database.getAdapter().supportsNativeOffset()) { limit = criteria.getLimit(); } else { if (criteria.getLimit() == -1) { limit = criteria.getLimit(); } else { limit = offset + criteria.getLimit(); } } } List result = new ArrayList(); int rowNumber = 0; while (resultSet.next()) { if (rowNumber < offset) { rowNumber++; continue; } if (limit >= 0 && rowNumber >= limit) { break; } TT rowResult = mapper.processRow(resultSet, 0); result.add(rowResult); rowNumber++; } long mappingEndTime = System.currentTimeMillis(); log.trace("mapping took " + (mappingEndTime - queryEndTime) + " milliseconds"); if (criteria.isSingleRecord() && result.size() > 1) { throw new TooManyRowsException( "Criteria expected single Record and " + "Multiple Records were selected"); } return result; } catch (SQLException e) { throw new TorqueException(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.warn("error closing resultSet", e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { log.warn("error closing statement", e); } } } } /** * Performs a SQL select using a PreparedStatement. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, TODO or null ???. * @param connection the database connection for selecting records, * not null. * * @return The results of the query, not null. * * @throws TorqueException Error performing database query. */ public List doSelect( org.apache.torque.criteria.Criteria criteria, RecordMapper mapper, TableMap defaultTableMap, Connection connection) throws TorqueException { correctBooleans(criteria, defaultTableMap); Query query = SqlBuilder.buildQuery(criteria); if (query.getFromClause().isEmpty() && defaultTableMap != null) { String tableName = SqlBuilder.getFullTableName( defaultTableMap.getName(), criteria.getDbName()); query.getFromClause().add(new FromElement(tableName)); } PreparedStatement statement = null; ResultSet resultSet = null; try { statement = connection.prepareStatement(query.toString()); if (query.getFetchSize() != null) { statement.setFetchSize(query.getFetchSize()); } List replacements = setPreparedStatementReplacements( statement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing query " + query + ", parameters = " + replacements); resultSet = statement.executeQuery(); long queryEndTime = System.currentTimeMillis(); log.trace("query took " + (queryEndTime - startTime) + " milliseconds"); long offset; Database database = Torque.getDatabase(criteria.getDbName()); if (database.getAdapter().supportsNativeOffset()) { offset = 0; //database takes care of offset } else { offset = criteria.getOffset(); } long limit; if (database.getAdapter().supportsNativeLimit()) { limit = -1; //database takes care of offset } else { if (database.getAdapter().supportsNativeOffset()) { limit = criteria.getLimit(); } else { if (criteria.getLimit() == -1) { limit = criteria.getLimit(); } else { limit = offset + criteria.getLimit(); } } } List result = new ArrayList(); int rowNumber = 0; while (resultSet.next()) { if (rowNumber < offset) { rowNumber++; continue; } if (limit >= 0 && rowNumber >= limit) { break; } TT rowResult = mapper.processRow(resultSet, 0); result.add(rowResult); rowNumber++; } long mappingEndTime = System.currentTimeMillis(); log.trace("mapping took " + (mappingEndTime - queryEndTime) + " milliseconds"); if (criteria.isSingleRecord() && result.size() > 1) { throw new TooManyRowsException( "Criteria expected single Record and " + "Multiple Records were selected"); } return result; } catch (SQLException e) { throw new TorqueException(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.warn("error closing resultSet", e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { log.warn("error closing statement", e); } } } } /** * Selects at most a single row from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, not null. * * @return The selected row, or null if no records was selected. * * @throws TorqueException if querying the database fails. */ public T doSelectSingleRecord( org.apache.torque.criteria.Criteria criteria, RecordMapper mapper, TableMap defaultTableMap) throws TorqueException { List resultList = doSelect(criteria, mapper, defaultTableMap); T result = null; if (resultList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!resultList.isEmpty()) { result = resultList.get(0); } return result; } /** * Selects at most a single row from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param defaultTableMap The table map used for the * unqualified columns in the query, not null. * @param connection the database connection, not null. * * @return The selected row, or null if no records was selected. * * @throws TorqueException if querying the database fails. */ public T doSelectSingleRecord( org.apache.torque.criteria.Criteria criteria, RecordMapper mapper, TableMap defaultTableMap, Connection connection) throws TorqueException { List resultList = doSelect( criteria, mapper, defaultTableMap, connection); T result = null; if (resultList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!resultList.isEmpty()) { result = resultList.get(0); } return result; } /** * Convenience method used to update rows in the DB. Checks if a * single primary key is specified in the Criteria * object and uses it to perform the update. If no primary key is * specified or the table has multiple primary keys, * an Exception will be thrown. *

* Use this method for performing an update of the kind: *

* "WHERE primary_key_id = someValue" *

* To perform an update on a table with multiple primary keys or * an update with non-primary key fields in the WHERE * clause, use doUpdate(ColumnValues, Criteria). * * @param updateValues Which columns to update with which values * for which primary key value, not null. * * @return the number of affected rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doUpdate(ColumnValues updateValues) throws TorqueException { String databaseName = updateValues.getDbName(); if (databaseName == null) { TableMap table = updateValues.getTable(); databaseName = table.getDatabaseMap().getDatabase().getName(); } Connection connection = null; try { connection = Transaction.begin(databaseName); int result = doUpdate(updateValues, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Convenience method used to update rows in the DB. Checks if a * single primary key is specified in the Criteria * object and uses it to perform the update. If no primary key is * specified or the table has multiple primary keys, * an Exception will be thrown. *

* Use this method for performing an update of the kind: *

* "WHERE primary_key_id = someValue" *

* To perform an update on a table with multiple primary keys or * an update with non-primary key fields in the WHERE * clause, use doUpdate(ColumnValues, Criteria, Connection). * * @param updateValues Which columns to update with which values * for which primary key value, not null. * @param connection the database connection to use. * * @return the number of affected rows. * * @param updateValues A map keyed by the column names * containing the column's values in its values. * @param connection the database connection to use. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doUpdate( ColumnValues updateValues, Connection connection) throws TorqueException { TableMap table = updateValues.getTable(); ColumnMap pk = table.getPrimaryKey(); org.apache.torque.criteria.Criteria selectCriteria = null; if (pk != null && updateValues.containsKey(pk.getSqlExpression())) { selectCriteria = new org.apache.torque.criteria.Criteria(); selectCriteria.where(pk, updateValues.remove(pk.getSqlExpression())); } else { throw new TorqueException("No PK specified for database update"); } return doUpdate(selectCriteria, updateValues, connection); } /** * Executes an update against the database. The rows to be updated * are selected using criteria and updated using the values * in updateValues. * * @param criteria selects which rows of which table should be updated. * @param updateValues Which columns to update with which values, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. * * @deprecated Please use doUpdate( * org.apache.torque.criteria.Criteria, ColumnValues). * This method will be removed in a future version of Torque. */ @Deprecated public int doUpdate( Criteria selectCriteria, ColumnValues updateValues) throws TorqueException { String databaseName = updateValues.getDbName(); if (databaseName == null) { TableMap table = updateValues.getTable(); databaseName = table.getDatabaseMap().getDatabase().getName(); } Connection connection = null; try { connection = Transaction.begin(databaseName); int result = doUpdate(selectCriteria, updateValues, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Executes an update against the database. The rows to be updated * are selected using criteria and updated using the values * in updateValues. * * @param criteria selects which rows of which table should be updated. * @param updateValues Which columns to update with which values, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. */ public int doUpdate( org.apache.torque.criteria.Criteria selectCriteria, ColumnValues updateValues) throws TorqueException { String databaseName = updateValues.getDbName(); if (databaseName == null) { TableMap table = updateValues.getTable(); databaseName = table.getDatabaseMap().getDatabase().getName(); } Connection connection = null; try { connection = Transaction.begin(databaseName); int result = doUpdate(selectCriteria, updateValues, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Executes an update against the database. The rows to be updated * are selected using criteria and updated using the values * in updateValues. * * @param criteria selects which rows of which table should be updated. * @param updateValues Which columns to update with which values, not null. * @param connection the database connection to use, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. * * @deprecated Please use doUpdate(org.apache.torque.criteria.Criteria, * ColumnValues, Connection). * This method will be removed in a future version of Torque. */ @Deprecated public int doUpdate( Criteria criteria, ColumnValues updateValues, Connection connection) throws TorqueException { Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.UPDATE); query.getFromClause().clear(); String fullTableName = SqlBuilder.getFullTableName( updateValues.getTable().getName(), criteria.getDbName()); query.getFromClause().add(new FromElement(fullTableName)); List replacementObjects = new ArrayList(); for (Map.Entry updateValue : updateValues.entrySet()) { Column column = updateValue.getKey(); query.getSelectClause().add(column.getColumnName()); replacementObjects.add(updateValue.getValue()); } PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(query.toString()); int position = 1; for (JdbcTypedValue replacementObject : replacementObjects) { Object value = replacementObject.getValue(); if (value != null) { preparedStatement.setObject(position, value); } else { preparedStatement.setNull( position, replacementObject.getJdbcType()); } position++; } List replacements = setPreparedStatementReplacements( preparedStatement, query.getPreparedStatementReplacements(), position - 1); long startTime = System.currentTimeMillis(); log.debug("Executing update " + query.toString() + " using update parameters " + replacementObjects + " and query parameters " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("update took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw new TorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Executes an update against the database. The rows to be updated * are selected using criteria and updated using the values * in updateValues. * * @param criteria selects which rows of which table should be updated. * @param updateValues Which columns to update with which values, not null. * @param connection the database connection to use, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. */ public int doUpdate( org.apache.torque.criteria.Criteria criteria, ColumnValues updateValues, Connection connection) throws TorqueException { Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.UPDATE); query.getFromClause().clear(); String fullTableName = SqlBuilder.getFullTableName( updateValues.getTable().getName(), criteria.getDbName()); query.getFromClause().add(new FromElement(fullTableName)); List replacementObjects = new ArrayList(); for (Map.Entry updateValue : updateValues.entrySet()) { Column column = updateValue.getKey(); query.getSelectClause().add(column.getColumnName()); replacementObjects.add(updateValue.getValue()); } PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(query.toString()); int position = 1; for (JdbcTypedValue replacementObject : replacementObjects) { Object value = replacementObject.getValue(); if (value != null) { preparedStatement.setObject(position, value); } else { preparedStatement.setNull( position, replacementObject.getJdbcType()); } position++; } List replacements = setPreparedStatementReplacements( preparedStatement, query.getPreparedStatementReplacements(), position - 1); long startTime = System.currentTimeMillis(); log.debug("Executing update " + query.toString() + " using update parameters " + replacementObjects + " and query parameters " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("update took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw new TorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Utility method which executes a given sql statement. This * method should be used for update, insert, and delete * statements. Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * @return The number of rows affected. * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int executeStatement(String statementString) throws TorqueException { return executeStatement(statementString, Torque.getDefaultDB()); } /** * Utility method which executes a given sql statement. This * method should be used for update, insert, and delete * statements. Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * @param dbName Name of database to connect to. * @return The number of rows affected. * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int executeStatement(String statementString, String dbName) throws TorqueException { Connection con = null; int rowCount = -1; try { con = Torque.getConnection(dbName); rowCount = executeStatement(statementString, con); } finally { Torque.closeConnection(con); } return rowCount; } /** * Utility method which executes a given sql statement. This * method should be used for update, insert, and delete * statements. Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * @param con A Connection. * @return The number of rows affected. * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int executeStatement(String statementString, Connection con) throws TorqueException { int rowCount = -1; Statement statement = null; try { statement = con.createStatement(); rowCount = statement.executeUpdate(statementString); } catch (SQLException e) { throw new TorqueException(e); } finally { if (statement != null) { try { statement.close(); } catch (SQLException e) { throw new TorqueException(e); } } } return rowCount; } /** * Sets the prepared statement replacements into a query, possibly * modifying the type if required by DB Drivers. * * @param statement the statement to set the parameters in, not null. * @param replacements the replacements to set, not null. * @param offset the offset on the parameters, 0 for no offset. * * @return the parameters set. * * @throws SQLException if setting the parameter fails. */ private List setPreparedStatementReplacements( PreparedStatement statement, List replacements, int offset) throws SQLException { List result = new ArrayList(replacements.size()); int i = 1 + offset; for (Object param : replacements) { if (param instanceof java.sql.Timestamp) { statement.setTimestamp(i, (java.sql.Timestamp) param); result.add(param); } else if (param instanceof java.sql.Date) { statement.setDate(i, (java.sql.Date) param); result.add(param); } else if (param instanceof java.util.Date) { java.sql.Timestamp sqlDate = new java.sql.Timestamp( ((java.util.Date) param).getTime()); statement.setTimestamp(i, sqlDate); result.add(sqlDate); } else if (param instanceof NumberKey) { BigDecimal bigDecimal = ((NumberKey) param).getBigDecimal(); statement.setBigDecimal(i, bigDecimal); result.add(bigDecimal); } else if (param instanceof Integer) { statement.setInt(i, ((Integer) param).intValue()); result.add(param); } else if (param instanceof Long) { statement.setLong(i, ((Long) param).longValue()); result.add(param); } else if (param instanceof BigDecimal) { statement.setBigDecimal(i, (BigDecimal) param); result.add(param); } else if (param instanceof Boolean) { statement.setBoolean(i, ((Boolean) param).booleanValue()); result.add(param); } else { statement.setString(i, param.toString()); result.add(param.toString()); } ++i; } return result; } /** * changes the boolean values in the criteria to the appropriate type, * whenever a booleanchar or booleanint column is involved. * This enables the user to create criteria using Boolean values * for booleanchar or booleanint columns * @param criteria the criteria in which the boolean values should be corrected * @throws TorqueException if the database map for the criteria cannot be obtained. */ public void correctBooleans(org.apache.torque.criteria.Criteria criteria) throws TorqueException { correctBooleans(criteria, getTableMap()); } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param criteria The criteria to be checked for booleanint and booleanchar * columns. * @param defaultTableMap the table map to be used if the table name is * not given in a column. * @throws TorqueException if the database map for the criteria cannot be * retrieved. * * @deprecated Please use correctBooleans( * org.apache.torque.criteria.Criteria, TableMap). * This method will be removed in a future version of Torque. */ @Deprecated public void correctBooleans( Criteria criteria, TableMap defaultTableMap) throws TorqueException { for (Object criterionObject : criteria.values()) { Criteria.Criterion criterion = (Criteria.Criterion) criterionObject; correctBooleans(criteria, criterion, defaultTableMap); } } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param criteria The criteria to which teh criterion belongs. * @param criterion The criterion to be checked for booleanint * and booleanchar columns. * @param defaultTableMap the table map to be used if the table name is * not given in a column. * @throws TorqueException if the database map for the criteria cannot be * retrieved. * * @deprecated */ @Deprecated private void correctBooleans( Criteria criteria, Criteria.Criterion criterion, TableMap defaultTableMap) throws TorqueException { Column column = criterion.getColumn(); TableMap tableMap = MapHelper.getTableMap( column, criteria, defaultTableMap); // if no description of table available, do not modify anything if (tableMap != null) { String columnName = column.getColumnName(); ColumnMap columnMap = tableMap.getColumn(columnName); if (columnMap != null) { if ("BOOLEANINT".equals(columnMap.getTorqueType())) { replaceBooleanValues( criterion, Integer.valueOf(1), Integer.valueOf(0)); } else if ("BOOLEANCHAR".equals(columnMap.getTorqueType())) { replaceBooleanValues(criterion, "Y", "N"); } } } for (Criteria.Criterion attachedCriterion : criterion.getClauses()) { correctBooleans(criteria, attachedCriterion, defaultTableMap); } } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param criteria The criteria to be checked for booleanint and booleanchar * columns. * @param defaultTableMap the table map to be used if the table name is * not given in a column. * @throws TorqueException if the database map for the criteria cannot be * retrieved. */ public void correctBooleans( org.apache.torque.criteria.Criteria criteria, TableMap defaultTableMap) throws TorqueException { correctBooleans( criteria, criteria.getTopLevelCriterion(), defaultTableMap); } private void correctBooleans( org.apache.torque.criteria.Criteria criteria, org.apache.torque.criteria.Criterion criterion, TableMap defaultTableMap) throws TorqueException { if (criterion == null) { return; } if (criterion.isComposite()) { for (org.apache.torque.criteria.Criterion part : criterion.getParts()) { correctBooleans(criteria, part, defaultTableMap); } return; } Object possibleColumn = criterion.getLValue(); TableMap tableMap = MapHelper.getTableMap( possibleColumn, criteria, defaultTableMap); // if no description of table available, do not modify anything if (tableMap == null) { return; } String columnName = ((Column) possibleColumn).getColumnName(); ColumnMap columnMap = tableMap.getColumn(columnName); if (columnMap != null) { if ("BOOLEANINT".equals(columnMap.getTorqueType())) { replaceBooleanValues( criterion, Integer.valueOf(1), Integer.valueOf(0)); } else if ("BOOLEANCHAR".equals(columnMap.getTorqueType())) { replaceBooleanValues(criterion, "Y", "N"); } } } /** * Replaces any Boolean value in the criterion and its attached Criterions * by trueValue if the Boolean equals Boolean.TRUE * and falseValue if the Boolean equals Boolean.FALSE. * * @param criterion the criterion to replace Boolean values in. * @param trueValue the value by which Boolean.TRUE should be replaced. * @param falseValue the value by which Boolean.FALSE should be replaced. * * @deprecated */ @Deprecated private void replaceBooleanValues( Criteria.Criterion criterion, Object trueValue, Object falseValue) { // attachedCriterions also contains the criterion itself, // so no additional treatment is needed for the criterion itself. Criteria.Criterion[] attachedCriterions = criterion.getAttachedCriterion(); for (int i = 0; i < attachedCriterions.length; ++i) { Object criterionValue = attachedCriterions[i].getValue(); if (criterionValue instanceof Boolean) { Boolean booleanValue = (Boolean) criterionValue; attachedCriterions[i].setValue( Boolean.TRUE.equals(booleanValue) ? trueValue : falseValue); } } } /** * Replaces any Boolean value in the criterion and its attached Criterions * by trueValue if the Boolean equals Boolean.TRUE * and falseValue if the Boolean equals Boolean.FALSE. * * @param criterion the criterion to replace Boolean values in. * May not be a composite criterion. * @param trueValue the value by which Boolean.TRUE should be replaced. * @param falseValue the value by which Boolean.FALSE should be replaced. */ private void replaceBooleanValues( org.apache.torque.criteria.Criterion criterion, Object trueValue, Object falseValue) { Object rValue = criterion.getRValue(); if (rValue instanceof Boolean) { Boolean booleanValue = (Boolean) rValue; criterion.setRValue( Boolean.TRUE.equals(booleanValue) ? trueValue : falseValue); } Object lValue = criterion.getLValue(); if (lValue instanceof Boolean) { Boolean booleanValue = (Boolean) lValue; criterion.setLValue( Boolean.TRUE.equals(booleanValue) ? trueValue : falseValue); } } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param columnValues The value to be checked for booleanint * and booleanchar columns. * @param defaultTableMap the table map to be used if the table name is * not given in a column. * @throws TorqueException if the database map for the criteria cannot be * retrieved. */ public void correctBooleans( ColumnValues columnValues) throws TorqueException { TableMap table = columnValues.getTable(); for (Map.Entry entry : columnValues.entrySet()) { String columnName = entry.getKey().getColumnName(); ColumnMap column = table.getColumn(columnName); if (column != null) { JdbcTypedValue columnValue = entry.getValue(); if ("BOOLEANINT".equals(column.getTorqueType())) { if (Boolean.TRUE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue(1, Types.INTEGER)); } else if (Boolean.FALSE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue(0, Types.INTEGER)); } else if (columnValue.getValue() == null) { entry.setValue(new JdbcTypedValue(null, Types.INTEGER)); } } else if ("BOOLEANCHAR".equals(column.getTorqueType())) { if (Boolean.TRUE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue("Y", Types.CHAR)); } else if (Boolean.FALSE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue("N", Types.CHAR)); } else if (columnValue.getValue() == null) { entry.setValue(new JdbcTypedValue(null, Types.CHAR)); } } } } } /** * Sets the database name in the passed criteria to the table's default, * if it is not already set. * * @param crit the criteria to set the database name in, not null. */ protected void setDbName(org.apache.torque.criteria.Criteria crit) throws TorqueException { if (!Torque.isInit()) { throw new TorqueException("Torque is not initialized"); } if (crit.getDbName() == null) { crit.setDbName(getDatabaseName()); } } } --------------080702050307000306090300 Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0"; name="BaseAuthorPeerImpl.java" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="BaseAuthorPeerImpl.java" cGFja2FnZSBvcmcuYXBhY2hlLnRvcnF1ZS50ZXN0OwoKaW1wb3J0IGphdmEuc3FsLkJsb2I7 CmltcG9ydCBqYXZhLnNxbC5DbG9iOwppbXBvcnQgamF2YS5zcWwuQ29ubmVjdGlvbjsKaW1w b3J0IGphdmEuc3FsLlNRTEV4Y2VwdGlvbjsKaW1wb3J0IGphdmEuc3FsLlJlc3VsdFNldDsK aW1wb3J0IGphdmEuc3FsLlByZXBhcmVkU3RhdGVtZW50OwppbXBvcnQgamF2YS5zcWwuVHlw ZXM7CmltcG9ydCBqYXZhLmlvLklPRXhjZXB0aW9uOwppbXBvcnQgamF2YS5pby5JbnB1dFN0 cmVhbTsKaW1wb3J0IGphdmEuaW8uQnl0ZUFycmF5SW5wdXRTdHJlYW07CmltcG9ydCBqYXZh LmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbTsKaW1wb3J0IGphdmEuaW8uUmVhZGVyOwppbXBv cnQgamF2YS5pby5TdHJpbmdSZWFkZXI7CmltcG9ydCBqYXZhLmlvLlN0cmluZ1dyaXRlcjsK aW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlv bjsKaW1wb3J0IGphdmEudXRpbC5EYXRlOwppbXBvcnQgamF2YS51dGlsLkl0ZXJhdG9yOwpp bXBvcnQgamF2YS51dGlsLkxpbmtlZExpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1w b3J0IGphdmEudXRpbC5NYXA7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGph dmEudXRpbC5TZXQ7CmltcG9ydCBqYXZhLnV0aWwuSGFzaFNldDsKCmltcG9ydCBvcmcuYXBh Y2hlLmNvbW1vbnMubG9nZ2luZy5Mb2c7CmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMubG9n Z2luZy5Mb2dGYWN0b3J5OwppbXBvcnQgb3JnLmFwYWNoZS50b3JxdWUuTm9Sb3dzRXhjZXB0 aW9uOwppbXBvcnQgb3JnLmFwYWNoZS50b3JxdWUuVG9vTWFueVJvd3NFeGNlcHRpb247Cmlt cG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS5Ub3JxdWU7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1 ZS5Ub3JxdWVFeGNlcHRpb247CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS5Ub3JxdWVSdW50 aW1lRXhjZXB0aW9uOwppbXBvcnQgb3JnLmFwYWNoZS50b3JxdWUuY3JpdGVyaWEuQ3JpdGVy aWE7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS5jcml0ZXJpYS5Dcml0ZXJpb247CmltcG9y dCBvcmcuYXBhY2hlLnRvcnF1ZS5tYXAuVGFibGVNYXA7CmltcG9ydCBvcmcuYXBhY2hlLnRv cnF1ZS5vbS5tYXBwZXIuUmVjb3JkTWFwcGVyOwppbXBvcnQgb3JnLmFwYWNoZS50b3JxdWUu b20ubWFwcGVyLkNvbXBvc2l0ZU1hcHBlcjsKaW1wb3J0IG9yZy5hcGFjaGUudG9ycXVlLm9t LkRhdGVLZXk7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS5vbS5OdW1iZXJLZXk7CmltcG9y dCBvcmcuYXBhY2hlLnRvcnF1ZS5vbS5TdHJpbmdLZXk7CmltcG9ydCBvcmcuYXBhY2hlLnRv cnF1ZS5vbS5PYmplY3RLZXk7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS5vbS5TaW1wbGVL ZXk7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS5vbS5Db21ib0tleTsKaW1wb3J0IG9yZy5h cGFjaGUudG9ycXVlLnV0aWwuQmFzZVBlZXI7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS51 dGlsLlRyYW5zYWN0aW9uOwppbXBvcnQgb3JnLmFwYWNoZS50b3JxdWUudXRpbC5Db2x1bW5W YWx1ZXM7CmltcG9ydCBvcmcuYXBhY2hlLnRvcnF1ZS51dGlsLkpkYmNUeXBlZFZhbHVlOwoK aW1wb3J0IG9yZy5hcGFjaGUudG9ycXVlLnRlc3QubWFwLio7CgoKLyoqCiAqIEF1dGhvciB0 YWJsZQogKgogKiBUaGUgc2tlbGV0b24gZm9yIHRoaXMgY2xhc3Mgd2FzIGF1dG9nZW5lcmF0 ZWQgYnkgVG9ycXVlIG9uOgogKgogKiBbU3VuIEp1bCAyMiAxODowMjoyNiBDRVNUIDIwMTJd CiAqCiAqIFlvdSBzaG91bGQgbm90IHVzZSB0aGlzIGNsYXNzIGRpcmVjdGx5LiAgSXQgc2hv dWxkIG5vdCBldmVuIGJlCiAqIGV4dGVuZGVkOyBhbGwgcmVmZXJlbmNlcyBzaG91bGQgYmUg dG8gQXV0aG9yUGVlcgogKi8KCnB1YmxpYyBhYnN0cmFjdCBjbGFzcyBCYXNlQXV0aG9yUGVl ckltcGwKICAgIGV4dGVuZHMgb3JnLmFwYWNoZS50b3JxdWUudXRpbC5CYXNlUGVlckltcGw8 QXV0aG9yPgp7CiAgICAvKiogVGhlIGNsYXNzIGxvZy4gKi8KICAgIHByaXZhdGUgc3RhdGlj IExvZyBsb2cgPSBMb2dGYWN0b3J5LmdldExvZyhCYXNlQXV0aG9yUGVlckltcGwuY2xhc3Mp OwoKICAgIC8qKiBTZXJpYWwgdmVyc2lvbiAqLwogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwg bG9uZyBzZXJpYWxWZXJzaW9uVUlEID0gMTM0Mjk3Mjk0NjE5M0w7CgoKCiAgICAvKioKICAg ICAqIFNlbGVjdHMgQXV0aG9yIG9iamVjdHMgZnJvbSB0aGUgZGF0YWJhc2Ugd2hpY2ggaGF2 ZQogICAgICogdGhlIHNhbWUgY29udGVudCBhcyB0aGUgcGFzc2VkIG9iamVjdC4KICAgICAq CiAgICAgKiBAcmV0dXJuIFRoZSBsaXN0IG9mIHNlbGVjdGVkIG9iamVjdHMsIG5vdCBudWxs LgogICAgICoKICAgICAqIEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25z IGNhdWdodCBkdXJpbmcgcHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhy b3duIHdyYXBwZWQgaW50byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGlj IExpc3Q8QXV0aG9yPiBkb1NlbGVjdChBdXRob3Igb2JqKQogICAgICAgICAgICB0aHJvd3Mg VG9ycXVlRXhjZXB0aW9uCiAgICB7CiAgICAgICAgcmV0dXJuIGRvU2VsZWN0KGJ1aWxkU2Vs ZWN0Q3JpdGVyaWEob2JqKSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBTZWxlY3RzIGF0IG1v c3Qgb25lIEF1dGhvciBvYmplY3QgZnJvbSB0aGUgZGF0YWJhc2UKICAgICAqIHdoaWNoIGhh cyB0aGUgc2FtZSBjb250ZW50IGFzIHRoZSBwYXNzZWQgb2JqZWN0LgogICAgICoKICAgICAq IEByZXR1cm4gdGhlIHNlbGVjdGVkIE9iamVjdCwgb3IgbnVsbCBpZiBubyBvYmplY3Qgd2Fz IHNlbGVjdGVkLgogICAgICoKICAgICAqIEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBl eGNlcHRpb25zIGNhdWdodCBkdXJpbmcgcHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAg ICAgIHJldGhyb3duIHdyYXBwZWQgaW50byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwog ICAgcHVibGljIEF1dGhvciBkb1NlbGVjdFNpbmdsZVJlY29yZCgKICAgICAgICAgICAgICAg IEF1dGhvciBvYmopCiAgICAgICAgICAgIHRocm93cyBUb3JxdWVFeGNlcHRpb24KICAgIHsK ICAgICAgICBMaXN0PEF1dGhvcj4gYXV0aG9yTGlzdCA9IGRvU2VsZWN0KG9iaik7CiAgICAg ICAgQXV0aG9yIGF1dGhvciA9IG51bGw7CiAgICAgICAgaWYgKGF1dGhvckxpc3Quc2l6ZSgp ID4gMSkKICAgICAgICB7CiAgICAgICAgICAgIHRocm93IG5ldyBUb29NYW55Um93c0V4Y2Vw dGlvbigiT2JqZWN0ICIgKyBvYmogCiAgICAgICAgICAgICAgICArICIgbWF0Y2hlZCBtb3Jl IHRoYW4gb25lIHJlY29yZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWF1dGhvckxpc3Qu aXNFbXB0eSgpKQogICAgICAgIHsKICAgICAgICAgICAgYXV0aG9yID0gYXV0aG9yTGlzdC5n ZXQoMCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhdXRob3I7CiAgICB9CgogICAgLyoq DQogICAgICogUmV0dXJucyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgRGF0YSBvYmplY3QgY2xh c3MNCiAgICAgKi8NCiAgICBwdWJsaWMgQXV0aG9yIGdldERiT2JqZWN0SW5zdGFuY2UoKQ0K ICAgIHsNCiAgICAgICAgcmV0dXJuIG5ldyBBdXRob3IoKTsNCiAgICB9DQoNCgogICAgLyoq CiAgICAgKiBNZXRob2QgdG8gZG8gaW5zZXJ0cy4KICAgICAqCiAgICAgKiBAcGFyYW0gY29s dW1uVmFsdWVzIHRoZSB2YWx1ZXMgdG8gaW5zZXJ0LgogICAgICoKICAgICAqIEByZXR1cm4g dGhlIHByaW1hcnkga2V5IG9mIHRoZSBpbnNlcnRlZCByb3cuCiAgICAgKgogICAgICogQHRo cm93cyBUb3JxdWVFeGNlcHRpb24gQW55IGV4Y2VwdGlvbnMgY2F1Z2h0IGR1cmluZyBwcm9j ZXNzaW5nIHdpbGwgYmUKICAgICAqICAgICAgICAgcmV0aHJvd24gd3JhcHBlZCBpbnRvIGEg VG9ycXVlRXhjZXB0aW9uLgogICAgICovCiAgICBwdWJsaWMgT2JqZWN0S2V5IGRvSW5zZXJ0 KENvbHVtblZhbHVlcyBjb2x1bW5WYWx1ZXMpIHRocm93cyBUb3JxdWVFeGNlcHRpb24KICAg IHsKICAgICAgICBDb25uZWN0aW9uIGNvbm5lY3Rpb24gPSBudWxsOwogICAgICAgIHRyeQog ICAgICAgIHsKICAgICAgICAgICAgY29ubmVjdGlvbiA9IFRyYW5zYWN0aW9uLmJlZ2luKAog ICAgICAgICAgICAgICAgICAgIEF1dGhvclBlZXIuREFUQUJBU0VfTkFNRSk7CiAgICAgICAg ICAgIE9iamVjdEtleSByZXN1bHQgPSBkb0luc2VydChjb2x1bW5WYWx1ZXMsIGNvbm5lY3Rp b24pOwogICAgICAgICAgICBUcmFuc2FjdGlvbi5jb21taXQoY29ubmVjdGlvbik7CiAgICAg ICAgICAgIGNvbm5lY3Rpb24gPSBudWxsOwogICAgICAgICAgICByZXR1cm4gcmVzdWx0Owog ICAgICAgIH0KICAgICAgICBmaW5hbGx5CiAgICAgICAgewogICAgICAgICAgICBpZiAoY29u bmVjdGlvbiAhPSBudWxsKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBUcmFuc2Fj dGlvbi5zYWZlUm9sbGJhY2soY29ubmVjdGlvbik7CiAgICAgICAgICAgIH0KICAgICAgICB9 CiAgICB9CgogICAgLyoqCiAgICAgKiBNZXRob2QgdG8gZG8gaW5zZXJ0cy4gIFRoaXMgbWV0 aG9kIGlzIHRvIGJlIHVzZWQgZHVyaW5nIGEgdHJhbnNhY3Rpb24sCiAgICAgKiBvdGhlcndp c2UgdXNlIHRoZSBkb0luc2VydChDcml0ZXJpYSkgbWV0aG9kLgogICAgICoKICAgICAqIEBw YXJhbSBjb2x1bW5WYWx1ZXMgdGhlIHZhbHVlcyB0byBpbnNlcnQuCiAgICAgKiBAcGFyYW0g Y29uIHRoZSBjb25uZWN0aW9uIHRvIHVzZSwgbm90IG51bGwuCiAgICAgKgogICAgICogQHJl dHVybiB0aGUgcHJpbWFyeSBrZXkgb2YgdGhlIGluc2VydGVkIHJvdy4KICAgICAqCiAgICAg KiBAdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbiBBbnkgZXhjZXB0aW9ucyBjYXVnaHQgZHVyaW5n IHByb2Nlc3Npbmcgd2lsbCBiZQogICAgICogICAgICAgICByZXRocm93biB3cmFwcGVkIGlu dG8gYSBUb3JxdWVFeGNlcHRpb24uCiAgICAgKi8KICAgIHB1YmxpYyBPYmplY3RLZXkgZG9J bnNlcnQoQ29sdW1uVmFsdWVzIGNvbHVtblZhbHVlcywgQ29ubmVjdGlvbiBjb24pCiAgICAg ICAgdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbgogICAgewogICAgICAgIGNvcnJlY3RCb29sZWFu cyhjb2x1bW5WYWx1ZXMpOwogICAgICAgIHJldHVybiBzdXBlci5kb0luc2VydChjb2x1bW5W YWx1ZXMsIGNvbik7CiAgICB9CgogICAgLyoqCiAgICAgKiBNZXRob2QgdG8gZG8gaW5zZXJ0 cwogICAgICoKICAgICAqIEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25z IGNhdWdodCBkdXJpbmcgcHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhy b3duIHdyYXBwZWQgaW50byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGlj IHZvaWQgZG9JbnNlcnQoQXV0aG9yIG9iaikgdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbgogICAg ewogICAgICAgIG9iai5zZXRQcmltYXJ5S2V5KGRvSW5zZXJ0KGJ1aWxkQ29sdW1uVmFsdWVz KG9iaikpKTsKICAgICAgICBvYmouc2V0TmV3KGZhbHNlKTsKICAgICAgICBvYmouc2V0TW9k aWZpZWQoZmFsc2UpOwogICAgfQoKICAgIC8qKgogICAgICogTWV0aG9kIHRvIGRvIGluc2Vy dHMuICBUaGlzIG1ldGhvZCBpcyB0byBiZSB1c2VkIGR1cmluZyBhIHRyYW5zYWN0aW9uLAog ICAgICogb3RoZXJ3aXNlIHVzZSB0aGUgZG9JbnNlcnQoQXV0aG9yKSBtZXRob2QuICBJdCB3 aWxsIHRha2UKICAgICAqIGNhcmUgb2YgdGhlIGNvbm5lY3Rpb24gZGV0YWlscyBpbnRlcm5h bGx5LgogICAgICoKICAgICAqIEBwYXJhbSBvYmogdGhlIGRhdGEgb2JqZWN0IHRvIGluc2Vy dCBpbnRvIHRoZSBkYXRhYmFzZS4KICAgICAqIEBwYXJhbSBjb24gdGhlIGNvbm5lY3Rpb24g dG8gdXNlCiAgICAgKiBAdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbiBBbnkgZXhjZXB0aW9ucyBj YXVnaHQgZHVyaW5nIHByb2Nlc3Npbmcgd2lsbCBiZQogICAgICogICAgICAgICByZXRocm93 biB3cmFwcGVkIGludG8gYSBUb3JxdWVFeGNlcHRpb24uCiAgICAgKi8KICAgIHB1YmxpYyB2 b2lkIGRvSW5zZXJ0KEF1dGhvciBvYmosIENvbm5lY3Rpb24gY29uKQogICAgICAgIHRocm93 cyBUb3JxdWVFeGNlcHRpb24KICAgIHsKICAgICAgICBPYmplY3RLZXkgcHJpbWFyeUtleSA9 IGRvSW5zZXJ0KGJ1aWxkQ29sdW1uVmFsdWVzKG9iaiksIGNvbik7CiAgICAgICAgaWYgKHBy aW1hcnlLZXkgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIG9iai5zZXRQcmltYXJ5 S2V5KHByaW1hcnlLZXkpOwogICAgICAgIH0KICAgICAgICBvYmouc2V0TmV3KGZhbHNlKTsK ICAgICAgICBvYmouc2V0TW9kaWZpZWQoZmFsc2UpOwogICAgfQoKICAgIC8qKgogICAgICog TWV0aG9kIHRvIGRvIHVwZGF0ZXMuCiAgICAgKgogICAgICogQHBhcmFtIGNvbHVtblZhbHVl cyB0aGUgdmFsdWVzIHRvIHVwZGF0ZSBwbHVzIHRoZSBwcmltYXJ5IGtleQogICAgICogICAg ICAgIGlkZW50aWZ5aW5nIHRoZSByb3cgdG8gdXBkYXRlLgogICAgICoKICAgICAqIEByZXR1 cm4gdGhlIG51bWJlciBvZiBhZmZlY3RlZCByb3dzLgogICAgICoKICAgICAqIEB0aHJvd3Mg VG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJpbmcgcHJvY2Vzc2lu ZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQgaW50byBhIFRvcnF1 ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGljIGludCBkb1VwZGF0ZShDb2x1bW5WYWx1 ZXMgY29sdW1uVmFsdWVzKSB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uCiAgICB7CiAgICAgICAg Q29ubmVjdGlvbiBjb25uZWN0aW9uID0gbnVsbDsKICAgICAgICB0cnkKICAgICAgICB7CiAg ICAgICAgICAgIGNvbm5lY3Rpb24gPSBUcmFuc2FjdGlvbi5iZWdpbigKICAgICAgICAgICAg ICAgICAgICBBdXRob3JQZWVyLkRBVEFCQVNFX05BTUUpOwogICAgICAgICAgICBpbnQgcmVz dWx0ID0gZG9VcGRhdGUoY29sdW1uVmFsdWVzLCBjb25uZWN0aW9uKTsKICAgICAgICAgICAg VHJhbnNhY3Rpb24uY29tbWl0KGNvbm5lY3Rpb24pOwogICAgICAgICAgICBjb25uZWN0aW9u ID0gbnVsbDsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAg ZmluYWxseQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGNvbm5lY3Rpb24gIT0gbnVsbCkK ICAgICAgICAgICAgewogICAgICAgICAgICAgICAgVHJhbnNhY3Rpb24uc2FmZVJvbGxiYWNr KGNvbm5lY3Rpb24pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8qKgog ICAgICogTWV0aG9kIHRvIGRvIHVwZGF0ZXMuICBUaGlzIG1ldGhvZCBpcyB0byBiZSB1c2Vk IGR1cmluZyBhIHRyYW5zYWN0aW9uLAogICAgICogb3RoZXJ3aXNlIHVzZSB0aGUgZG9VcGRh dGUoQ3JpdGVyaWEpIG1ldGhvZC4KICAgICAqCiAgICAgKiBAcGFyYW0gY29sdW1uVmFsdWVz IHRoZSB2YWx1ZXMgdG8gdXBkYXRlIHBsdXMgdGhlIHByaW1hcnkga2V5CiAgICAgKiAgICAg ICAgaWRlbnRpZnlpbmcgdGhlIHJvdyB0byB1cGRhdGUuCiAgICAgKiBAcGFyYW0gY29uIHRo ZSBjb25uZWN0aW9uIHRvIHVzZSwgbm90IG51bGwuCiAgICAgKgogICAgICogQHJldHVybiB0 aGUgbnVtYmVyIG9mIGFmZmVjdGVkIHJvd3MuCiAgICAgKgogICAgICogQHRocm93cyBUb3Jx dWVFeGNlcHRpb24gQW55IGV4Y2VwdGlvbnMgY2F1Z2h0IGR1cmluZyBwcm9jZXNzaW5nIHdp bGwgYmUKICAgICAqICAgICAgICAgcmV0aHJvd24gd3JhcHBlZCBpbnRvIGEgVG9ycXVlRXhj ZXB0aW9uLgogICAgICovCiAgICBwdWJsaWMgaW50IGRvVXBkYXRlKENvbHVtblZhbHVlcyBj b2x1bW5WYWx1ZXMsIENvbm5lY3Rpb24gY29uKQogICAgICAgIHRocm93cyBUb3JxdWVFeGNl cHRpb24KICAgIHsKICAgICAgICBDcml0ZXJpYSBzZWxlY3RDcml0ZXJpYSAKICAgICAgICAg ICAgICAgID0gbmV3IENyaXRlcmlhKEF1dGhvclBlZXIuREFUQUJBU0VfTkFNRSk7CiAgICAg ICAgY29ycmVjdEJvb2xlYW5zKGNvbHVtblZhbHVlcyk7CgoKICAgIAogICAgICAgIHNlbGVj dENyaXRlcmlhLndoZXJlKAogICAgICAgICAgICAgICAgQXV0aG9yUGVlci5BVVRIT1JfSUQs CiAgICAgICAgICAgICAgICBjb2x1bW5WYWx1ZXMucmVtb3ZlKEF1dGhvclBlZXIuQVVUSE9S X0lEKS5nZXRWYWx1ZSgpKTsKCiAgICAgICAgcmV0dXJuIGRvVXBkYXRlKHNlbGVjdENyaXRl cmlhLCBjb2x1bW5WYWx1ZXMsIGNvbik7CiAgICB9CgogICAgLyoqCiAgICAgKiBVcGRhdGVz IGFuIEF1dGhvciBpbiB0aGUgZGF0YWJhc2UuCiAgICAgKiBUaGUgcHJpbWFyeSBrZXkgaXMg dXNlZCB0byBpZGVudGlmeSB0aGUgb2JqZWN0IHRvIHVwZGF0ZS4KICAgICAqCiAgICAgKiBA cGFyYW0gb2JqIHRoZSBkYXRhIG9iamVjdCB0byB1cGRhdGUgaW4gdGhlIGRhdGFiYXNlLgog ICAgICoKICAgICAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBhZmZlY3RlZCByb3dzLgogICAg ICoKICAgICAqIEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdo dCBkdXJpbmcgcHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdy YXBwZWQgaW50byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGljIGludCBk b1VwZGF0ZShBdXRob3Igb2JqKSB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uCiAgICB7CiAgICAg ICAgQ29sdW1uVmFsdWVzIGNvbHVtblZhbHVlcyA9IGJ1aWxkQ29sdW1uVmFsdWVzKG9iaik7 CiAgICAgICAgaW50IHJlc3VsdCA9IGRvVXBkYXRlKGNvbHVtblZhbHVlcyk7CiAgICAgICAg b2JqLnNldE1vZGlmaWVkKGZhbHNlKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoK ICAgIC8qKgogICAgICogVXBkYXRlcyBhIEF1dGhvciBpbiB0aGUgZGF0YWJhc2UuCiAgICAg KiBUaGUgcHJpbWFyeSBrZXkgaXMgdXNlZCB0byBpZGVudGlmeSB0aGUgb2JqZWN0IHRvIHVw ZGF0ZS4KICAgICAqIFRoaXMgbWV0aG9kIGlzIHRvIGJlIHVzZWQgZHVyaW5nIGEgdHJhbnNh Y3Rpb24sCiAgICAgKiBvdGhlcndpc2UgdGhlIGRvVXBkYXRlKEF1dGhvcikgbWV0aG9kIGNh biBiZSB1c2VkLgogICAgICoKICAgICAqIEBwYXJhbSBvYmogdGhlIGRhdGEgb2JqZWN0IHRv IHVwZGF0ZSBpbiB0aGUgZGF0YWJhc2UuCiAgICAgKiBAcGFyYW0gY29uIHRoZSBjb25uZWN0 aW9uIHRvIHVzZSwgbm90IG51bGwuCiAgICAgCiAgICAgKiBAcmV0dXJuIHRoZSBudW1iZXIg b2YgYWZmZWN0ZWQgcm93cy4KICAgICAqCiAgICAgKiBAdGhyb3dzIFRvcnF1ZUV4Y2VwdGlv biBBbnkgZXhjZXB0aW9ucyBjYXVnaHQgZHVyaW5nIHByb2Nlc3Npbmcgd2lsbCBiZQogICAg ICogICAgICAgICByZXRocm93biB3cmFwcGVkIGludG8gYSBUb3JxdWVFeGNlcHRpb24uCiAg ICAgKi8KICAgIHB1YmxpYyBpbnQgZG9VcGRhdGUoQXV0aG9yIG9iaiwgQ29ubmVjdGlvbiBj b24pCiAgICAgICAgdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbgogICAgewogICAgICAgIENvbHVt blZhbHVlcyBjb2x1bW5WYWx1ZXMgPSBidWlsZENvbHVtblZhbHVlcyhvYmopOwogICAgICAg IGludCByZXN1bHQgPSBkb1VwZGF0ZShjb2x1bW5WYWx1ZXMsIGNvbik7CiAgICAgICAgb2Jq LnNldE1vZGlmaWVkKGZhbHNlKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAg IC8qKgogICAgICogRGVsZXRlcyBhIGRhdGEgb2JqZWN0LCBpLmUuIGEgcm93IGluIGEgdGFi bGUsIGluIHRoZSBkYXRhYmFzZS4KICAgICAqCiAgICAgKiBAcGFyYW0gb2JqIHRoZSBkYXRh IG9iamVjdCB0byBkZWxldGUgaW4gdGhlIGRhdGFiYXNlLCBub3QgbnVsbC4KICAgICAqCiAg ICAgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgZGVsZXRlZCByb3dzLgogICAgICoKICAgICAq IEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJpbmcg cHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQgaW50 byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGljIGludCBkb0RlbGV0ZShB dXRob3Igb2JqKSB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uCiAgICB7CiAgICAgICAgaW50IHJl c3VsdCA9IGRvRGVsZXRlKGJ1aWxkQ3JpdGVyaWEob2JqLmdldFByaW1hcnlLZXkoKSksIGdl dFRhYmxlTWFwKCkpOwogICAgICAgIG9iai5zZXREZWxldGVkKHRydWUpOwogICAgICAgIHJl dHVybiByZXN1bHQ7CiAgICB9CgogICAgLyoqCiAgICAgKiBEZWxldGVzIGEgZGF0YSBvYmpl Y3QsIGkuZS4gYSByb3cgaW4gYSB0YWJsZSwgaW4gdGhlIGRhdGFiYXNlLgogICAgICogVGhp cyBtZXRob2QgaXMgdG8gYmUgdXNlZCBkdXJpbmcgYSB0cmFuc2FjdGlvbiwgb3RoZXJ3aXNl IHVzZSB0aGUKICAgICAqIGRvRGVsZXRlKEF1dGhvcikgbWV0aG9kLgogICAgICoKICAgICAq IEBwYXJhbSBvYmogdGhlIGRhdGEgb2JqZWN0IHRvIGRlbGV0ZSBpbiB0aGUgZGF0YWJhc2Us IG5vdCBudWxsLgogICAgICogQHBhcmFtIGNvbiB0aGUgY29ubmVjdGlvbiB0byB1c2UsIG5v dCBudWxsLgogICAgICoKICAgICAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBkZWxldGVkIHJv d3MuCiAgICAgKgogICAgICogQHRocm93cyBUb3JxdWVFeGNlcHRpb24gQW55IGV4Y2VwdGlv bnMgY2F1Z2h0IGR1cmluZyBwcm9jZXNzaW5nIHdpbGwgYmUKICAgICAqICAgICAgICAgcmV0 aHJvd24gd3JhcHBlZCBpbnRvIGEgVG9ycXVlRXhjZXB0aW9uLgogICAgICovCiAgICBwdWJs aWMgaW50IGRvRGVsZXRlKEF1dGhvciBvYmosIENvbm5lY3Rpb24gY29uKQogICAgICAgIHRo cm93cyBUb3JxdWVFeGNlcHRpb24KICAgIHsKICAgICAgICBpbnQgcmVzdWx0ID0gZG9EZWxl dGUoYnVpbGRDcml0ZXJpYShvYmouZ2V0UHJpbWFyeUtleSgpKSwgZ2V0VGFibGVNYXAoKSwg Y29uKTsKICAgICAgICBvYmouc2V0RGVsZXRlZCh0cnVlKTsKICAgICAgICByZXR1cm4gcmVz dWx0OwogICAgfQoKICAgIC8qKgogICAgICogRGVsZXRlcyBkYXRhIG9iamVjdHMsIGkuZS4g cm93cyBpbiBhIHRhYmxlLCBpbiB0aGUgZGF0YWJhc2UuCiAgICAgKgogICAgICogQHBhcmFt IG9iamVjdHMgdGhlIGRhdGEgb2JqZWN0IHRvIGRlbGV0ZSBpbiB0aGUgZGF0YWJhc2UsIG5v dCBudWxsLAogICAgICogICAgICAgIG1heSBub3QgY29udGFpbiBudWxsLgogICAgICoKICAg ICAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBkZWxldGVkIHJvd3MuCiAgICAgKgogICAgICog QHRocm93cyBUb3JxdWVFeGNlcHRpb24gQW55IGV4Y2VwdGlvbnMgY2F1Z2h0IGR1cmluZyBw cm9jZXNzaW5nIHdpbGwgYmUKICAgICAqICAgICAgICAgcmV0aHJvd24gd3JhcHBlZCBpbnRv IGEgVG9ycXVlRXhjZXB0aW9uLgogICAgICovCiAgICBwdWJsaWMgaW50IGRvRGVsZXRlKENv bGxlY3Rpb248QXV0aG9yPiBvYmplY3RzKQogICAgICAgICAgICB0aHJvd3MgVG9ycXVlRXhj ZXB0aW9uCiAgICB7CiAgICAgICAgaW50IHJlc3VsdCA9IGRvRGVsZXRlKGJ1aWxkUGtDcml0 ZXJpYShvYmplY3RzKSwgZ2V0VGFibGVNYXAoKSk7CiAgICAgICAgZm9yIChBdXRob3Igb2Jq ZWN0IDogb2JqZWN0cykKICAgICAgICB7CiAgICAgICAgICAgIG9iamVjdC5zZXREZWxldGVk KHRydWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAgIC8q KgogICAgICogRGVsZXRlcyBkYXRhIG9iamVjdHMsIGkuZS4gcm93cyBpbiBhIHRhYmxlLCBp biB0aGUgZGF0YWJhc2UuCiAgICAgKiBUaGlzIG1ldGhvZCB1c2VzIHRoZSBwYXNzZWQgY29u bmVjdGlvbiB0byBkZWxldGUgdGhlIHJvd3M7CiAgICAgKiBpZiBhIHRyYW5zYWN0aW9uIGlz IG9wZW4gaW4gdGhlIGNvbm5lY3Rpb24sIHRoZSBkZWxldGlvbiBoYXBwZW5zIGluc2lkZQog ICAgICogdGhpcyB0cmFuc2FjdGlvbi4KICAgICAqCiAgICAgKiBAcGFyYW0gb2JqZWN0cyB0 aGUgZGF0YSBvYmplY3RzIHRvIGRlbGV0ZSBpbiB0aGUgZGF0YWJhc2UsIG5vdCBudWxsLAog ICAgICogICAgICAgIG1heSBub3QgY29udGFpbiBudWxsLgogICAgICogQHBhcmFtIGNvbiB0 aGUgY29ubmVjdGlvbiB0byB1c2UgZm9yIGRlbGV0aW5nLCBub3QgbnVsbC4KICAgICAqCiAg ICAgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgZGVsZXRlZCByb3dzLgogICAgICoKICAgICAq IEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJpbmcg cHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQgaW50 byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGljIGludCBkb0RlbGV0ZSgK ICAgICAgICAgICAgQ29sbGVjdGlvbjxBdXRob3I+IG9iamVjdHMsCiAgICAgICAgICAgIENv bm5lY3Rpb24gY29uKQogICAgICAgIHRocm93cyBUb3JxdWVFeGNlcHRpb24KICAgIHsKICAg ICAgICBpbnQgcmVzdWx0ID0gZG9EZWxldGUoYnVpbGRQa0NyaXRlcmlhKG9iamVjdHMpLCBn ZXRUYWJsZU1hcCgpLCBjb24pOwogICAgICAgIGZvciAoQXV0aG9yIG9iamVjdCA6IG9iamVj dHMpCiAgICAgICAgewogICAgICAgICAgICBvYmplY3Quc2V0RGVsZXRlZCh0cnVlKTsKICAg ICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICAvKioKICAgICAqIERl bGV0ZXMgYSByb3cgaW4gdGhlIGRhdGFiYXNlLgogICAgICoKICAgICAqIEBwYXJhbSBwayB0 aGUgT2JqZWN0S2V5IHRoYXQgaWRlbnRpZmllcyB0aGUgcm93IHRvIGRlbGV0ZS4KICAgICAq CiAgICAgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgZGVsZXRlZCByb3dzLgogICAgICoKICAg ICAqIEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJp bmcgcHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQg aW50byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGljIGludCBkb0RlbGV0 ZShPYmplY3RLZXkgcGspIHRocm93cyBUb3JxdWVFeGNlcHRpb24KICAgIHsKICAgICAgICBD b25uZWN0aW9uIGNvbm5lY3Rpb24gPSBudWxsOwogICAgICAgIHRyeQogICAgICAgIHsKICAg ICAgICAgICAgY29ubmVjdGlvbiA9IFRyYW5zYWN0aW9uLmJlZ2luKAogICAgICAgICAgICAg ICAgICAgIEF1dGhvclBlZXIuREFUQUJBU0VfTkFNRSk7CiAgICAgICAgICAgIGludCBkZWxl dGVkUm93cyA9IGRvRGVsZXRlKHBrLCBjb25uZWN0aW9uKTsKICAgICAgICAgICAgVHJhbnNh Y3Rpb24uY29tbWl0KGNvbm5lY3Rpb24pOwogICAgICAgICAgICBjb25uZWN0aW9uID0gbnVs bDsKICAgICAgICAgICAgcmV0dXJuIGRlbGV0ZWRSb3dzOwogICAgICAgIH0KICAgICAgICBm aW5hbGx5CiAgICAgICAgewogICAgICAgICAgICBpZiAoY29ubmVjdGlvbiAhPSBudWxsKQog ICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBUcmFuc2FjdGlvbi5zYWZlUm9sbGJhY2so Y29ubmVjdGlvbik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLyoqCiAg ICAgKiBEZWxldGVzIGEgcm93IGluIHRoZSBkYXRhYmFzZS4KICAgICAqIFRoaXMgbWV0aG9k IGlzIHRvIGJlIHVzZWQgZHVyaW5nIGEgdHJhbnNhY3Rpb24sCiAgICAgKiBvdGhlcndpc2Ug dXNlIHRoZSBkb0RlbGV0ZShPYmplY3RLZXkpIG1ldGhvZC4KICAgICAqCiAgICAgKiBAcGFy YW0gcGsgdGhlIE9iamVjdEtleSB0aGF0IGlkZW50aWZpZXMgdGhlIHJvdyB0byBkZWxldGUu CiAgICAgKiBAcGFyYW0gY29uIHRoZSBjb25uZWN0aW9uIHRvIHVzZSBmb3IgZGVsZXRpbmcs IG5vdCBudWxsLgogICAgICoKICAgICAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBkZWxldGVk IHJvd3MuCiAgICAgKgogICAgICogQHRocm93cyBUb3JxdWVFeGNlcHRpb24gQW55IGV4Y2Vw dGlvbnMgY2F1Z2h0IGR1cmluZyBwcm9jZXNzaW5nIHdpbGwgYmUKICAgICAqICAgICAgICAg cmV0aHJvd24gd3JhcHBlZCBpbnRvIGEgVG9ycXVlRXhjZXB0aW9uLgogICAgICovCiAgICBw dWJsaWMgaW50IGRvRGVsZXRlKE9iamVjdEtleSBwaywgQ29ubmVjdGlvbiBjb24pCiAgICAg ICAgdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbgogICAgewogICAgICAgIHJldHVybiBkb0RlbGV0 ZShidWlsZENyaXRlcmlhKHBrKSwgZ2V0VGFibGVNYXAoKSwgY29uKTsKICAgIH0KCiAgICAv KiogCiAgICAgKiBCdWlsZCBhIENyaXRlcmlhIG9iamVjdCB3aGljaCBzZWxlY3RzIGFsbCBv YmplY3RzIHdoaWNoIGhhdmUgYSBnaXZlbgogICAgICogcHJpbWFyeSBrZXkuCiAgICAgKgog ICAgICogQHBhcmFtIHBrIHRoZSBwcmltYXJ5IGtleSB2YWx1ZSB0byBidWlsZCB0aGUgY3Jp dGVyaWEgZnJvbSwgbm90IG51bGwuCiAgICAgKi8KICAgIHB1YmxpYyBDcml0ZXJpYSBidWls ZENyaXRlcmlhKE9iamVjdEtleSBwaykKICAgIHsKICAgICAgICBDcml0ZXJpYSBjcml0ZXJp YSA9IG5ldyBDcml0ZXJpYSgpOwogICAgICAgIGNyaXRlcmlhLmFkZChBdXRob3JQZWVyLkFV VEhPUl9JRCwgcGspOwogICAgICAgIHJldHVybiBjcml0ZXJpYTsKICAgICB9CgogICAgLyoq IAogICAgICogQnVpbGQgYSBDcml0ZXJpYSBvYmplY3Qgd2hpY2ggc2VsZWN0cyBhbGwgb2Jq ZWN0cyB3aGljaCBwcmltYXJ5IGtleXMKICAgICAqIGFyZSBjb250YWluZWQgaW4gdGhlIHBh c3NlZCBjb2xsZWN0aW9uLgogICAgICoKICAgICAqIEBwYXJhbSBwa3MgdGhlIHByaW1hcnkg a2V5IHZhbHVlcyB0byBidWlsZCB0aGUgY3JpdGVyaWEgZnJvbSwgbm90IG51bGwsCiAgICAg KiAgICAgICAgbWF5IG5vdCBjb250YWluIG51bGwuCiAgICAgKi8KICAgIHB1YmxpYyBDcml0 ZXJpYSBidWlsZENyaXRlcmlhKENvbGxlY3Rpb248T2JqZWN0S2V5PiBwa3MpCiAgICB7CiAg ICAgICAgQ3JpdGVyaWEgY3JpdGVyaWEgPSBuZXcgQ3JpdGVyaWEoKTsKICAgICAgICBjcml0 ZXJpYS5hZGRJbihBdXRob3JQZWVyLkFVVEhPUl9JRCwgcGtzKTsKICAgICAgICByZXR1cm4g Y3JpdGVyaWE7CiAgICAgfQoKCiAgICAvKiogCiAgICAgKiBCdWlsZCBhIENyaXRlcmlhIG9i amVjdCB3aGljaCBzZWxlY3RzIGFsbCBwYXNzZWQgb2JqZWN0cyB1c2luZyB0aGVpcgogICAg ICogcHJpbWFyeSBrZXkuIE9iamVjdHMgd2hpY2ggZG8gbm90IHlldCBoYXZlIGEgcHJpbWFy eSBrZXkgYXJlIGlnbm9yZWQuCiAgICAgKgogICAgICogQHBhcmFtIG9iamVjdHMgdGhlIG9i amVjdHMgdG8gYnVpbGQgdGhlIGNyaXRlcmlhIGZyb20sIG5vdCBudWxsLAogICAgICogICAg ICAgIG1heSBub3QgY29udGFpbiBudWxsLgogICAgICovCiAgICBwdWJsaWMgQ3JpdGVyaWEg YnVpbGRQa0NyaXRlcmlhKAogICAgICAgICAgICBDb2xsZWN0aW9uPEF1dGhvcj4gb2JqZWN0 cykKICAgIHsKICAgICAgICBMaXN0PE9iamVjdEtleT4gcGtzID0gbmV3IEFycmF5TGlzdDxP YmplY3RLZXk+KG9iamVjdHMuc2l6ZSgpKTsKICAgICAgICBmb3IgKEF1dGhvciBvYmplY3Qg OiBvYmplY3RzKQogICAgICAgIHsKICAgICAgICAgICAgT2JqZWN0S2V5IHBrID0gb2JqZWN0 LmdldFByaW1hcnlLZXkoKTsKICAgICAgICAgICAgaWYgKHBrICE9IG51bGwpCiAgICAgICAg ICAgIHsKICAgICAgICAgICAgICAgIHBrcy5hZGQocGspOwogICAgICAgICAgICB9CiAgICAg ICAgfQogICAgICAgIHJldHVybiBidWlsZENyaXRlcmlhKHBrcyk7CiAgICB9CgogICAgLyoq IAogICAgICogQnVpbGQgYSBDcml0ZXJpYSBvYmplY3QgZnJvbSB0aGUgZGF0YSBvYmplY3Qg Zm9yIHRoaXMgcGVlci4KICAgICAqIFRoZSBwcmltYXJ5IGtleSBjb2x1bW5zIGFyZSBvbmx5 IGFkZGVkIGlmIHRoZSBvYmplY3QgaXMgbm90IG5ldy4KICAgICAqCiAgICAgKiBAcGFyYW0g b2JqIHRoZSBvYmplY3QgdG8gYnVpbGQgdGhlIGNyaXRlcmlhIGZyb20sIG5vdCBudWxsLgog ICAgICovCiAgICBwdWJsaWMgQ3JpdGVyaWEgYnVpbGRDcml0ZXJpYShBdXRob3Igb2JqKQog ICAgewogICAgICAgIENyaXRlcmlhIGNyaXRlcmlhID0gbmV3IENyaXRlcmlhKEF1dGhvclBl ZXIuREFUQUJBU0VfTkFNRSk7CiAgICAgICAgaWYgKCFvYmouaXNOZXcoKSkKICAgICAgICB7 CiAgICAgICAgICAgIGNyaXRlcmlhLmFkZChBdXRob3JQZWVyLkFVVEhPUl9JRCwgb2JqLmdl dEF1dGhvcklkKCkpOwogICAgICAgIH0KICAgICAgICBjcml0ZXJpYS5hZGQoQXV0aG9yUGVl ci5OQU1FLCBvYmouZ2V0TmFtZSgpKTsKICAgICAgICByZXR1cm4gY3JpdGVyaWE7CiAgICB9 CgogICAgLyoqIAogICAgICogQnVpbGQgYSBDcml0ZXJpYSBvYmplY3QgZnJvbSB0aGUgZGF0 YSBvYmplY3QgZm9yIHRoaXMgcGVlciwKICAgICAqIHNraXBwaW5nIGFsbCBiaW5hcnkgY29s dW1ucy4KICAgICAqCiAgICAgKiBAcGFyYW0gb2JqIHRoZSBvYmplY3QgdG8gYnVpbGQgdGhl IGNyaXRlcmlhIGZyb20sIG5vdCBudWxsLgogICAgICovCiAgICBwdWJsaWMgQ3JpdGVyaWEg YnVpbGRTZWxlY3RDcml0ZXJpYShBdXRob3Igb2JqKQogICAgewogICAgICAgIENyaXRlcmlh IGNyaXRlcmlhID0gbmV3IENyaXRlcmlhKEF1dGhvclBlZXIuREFUQUJBU0VfTkFNRSk7CiAg ICAgICAgaWYgKCFvYmouaXNOZXcoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNyaXRlcmlh LmFkZChBdXRob3JQZWVyLkFVVEhPUl9JRCwgb2JqLmdldEF1dGhvcklkKCkpOwogICAgICAg IH0KICAgICAgICBjcml0ZXJpYS5hZGQoQXV0aG9yUGVlci5OQU1FLCBvYmouZ2V0TmFtZSgp KTsKICAgICAgICByZXR1cm4gY3JpdGVyaWE7CiAgICB9CgogICAgLyoqIAogICAgICogUmV0 dXJucyB0aGUgY29udGVudHMgb2YgdGhlIG9iamVjdCBhcyBDb2x1bW5WYWx1ZXMgb2JqZWN0 LgogICAgICogUHJpbWFyeSBrZXkgY29sdW1ucyB3aGljaCBhcmUgZ2VuZXJhdGVkIG9uIGlu c2VydGlvbiBhcmUgbm90CiAgICAgKiBhZGRlZCB0byB0aGUgcmV0dXJuZWQgb2JqZWN0IGlm IHRoZXkgc3RpbGwgaGF2ZSB0aGVpciBpbml0aWFsCiAgICAgKiB2YWx1ZS4gQWxzbywgY29s dW1ucyB3aGljaCBoYXZlIHRoZSB1c2VEYXRhYmFzZURlZmF1bHRWYWx1ZQogICAgICogZmxh ZyBzZXQgdG8gdHJ1ZSBhcmUgYWxzbyBub3QgYWRkZWQgdG8gdGhlIHJldHVybmVkIG9iamVj dAogICAgICogaWYgdGhleSBzdGlsbCBoYXZlIHRoZWlyIGluaXRpYWwgdmFsdWUuCiAgICAg KgogICAgICogQHRocm93cyBUb3JxdWVFeGNlcHRpb24gaWYgdGhlIHRhYmxlIG1hcCBjYW5u b3QgYmUgcmV0cmlldmVkCiAgICAgKiAgICAgICAgIChzaG91bGQgbm90IGhhcHBlbikuCiAg ICAgKi8KICAgIHB1YmxpYyBDb2x1bW5WYWx1ZXMgYnVpbGRDb2x1bW5WYWx1ZXMoQXV0aG9y IGF1dGhvcikKICAgICAgICAgICAgdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbgogICAgewogICAg ICAgIENvbHVtblZhbHVlcyBjb2x1bW5WYWx1ZXMgPSBuZXcgQ29sdW1uVmFsdWVzKGdldFRh YmxlTWFwKCkpOwogICAgICAgIGlmICghYXV0aG9yLmlzTmV3KCkgCiAgICAgICAgICAgIHx8 IGF1dGhvci5nZXRBdXRob3JJZCgpICE9IDApCiAgICAgICAgewogICAgICAgICAgICBjb2x1 bW5WYWx1ZXMucHV0KAogICAgICAgICAgICAgICAgICAgIEF1dGhvclBlZXIuQVVUSE9SX0lE LAogICAgICAgICAgICAgICAgICAgIG5ldyBKZGJjVHlwZWRWYWx1ZSgKICAgICAgICAgICAg ICAgICAgICAgICAgYXV0aG9yLmdldEF1dGhvcklkKCksCiAgICAgICAgICAgICAgICAgICAg ICAgIDQpKTsKICAgICAgICB9CiAgICAgICAgY29sdW1uVmFsdWVzLnB1dCgKICAgICAgICAg ICAgICAgIEF1dGhvclBlZXIuTkFNRSwKICAgICAgICAgICAgICAgIG5ldyBKZGJjVHlwZWRW YWx1ZSgKICAgICAgICAgICAgICAgICAgICBhdXRob3IuZ2V0TmFtZSgpLAogICAgICAgICAg ICAgICAgICAgIDEyKSk7CiAgICAgICAgcmV0dXJuIGNvbHVtblZhbHVlczsKICAgIH0KCiAg ICAvKioKICAgICAqIFJldHJpZXZlIGEgc2luZ2xlIG9iamVjdCBieSBwawogICAgICoKICAg ICAqIEBwYXJhbSBwayB0aGUgcHJpbWFyeSBrZXkKICAgICAqIEB0aHJvd3MgVG9ycXVlRXhj ZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJpbmcgcHJvY2Vzc2luZyB3aWxsIGJl CiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQgaW50byBhIFRvcnF1ZUV4Y2VwdGlv bi4KICAgICAqIEB0aHJvd3MgTm9Sb3dzRXhjZXB0aW9uIFByaW1hcnkga2V5IHdhcyBub3Qg Zm91bmQgaW4gZGF0YWJhc2UuCiAgICAgKiBAdGhyb3dzIFRvb01hbnlSb3dzRXhjZXB0aW9u IFByaW1hcnkga2V5IHdhcyBub3QgZm91bmQgaW4gZGF0YWJhc2UuCiAgICAgKi8KICAgIHB1 YmxpYyBBdXRob3IgcmV0cmlldmVCeVBLKGludCBwaykKICAgICAgICB0aHJvd3MgVG9ycXVl RXhjZXB0aW9uLCBOb1Jvd3NFeGNlcHRpb24sIFRvb01hbnlSb3dzRXhjZXB0aW9uCiAgICB7 CiAgICAgICAgcmV0dXJuIHJldHJpZXZlQnlQSyhTaW1wbGVLZXkua2V5Rm9yKHBrKSk7CiAg ICB9CgogICAgLyoqCiAgICAgKiBSZXRyaWV2ZSBhIHNpbmdsZSBvYmplY3QgYnkgcGsKICAg ICAqCiAgICAgKiBAcGFyYW0gcGsgdGhlIHByaW1hcnkga2V5CiAgICAgKiBAcGFyYW0gY29u IHRoZSBjb25uZWN0aW9uIHRvIHVzZQogICAgICogQHRocm93cyBUb3JxdWVFeGNlcHRpb24g QW55IGV4Y2VwdGlvbnMgY2F1Z2h0IGR1cmluZyBwcm9jZXNzaW5nIHdpbGwgYmUKICAgICAq ICAgICAgICAgcmV0aHJvd24gd3JhcHBlZCBpbnRvIGEgVG9ycXVlRXhjZXB0aW9uLgogICAg ICogQHRocm93cyBOb1Jvd3NFeGNlcHRpb24gUHJpbWFyeSBrZXkgd2FzIG5vdCBmb3VuZCBp biBkYXRhYmFzZS4KICAgICAqIEB0aHJvd3MgVG9vTWFueVJvd3NFeGNlcHRpb24gUHJpbWFy eSBrZXkgd2FzIG5vdCBmb3VuZCBpbiBkYXRhYmFzZS4KICAgICAqLwogICAgcHVibGljIEF1 dGhvciByZXRyaWV2ZUJ5UEsoaW50IHBrLCBDb25uZWN0aW9uIGNvbikKICAgICAgICB0aHJv d3MgVG9ycXVlRXhjZXB0aW9uLCBOb1Jvd3NFeGNlcHRpb24sIFRvb01hbnlSb3dzRXhjZXB0 aW9uCiAgICB7CiAgICAgICAgcmV0dXJuIHJldHJpZXZlQnlQSyhTaW1wbGVLZXkua2V5Rm9y KHBrKSwgY29uKTsKICAgIH0KICAgIAogICAgCiAgICAKCiAgICAvKioKICAgICAqIFJldHJp ZXZlIGEgc2luZ2xlIG9iamVjdCBieSBwawogICAgICoKICAgICAqIEBwYXJhbSBwayB0aGUg cHJpbWFyeSBrZXkKICAgICAqIEB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRp b25zIGNhdWdodCBkdXJpbmcgcHJvY2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJl dGhyb3duIHdyYXBwZWQgaW50byBhIFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqIEB0aHJvd3Mg Tm9Sb3dzRXhjZXB0aW9uIFByaW1hcnkga2V5IHdhcyBub3QgZm91bmQgaW4gZGF0YWJhc2Uu CiAgICAgKiBAdGhyb3dzIFRvb01hbnlSb3dzRXhjZXB0aW9uIFByaW1hcnkga2V5IHdhcyBu b3QgZm91bmQgaW4gZGF0YWJhc2UuCiAgICAgKi8KICAgIHB1YmxpYyBBdXRob3IgcmV0cmll dmVCeVBLKE9iamVjdEtleSBwaykKICAgICAgICB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uLCBO b1Jvd3NFeGNlcHRpb24sIFRvb01hbnlSb3dzRXhjZXB0aW9uCiAgICB7CiAgICAgICAgQ29u bmVjdGlvbiBkYiA9IG51bGw7CiAgICAgICAgQXV0aG9yIHJldFZhbDsKICAgICAgICB0cnkK ICAgICAgICB7CiAgICAgICAgICAgIGRiID0gVG9ycXVlLmdldENvbm5lY3Rpb24oQXV0aG9y UGVlci5EQVRBQkFTRV9OQU1FKTsKICAgICAgICAgICAgcmV0VmFsID0gcmV0cmlldmVCeVBL KHBrLCBkYik7CiAgICAgICAgfQogICAgICAgIGZpbmFsbHkKICAgICAgICB7CiAgICAgICAg ICAgIFRvcnF1ZS5jbG9zZUNvbm5lY3Rpb24oZGIpOwogICAgICAgIH0KICAgICAgICByZXR1 cm4gcmV0VmFsOwogICAgfQoKICAgIC8qKgogICAgICogUmV0cmlldmUgYSBzaW5nbGUgb2Jq ZWN0IGJ5IHBrCiAgICAgKgogICAgICogQHBhcmFtIHBrIHRoZSBwcmltYXJ5IGtleQogICAg ICogQHBhcmFtIGNvbiB0aGUgY29ubmVjdGlvbiB0byB1c2UKICAgICAqIEB0aHJvd3MgVG9y cXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJpbmcgcHJvY2Vzc2luZyB3 aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQgaW50byBhIFRvcnF1ZUV4 Y2VwdGlvbi4KICAgICAqIEB0aHJvd3MgTm9Sb3dzRXhjZXB0aW9uIFByaW1hcnkga2V5IHdh cyBub3QgZm91bmQgaW4gZGF0YWJhc2UuCiAgICAgKiBAdGhyb3dzIFRvb01hbnlSb3dzRXhj ZXB0aW9uIFByaW1hcnkga2V5IHdhcyBub3QgZm91bmQgaW4gZGF0YWJhc2UuCiAgICAgKi8K ICAgIHB1YmxpYyBBdXRob3IgcmV0cmlldmVCeVBLKE9iamVjdEtleSBwaywgQ29ubmVjdGlv biBjb24pCiAgICAgICAgdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbiwgTm9Sb3dzRXhjZXB0aW9u LCBUb29NYW55Um93c0V4Y2VwdGlvbgogICAgewogICAgICAgIENyaXRlcmlhIGNyaXRlcmlh ID0gYnVpbGRDcml0ZXJpYShwayk7CiAgICAgICAgTGlzdDxBdXRob3I+IHYgPSBkb1NlbGVj dChjcml0ZXJpYSwgY29uKTsKICAgICAgICBpZiAodi5zaXplKCkgPT0gMCkKICAgICAgICB7 CiAgICAgICAgICAgIHRocm93IG5ldyBOb1Jvd3NFeGNlcHRpb24oIkZhaWxlZCB0byBzZWxl Y3QgYSByb3cuIik7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKHYuc2l6ZSgpID4gMSkK ICAgICAgICB7CiAgICAgICAgICAgIHRocm93IG5ldyBUb29NYW55Um93c0V4Y2VwdGlvbigi RmFpbGVkIHRvIHNlbGVjdCBvbmx5IG9uZSByb3cuIik7CiAgICAgICAgfQogICAgICAgIGVs c2UKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAoQXV0aG9yKXYuZ2V0KDApOwogICAg ICAgIH0KICAgIH0KCgogICAgLyoqCiAgICAgKiBSZXRyaWV2ZSBhIG11bHRpcGxlIG9iamVj dHMgYnkgcGsKICAgICAqCiAgICAgKiBAcGFyYW0gcGtzIExpc3Qgb2YgcHJpbWFyeSBrZXlz CiAgICAgKiBAdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbiBBbnkgZXhjZXB0aW9ucyBjYXVnaHQg ZHVyaW5nIHByb2Nlc3Npbmcgd2lsbCBiZQogICAgICogICAgICAgICByZXRocm93biB3cmFw cGVkIGludG8gYSBUb3JxdWVFeGNlcHRpb24uCiAgICAgKi8KICAgIHB1YmxpYyBMaXN0PEF1 dGhvcj4gcmV0cmlldmVCeVBLcyhDb2xsZWN0aW9uPE9iamVjdEtleT4gcGtzKQogICAgICAg IHRocm93cyBUb3JxdWVFeGNlcHRpb24KICAgIHsKICAgICAgICBDb25uZWN0aW9uIGRiID0g bnVsbDsKICAgICAgICBMaXN0PEF1dGhvcj4gcmV0VmFsID0gbnVsbDsKICAgICAgICB0cnkK ICAgICAgICB7CiAgICAgICAgICAgZGIgPSBUb3JxdWUuZ2V0Q29ubmVjdGlvbihBdXRob3JQ ZWVyLkRBVEFCQVNFX05BTUUpOwogICAgICAgICAgIHJldFZhbCA9IHJldHJpZXZlQnlQS3Mo cGtzLCBkYik7CiAgICAgICAgfQogICAgICAgIGZpbmFsbHkKICAgICAgICB7CiAgICAgICAg ICAgIFRvcnF1ZS5jbG9zZUNvbm5lY3Rpb24oZGIpOwogICAgICAgIH0KICAgICAgICByZXR1 cm4gcmV0VmFsOwogICAgfQoKICAgIC8qKgogICAgICogUmV0cmlldmUgbXVsdGlwbGUgb2Jq ZWN0cyBieSBwawogICAgICoKICAgICAqIEBwYXJhbSBwa3MgTGlzdCBvZiBwcmltYXJ5IGtl eXMKICAgICAqIEBwYXJhbSBkYmNvbiB0aGUgY29ubmVjdGlvbiB0byB1c2UKICAgICAqIEB0 aHJvd3MgVG9ycXVlRXhjZXB0aW9uIEFueSBleGNlcHRpb25zIGNhdWdodCBkdXJpbmcgcHJv Y2Vzc2luZyB3aWxsIGJlCiAgICAgKiAgICAgICAgIHJldGhyb3duIHdyYXBwZWQgaW50byBh IFRvcnF1ZUV4Y2VwdGlvbi4KICAgICAqLwogICAgcHVibGljIExpc3Q8QXV0aG9yPiByZXRy aWV2ZUJ5UEtzKAogICAgICAgICAgICAgICAgQ29sbGVjdGlvbjxPYmplY3RLZXk+IHBrcywK ICAgICAgICAgICAgICAgIENvbm5lY3Rpb24gZGJjb24pCiAgICAgICAgICAgIHRocm93cyBU b3JxdWVFeGNlcHRpb24KICAgIHsKICAgICAgICBpZiAocGtzID09IG51bGwgfHwgcGtzLnNp emUoKSA9PSAwKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBBcnJheUxpc3Q8 QXV0aG9yPigpOwogICAgICAgIH0KICAgICAgICBDcml0ZXJpYSBjcml0ZXJpYSA9IGJ1aWxk Q3JpdGVyaWEocGtzKTsKICAgICAgICBMaXN0PEF1dGhvcj4gcmVzdWx0ID0gZG9TZWxlY3Qo Y3JpdGVyaWEsIGRiY29uKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKCgoKCiAg ICAvKiogDQogICAgICogRmlsbHMgdGhlIHJlZmVyZW5jZWQgQm9vayBvYmplY3RzIGluIHRo ZSBjb2xsQm9va3MgZmllbGRzDQogICAgICogb2YgdGhlIG9iamVjdHMgaW4gPGNvZGU+dG9G aWxsPC9jb2RlPiBieSByZWFkaW5nIHRoZSBkYXRhYmFzZS4NCiAgICAgKg0KICAgICAqIEBw YXJhbSB0b0ZpbGwgQ29udGFpbnMgdGhlIG9iamVjdHMgdG8gZmlsbCwgbm90IG51bGwsDQog ICAgICogICAgICAgIG1heSBub3QgY29udGFpbiBudWxsLg0KICAgICAqDQogICAgICogQHJl dHVybiBhbGwgcmVhZCBMaXN0PEJvb2s+IG9iamVjdHMuDQogICAgICoNCiAgICAgKiBAdGhy b3dzIFRvcnF1ZUV4Y2VwdGlvbiBpZiBhbiBlcnJvciBxdWVyeWluZyB0aGUgZGF0YWJhc2Ug b2NjdXJzLg0KICAgICAqIEB0aHJvd3MgTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgdG9GaWxs IGlzIG51bGwgb3IgY29udGFpbnMgbnVsbCBlbGVtZW50cy4NCiAgICAgKi8NCiAgICBwdWJs aWMgTGlzdDxCb29rPiBmaWxsQm9va3MoDQogICAgICAgICAgICBDb2xsZWN0aW9uPEF1dGhv cj4gdG9GaWxsKQ0KICAgICAgICB0aHJvd3MgVG9ycXVlRXhjZXB0aW9uDQogICAgew0KICAg ICAgICBDb25uZWN0aW9uIGNvbm5lY3Rpb24gPSBudWxsOw0KICAgICAgICB0cnkNCiAgICAg ICAgew0KICAgICAgICAgICAgY29ubmVjdGlvbiA9IFRyYW5zYWN0aW9uLmJlZ2luKA0KICAg ICAgICAgICAgICAgICAgICBBdXRob3JQZWVyLkRBVEFCQVNFX05BTUUpOw0KICAgICAgICAg ICAgTGlzdDxCb29rPiByZXN1bHQgPSBmaWxsQm9va3ModG9GaWxsLCBjb25uZWN0aW9uKTsN CiAgICAgICAgICAgIFRyYW5zYWN0aW9uLmNvbW1pdChjb25uZWN0aW9uKTsNCiAgICAgICAg ICAgIGNvbm5lY3Rpb24gPSBudWxsOw0KICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsNCiAg ICAgICAgfQ0KICAgICAgICBmaW5hbGx5DQogICAgICAgIHsNCiAgICAgICAgICAgIGlmIChj b25uZWN0aW9uICE9IG51bGwpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgVHJh bnNhY3Rpb24uc2FmZVJvbGxiYWNrKGNvbm5lY3Rpb24pOw0KICAgICAgICAgICAgfQ0KICAg ICAgICB9DQogICAgfQ0KDQogICAgLyoqIA0KICAgICAqIEZpbGxzIHRoZSByZWZlcmVuY2Vk IEJvb2sgb2JqZWN0cyBpbiB0aGUgY29sbEJvb2tzIGZpZWxkcw0KICAgICAqIG9mIHRoZSBv YmplY3RzIGluIDxjb2RlPnRvRmlsbDwvY29kZT4gYnkgcmVhZGluZyB0aGUgZGF0YWJhc2Uu DQogICAgICoNCiAgICAgKiBAcGFyYW0gdG9GaWxsIENvbnRhaW5zIHRoZSBvYmplY3RzIHRv IGZpbGwsIG5vdCBudWxsLA0KICAgICAqICAgICAgICBtYXkgbm90IGNvbnRhaW4gbnVsbC4N CiAgICAgKiBAcGFyYW0gY29ubmVjdGlvbiB0aGUgZGF0YWJhc2UgY29ubmVjdGlvbiB0byB1 c2UsIG5vdCBudWxsLg0KICAgICAqDQogICAgICogQHJldHVybiBhbGwgcmVhZCBMaXN0PEJv b2s+IG9iamVjdHMuDQogICAgICoNCiAgICAgKiBAdGhyb3dzIFRvcnF1ZUV4Y2VwdGlvbiBp ZiBhbiBlcnJvciBxdWVyeWluZyB0aGUgZGF0YWJhc2Ugb2NjdXJzLg0KICAgICAqIEB0aHJv d3MgTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgdG9GaWxsIGlzIG51bGwgb3IgY29udGFpbnMg bnVsbCBlbGVtZW50cy4NCiAgICAgKi8NCiAgICBwdWJsaWMgTGlzdDxCb29rPiBmaWxsQm9v a3MoDQogICAgICAgICAgICBDb2xsZWN0aW9uPEF1dGhvcj4gdG9GaWxsLA0KICAgICAgICAg ICAgQ29ubmVjdGlvbiBjb25uZWN0aW9uKQ0KICAgICAgICB0aHJvd3MgVG9ycXVlRXhjZXB0 aW9uDQogICAgew0KICAgICAgICBTZXQ8T2JqZWN0S2V5PiBsb2NhbEtleVNldCA9IG5ldyBI YXNoU2V0PE9iamVjdEtleT4oKTsNCiAgICAgICAgZm9yIChBdXRob3IgY3VycmVudEF1dGhv ciA6IHRvRmlsbCkNCiAgICAgICAgew0KICAgICAgICAgICAgT2JqZWN0S2V5IGxvY2FsS2V5 ID0gY3VycmVudEF1dGhvci5nZXRQcmltYXJ5S2V5KCk7DQogICAgICAgICAgICBsb2NhbEtl eVNldC5hZGQobG9jYWxLZXkpOw0KICAgICAgICB9DQoNCiAgICAgICAgaW50IGZpbGxlckNo dW5rU2l6ZSA9IGdldEZpbGxlckNodW5rU2l6ZSgpOw0KICAgICAgICBJdGVyYXRvcjxPYmpl Y3RLZXk+IGxvY2FsS2V5SXQgPSBsb2NhbEtleVNldC5pdGVyYXRvcigpOw0KICAgICAgICBM aXN0PE9iamVjdEtleT4gbG9jYWxLZXlMaXN0Q2h1bmsNCiAgICAgICAgICAgICAgICA9IG5l dyBBcnJheUxpc3Q8T2JqZWN0S2V5PihmaWxsZXJDaHVua1NpemUpOw0KICAgICAgICBNYXA8 T2JqZWN0S2V5LCBMaXN0PEJvb2s+PiBma1RvQm9va01hcA0KICAgICAgICAgICAgICAgID0g bmV3IEhhc2hNYXA8T2JqZWN0S2V5LCBMaXN0PEJvb2s+PigpOw0KICAgICAgICB3aGlsZSAo bG9jYWxLZXlJdC5oYXNOZXh0KCkpDQogICAgICAgIHsNCiAgICAgICAgICAgIE9iamVjdEtl eSBjdXJyZW50S2V5ID0gbG9jYWxLZXlJdC5uZXh0KCk7DQogICAgICAgICAgICBsb2NhbEtl eUxpc3RDaHVuay5hZGQoY3VycmVudEtleSk7DQogICAgICAgICAgICBpZiAobG9jYWxLZXlM aXN0Q2h1bmsuc2l6ZSgpIDwgZmlsbGVyQ2h1bmtTaXplDQogICAgICAgICAgICAgICAgJiYg bG9jYWxLZXlJdC5oYXNOZXh0KCkpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAg Y29udGludWU7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIENyaXRlcmlhIGNyaXRl cmlhID0gbmV3IENyaXRlcmlhKCk7DQogICAgICAgICAgICBjcml0ZXJpYS5hZGRJbihCb29r UGVlci5BVVRIT1JfSUQsIGxvY2FsS2V5TGlzdENodW5rKTsNCiAgICAgICAgICAgIExpc3Q8 Qm9vaz4gcmVmZXJlbmNlZEJvb2tMaXN0DQogICAgICAgICAgICAgICAgID0gQm9va1BlZXIu ZG9TZWxlY3QoDQogICAgICAgICAgICAgICAgICAgICBjcml0ZXJpYSwNCiAgICAgICAgICAg ICAgICAgICAgIGNvbm5lY3Rpb24pOw0KICAgICAgICAgICAgZm9yIChCb29rIHJlZmVyZW5j ZWRPYmplY3QgOiByZWZlcmVuY2VkQm9va0xpc3QpDQogICAgICAgICAgICB7DQogICAgICAg ICAgICAgICAgT2JqZWN0S2V5IGZvcmVpZ25LZXkgPSByZWZlcmVuY2VkT2JqZWN0LmdldEZv cmVpZ25LZXlGb3JBdXRob3IoKTsNCiAgICAgICAgICAgICAgICBMaXN0PEJvb2s+IG9iamVj dHNXaXRoRm9yZWlnbktleSANCiAgICAgICAgICAgICAgICAgICAgPSBma1RvQm9va01hcC5n ZXQoZm9yZWlnbktleSk7DQogICAgICAgICAgICAgICAgaWYgKG9iamVjdHNXaXRoRm9yZWln bktleSA9PSBudWxsKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAg b2JqZWN0c1dpdGhGb3JlaWduS2V5ID0gbmV3IEFycmF5TGlzdDxCb29rPigpOw0KICAgICAg ICAgICAgICAgICAgICBma1RvQm9va01hcC5wdXQoDQogICAgICAgICAgICAgICAgICAgICAg ICBmb3JlaWduS2V5LA0KICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0c1dpdGhGb3Jl aWduS2V5KTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgb2JqZWN0c1dp dGhGb3JlaWduS2V5LmFkZChyZWZlcmVuY2VkT2JqZWN0KTsNCiAgICAgICAgICAgIH0NCiAg ICAgICAgICAgIGxvY2FsS2V5TGlzdENodW5rLmNsZWFyKCk7DQogICAgICAgIH0NCg0KICAg ICAgICBMaXN0PEJvb2s+IHJlc3VsdCA9IG5ldyBBcnJheUxpc3Q8Qm9vaz4oKTsNCiAgICAg ICAgZm9yIChBdXRob3Igb2JqZWN0VG9GaWxsIDogdG9GaWxsKQ0KICAgICAgICB7DQogICAg ICAgICAgICBvYmplY3RUb0ZpbGwuaW5pdEJvb2tzKCk7DQogICAgICAgICAgICBvYmplY3RU b0ZpbGwuZ2V0Qm9va3MoKS5jbGVhcigpOw0KICAgICAgICAgICAgT2JqZWN0S2V5IGxvY2Fs S2V5ID0gb2JqZWN0VG9GaWxsLmdldFByaW1hcnlLZXkoKTsNCiAgICAgICAgICAgIExpc3Q8 Qm9vaz4gcmVmZXJlbmNpbmdMaXN0DQogICAgICAgICAgICAgICAgPSBma1RvQm9va01hcC5n ZXQobG9jYWxLZXkpOw0KICAgICAgICAgICAgaWYgKHJlZmVyZW5jaW5nTGlzdCA9PSBudWxs KQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAgICAg ICAgfQ0KICAgICAgICAgICAgZm9yIChCb29rIHJlZmVyZW5jaW5nIDogcmVmZXJlbmNpbmdM aXN0KQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIC8vIGNvcHkgdGhlIHJlZmVy ZW5jaW5nIG9iamVjdCBmb3IgdGhlIGNhc2UgdGhhdCBtb3JlIHRoYW4gb25lDQogICAgICAg ICAgICAgICAgLy8gdG9GaWxsIG9iamVjdCByZWZlcmVuY2VzIHRoZSBzYW1lIG9iamVjdDsg aW4gdGhpcyBjYXNlDQogICAgICAgICAgICAgICAgLy8gZXZlcnkgdG9GaWxsT2JqZWN0IHNo b3VsZCBoYXZlIGl0cyBvd24gaW5zdGFuY2UgDQogICAgICAgICAgICAgICAgLy8gb2YgdGhl IHJlZmVyZW5jaW5nIG9iamVjdCB0byByZW1haW4gY29uc2lzdGVudA0KICAgICAgICAgICAg ICAgIC8vIHdpdGggb3RoZXIgVG9ycXVlIHJlZmVyZW5jaW5nIG9iamVjdCB0cmVhdG1lbnQN CiAgICAgICAgICAgICAgICBCb29rIHJlZmVyZW5jaW5nQ29weSA9IHJlZmVyZW5jaW5nLmNv cHkoZmFsc2UpOw0KICAgICAgICAgICAgICAgIC8vIGNvcHkgZG9lcyBub3Qgc2V0IHByaW1h cnkga2V5DQogICAgICAgICAgICAgICAgcmVmZXJlbmNpbmdDb3B5LnNldFByaW1hcnlLZXko cmVmZXJlbmNpbmcuZ2V0UHJpbWFyeUtleSgpKTsNCiAgICAgICAgICAgICAgICBvYmplY3RU b0ZpbGwuYWRkQm9vayhyZWZlcmVuY2luZ0NvcHkpOw0KICAgICAgICAgICAgICAgIHJlc3Vs dC5hZGQocmVmZXJlbmNpbmdDb3B5KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAg ICAgICByZXR1cm4gcmVzdWx0Ow0KICAgIH0NCgogICAgLyoqIA0KICAgICAqIFJldHVybnMg dGhlIGNodW5rIHNpemUgZm9yIHRoZSBmaWxsZXIgbWV0aG9kcy4NCiAgICAgKg0KICAgICAq IEByZXR1cm4gdGhlIGNodW5rIHNpemUgZm9yIHRoZSBmaWxsZXIgbWV0aG9kcy4NCiAgICAg Ki8NCiAgICBwcm90ZWN0ZWQgaW50IGdldEZpbGxlckNodW5rU2l6ZSgpDQogICAgew0KICAg ICAgICByZXR1cm4gOTk5Ow0KICAgIH0NCgoKfQo= --------------080702050307000306090300 Content-Type: text/plain; charset=us-ascii --------------------------------------------------------------------- To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org For additional commands, e-mail: torque-dev-help@db.apache.org --------------080702050307000306090300--