diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java index 254dfb3111..504e077c09 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -68,6 +68,7 @@ import org.jooq.ExecuteContext; import org.jooq.ExecuteListenerProvider; import org.jooq.Name; import org.jooq.Query; +import org.jooq.Record; import org.jooq.SQLDialect; import org.jooq.Schema; import org.jooq.Table; @@ -369,59 +370,62 @@ public abstract class AbstractDatabase implements Database { } } - // [#8972] TODO: Implement these for all non-PostgresDatabase databases. - @Override - public TableQualifier tableQualifier() { - return null; - } - - @Override - public ColumnQualifier columnQualifier() { - return null; - } - @Override public final boolean exists(TableField field) { Boolean result = existFields.get(field); - if (result == null) { - ColumnQualifier qualifier = columnQualifier(); - - // [#8972] In the presence of a qualifier, avoid running an error- - // triggering query, which may lead to unwanted log messages - if (qualifier == null) { - try { - create(true) - .select(field) - .from(field.getTable()) - .where(falseCondition()) - .fetch(); - - result = true; - } - catch (DataAccessException e) { - result = false; - } - } - else { - Condition condition = qualifier.columnName().eq(field.getName()); - - Table table = field.getTable(); - condition = condition.and(qualifier.tableName().eq(table.getName())); - - Schema schema = table.getSchema(); - if (schema != null) - condition = condition.and(qualifier.tableSchema().eq(schema.getName())); - - result = create().fetchExists(qualifier.table(), condition); - } - - existFields.put(field, result); - } + if (result == null) + existFields.put(field, result = exists0(field)); return result; } + /** + * [#8972] Subclasses may override this method for a more efficient implementation. + */ + protected boolean exists0(TableField field) { + try { + create(true) + .select(field) + .from(field.getTable()) + .where(falseCondition()) + .fetch(); + + return true; + } + catch (DataAccessException e) { + return false; + } + } + + /** + * A utility method to look up a field in a single dictionary view. + * + * @param find The field to look up + * @param in The dictionary view + * @param schemaQualifier The column in the dictionary view qualifying the schema + * @param tableQualifier The column in the dictionary view qualifying the table + * @param columnQualifier The column in the dictionary view qualifying the column + */ + protected final boolean exists1( + TableField find, + Table in, + TableField schemaQualifier, + TableField tableQualifier, + TableField columnQualifier + ) { + Condition condition = columnQualifier.eq(find.getName()); + + Table table = find.getTable(); + condition = condition.and(tableQualifier.eq(table.getName())); + + Schema schema = table.getSchema(); + if (schema != null) + condition = condition.and(schemaQualifier.eq(schema.getName())); + + return create().fetchExists(in, condition); + } + @Override public final boolean existAll(TableField... f) { for (TableField field : f) @@ -435,41 +439,53 @@ public abstract class AbstractDatabase implements Database { public final boolean exists(Table table) { Boolean result = existTables.get(table); - if (result == null) { - TableQualifier qualifier = tableQualifier(); - - // [#8972] In the presence of a qualifier, avoid running an error- - // triggering query, which may lead to unwanted log messages - if (qualifier == null) { - try { - create(true) - .selectOne() - .from(table) - .where(falseCondition()) - .fetch(); - - result = true; - } - catch (DataAccessException e) { - result = false; - } - } - else { - Condition condition = qualifier.tableName().eq(table.getName()); - - Schema schema = table.getSchema(); - if (schema != null) - condition = condition.and(qualifier.tableSchema().eq(schema.getName())); - - result = create().fetchExists(qualifier.table(), condition); - } - - existTables.put(table, result); - } + if (result == null) + existTables.put(table, result = exists0(table)); return result; } + /** + * [#8972] Subclasses may override this method for a more efficient implementation. + */ + protected boolean exists0(Table table) { + try { + create(true) + .selectOne() + .from(table) + .where(falseCondition()) + .fetch(); + + return true; + } + catch (DataAccessException e) { + return false; + } + } + + /** + * A utility method to look up a table in a single dictionary view. + * + * @param find The table to look up + * @param in The dictionary view + * @param schemaQualifier The column in the dictionary view qualifying the schema + * @param tableQualifier The column in the dictionary view qualifying the table + */ + protected final boolean exists1( + Table find, + Table in, + TableField schemaQualifier, + TableField tableQualifier + ) { + Condition condition = tableQualifier.eq(find.getName()); + + Schema schema = find.getSchema(); + if (schema != null) + condition = condition.and(schemaQualifier.eq(schema.getName())); + + return create().fetchExists(in, condition); + } + @Override public final boolean existAll(Table... t) { for (Table table : t) diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/ColumnQualifier.java b/jOOQ-meta/src/main/java/org/jooq/meta/ColumnQualifier.java deleted file mode 100644 index cd98d56092..0000000000 --- a/jOOQ-meta/src/main/java/org/jooq/meta/ColumnQualifier.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed 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. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.meta; - -import org.jooq.Table; -import org.jooq.TableField; - -/** - * A qualifier for columns in the dictionary views. - * - * @author Lukas Eder - */ -public interface ColumnQualifier { - - /** - * The table containing column meta information. - */ - Table table(); - - /** - * The field specifying the column table's catalog name. - */ - TableField tableCatalog(); - - /** - * The field specifying the column table's schema name. - */ - TableField tableSchema(); - - /** - * The field specifying the column table's table name. - */ - TableField tableName(); - - /** - * The field specifying the column name. - */ - TableField columnName(); - -} diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java index 4c5749dffc..5c1ce1dfd0 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java @@ -904,18 +904,6 @@ public interface Database extends AutoCloseable { */ boolean tableValuedFunctions(); - /** - * The table qualifier used by this database, or null, if this - * database doesn't specify such a qualifier. - */ - TableQualifier tableQualifier(); - - /** - * The column qualifier used by this database, or null, if this - * database doesn't specify such a qualifier. - */ - ColumnQualifier columnQualifier(); - /** * Check for the existence of a table field in the dictionary views. */ diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnQualifier.java b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnQualifier.java deleted file mode 100644 index eac3ec9258..0000000000 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnQualifier.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed 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. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.meta; - -import org.jooq.Table; -import org.jooq.TableField; - -/** - * @author Lukas Eder - */ -public class DefaultColumnQualifier implements ColumnQualifier { - - private final Table table; - private final TableField tableCatalog; - private final TableField tableSchema; - private final TableField tableName; - private final TableField columnName; - - public DefaultColumnQualifier( - Table table, - TableField tableCatalog, - TableField tableSchema, - TableField tableName, - TableField columnName - ) { - this.table = table; - this.tableCatalog = tableCatalog; - this.tableSchema = tableSchema; - this.tableName = tableName; - this.columnName = columnName; - } - - @Override - public Table table() { - return table; - } - - @Override - public TableField tableCatalog() { - return tableCatalog; - } - - @Override - public TableField tableSchema() { - return tableSchema; - } - - @Override - public TableField tableName() { - return tableName; - } - - @Override - public TableField columnName() { - return columnName; - } -} diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultTableQualifier.java b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultTableQualifier.java deleted file mode 100644 index 9248a8ea36..0000000000 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultTableQualifier.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed 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. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.meta; - -import org.jooq.Table; -import org.jooq.TableField; - -/** - * @author Lukas Eder - */ -public class DefaultTableQualifier implements TableQualifier { - - private final Table table; - private final TableField tableCatalog; - private final TableField tableSchema; - private final TableField tableName; - - public DefaultTableQualifier( - Table table, - TableField tableCatalog, - TableField tableSchema, - TableField tableName - ) { - this.table = table; - this.tableCatalog = tableCatalog; - this.tableSchema = tableSchema; - this.tableName = tableName; - } - - @Override - public Table table() { - return table; - } - - @Override - public TableField tableCatalog() { - return tableCatalog; - } - - @Override - public TableField tableSchema() { - return tableSchema; - } - - @Override - public TableField tableName() { - return tableName; - } -} diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/TableQualifier.java b/jOOQ-meta/src/main/java/org/jooq/meta/TableQualifier.java deleted file mode 100644 index b522488f1a..0000000000 --- a/jOOQ-meta/src/main/java/org/jooq/meta/TableQualifier.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed 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. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.meta; - -import org.jooq.Table; -import org.jooq.TableField; - -/** - * A qualifier for tables in the dictionary views. - * - * @author Lukas Eder - */ -public interface TableQualifier { - - /** - * The table containing table meta information. - */ - Table table(); - - /** - * The field specifying the table's catalog name. - */ - TableField tableCatalog(); - - /** - * The field specifying the table's schema name. - */ - TableField tableSchema(); - - /** - * The field specifying the table's table name. - */ - TableField tableName(); - -} diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/h2/H2Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/h2/H2Database.java index 24658afec4..4d4e13e558 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/h2/H2Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/h2/H2Database.java @@ -37,7 +37,6 @@ */ package org.jooq.meta.h2; -import static org.jooq.impl.DSL.falseCondition; import static org.jooq.impl.DSL.field; import static org.jooq.impl.DSL.inline; import static org.jooq.impl.DSL.name; @@ -67,7 +66,8 @@ import org.jooq.Record4; import org.jooq.Result; import org.jooq.SQLDialect; import org.jooq.SortOrder; -import org.jooq.exception.DataAccessException; +import org.jooq.Table; +import org.jooq.TableField; import org.jooq.impl.DSL; import org.jooq.meta.AbstractDatabase; import org.jooq.meta.AbstractIndexDefinition; @@ -115,6 +115,16 @@ public class H2Database extends AbstractDatabase { return DSL.using(getConnection(), SQLDialect.H2); } + @Override + protected boolean exists0(TableField field) { + return exists1(field, COLUMNS, Columns.TABLE_SCHEMA, Columns.TABLE_NAME, Columns.COLUMN_NAME); + } + + @Override + protected boolean exists0(Table table) { + return exists1(table, TABLES, Tables.TABLE_SCHEMA, Tables.TABLE_NAME); + } + @Override protected List getIndexes0() throws SQLException { List result = new ArrayList<>(); @@ -619,43 +629,19 @@ public class H2Database extends AbstractDatabase { private static Boolean is1_4_198; boolean is1_4_197() { - if (is1_4_197 == null) { - // [#5874] The COLUMNS.COLUMN_TYPE column was introduced in H2 1.4.197 - try { - create(true) - .select(Columns.COLUMN_TYPE) - .from(COLUMNS) - .where(falseCondition()) - .fetch(); - - is1_4_197 = true; - } - catch (DataAccessException e) { - is1_4_197 = false; - } - } + // [#5874] The COLUMNS.COLUMN_TYPE column was introduced in H2 1.4.197 + if (is1_4_197 == null) + is1_4_197 = exists(Columns.COLUMN_TYPE); return is1_4_197; } boolean is1_4_198() { - if (is1_4_198 == null) { - // [#5874] The COLUMNS.IS_VISIBLE column was introduced in H2 1.4.198 - try { - create(true) - .select(Columns.IS_VISIBLE) - .from(COLUMNS) - .where(falseCondition()) - .fetch(); - - is1_4_198 = true; - } - catch (DataAccessException e) { - is1_4_198 = false; - } - } + // [#5874] The COLUMNS.IS_VISIBLE column was introduced in H2 1.4.198 + if (is1_4_198 == null) + is1_4_198 = exists(Columns.IS_VISIBLE); return is1_4_198; } diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/mysql/MySQLDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/mysql/MySQLDatabase.java index 7dd358db2b..2bd7737675 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/mysql/MySQLDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/mysql/MySQLDatabase.java @@ -64,7 +64,8 @@ import org.jooq.Record6; import org.jooq.Result; import org.jooq.SQLDialect; import org.jooq.SortOrder; -import org.jooq.exception.DataAccessException; +import org.jooq.Table; +import org.jooq.TableField; import org.jooq.impl.DSL; import org.jooq.meta.AbstractDatabase; import org.jooq.meta.AbstractIndexDefinition; @@ -223,17 +224,10 @@ public class MySQLDatabase extends AbstractDatabase { } protected boolean is8() { - if (is8 == null) { - // [#6602] The mysql.proc table got removed in MySQL 8.0 - try { - create(true).fetchExists(PROC); - is8 = false; - } - catch (DataAccessException ignore) { - is8 = true; - } - } + // [#6602] The mysql.proc table got removed in MySQL 8.0 + if (is8 == null) + is8 = !exists(PROC); return is8; } @@ -532,4 +526,14 @@ public class MySQLDatabase extends AbstractDatabase { protected DSLContext create0() { return DSL.using(getConnection(), SQLDialect.MYSQL); } + + @Override + protected boolean exists0(TableField field) { + return exists1(field, Columns.COLUMNS, Columns.TABLE_SCHEMA, Columns.TABLE_NAME, Columns.COLUMN_NAME); + } + + @Override + protected boolean exists0(Table table) { + return exists1(table, Tables.TABLES, Tables.TABLE_SCHEMA, Tables.TABLE_NAME); + } } diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/postgres/PostgresDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/postgres/PostgresDatabase.java index 8af491b3b8..106d243fd8 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/postgres/PostgresDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/postgres/PostgresDatabase.java @@ -95,6 +95,8 @@ import org.jooq.Result; import org.jooq.SQLDialect; import org.jooq.Select; import org.jooq.SortOrder; +import org.jooq.Table; +import org.jooq.TableField; import org.jooq.exception.DataAccessException; import org.jooq.impl.DSL; import org.jooq.impl.SQLDataType; @@ -103,17 +105,14 @@ import org.jooq.meta.AbstractIndexDefinition; import org.jooq.meta.ArrayDefinition; import org.jooq.meta.CatalogDefinition; import org.jooq.meta.ColumnDefinition; -import org.jooq.meta.ColumnQualifier; import org.jooq.meta.DataTypeDefinition; import org.jooq.meta.DefaultCheckConstraintDefinition; -import org.jooq.meta.DefaultColumnQualifier; import org.jooq.meta.DefaultDataTypeDefinition; import org.jooq.meta.DefaultDomainDefinition; import org.jooq.meta.DefaultEnumDefinition; import org.jooq.meta.DefaultIndexColumnDefinition; import org.jooq.meta.DefaultRelations; import org.jooq.meta.DefaultSequenceDefinition; -import org.jooq.meta.DefaultTableQualifier; import org.jooq.meta.DomainDefinition; import org.jooq.meta.EnumDefinition; import org.jooq.meta.IndexColumnDefinition; @@ -123,7 +122,6 @@ import org.jooq.meta.RoutineDefinition; import org.jooq.meta.SchemaDefinition; import org.jooq.meta.SequenceDefinition; import org.jooq.meta.TableDefinition; -import org.jooq.meta.TableQualifier; import org.jooq.meta.UDTDefinition; import org.jooq.meta.hsqldb.HSQLDBDatabase; import org.jooq.meta.postgres.information_schema.tables.CheckConstraints; @@ -622,7 +620,6 @@ public class PostgresDatabase extends AbstractDatabase { return result; } - @SuppressWarnings("unchecked") @Override protected List getDomains0() throws SQLException { List result = new ArrayList<>(); @@ -850,46 +847,34 @@ public class PostgresDatabase extends AbstractDatabase { } boolean is94() { - if (is94 == null) { - // [#4254] INFORMATION_SCHEMA.PARAMETERS.PARAMETER_DEFAULT was added - // in PostgreSQL 9.4 only - try { - create(true) - .select(PARAMETERS.PARAMETER_DEFAULT) - .from(PARAMETERS) - .where(falseCondition()) - .fetch(); - - is94 = true; - } - catch (DataAccessException e) { - is94 = false; - } - } + // [#4254] INFORMATION_SCHEMA.PARAMETERS.PARAMETER_DEFAULT was added + // in PostgreSQL 9.4 only + if (is94 == null) + is94 = exists(PARAMETERS.PARAMETER_DEFAULT); return is94; } boolean is11() { - if (is11 == null) { - // [#7785] pg_proc.prokind was added in PostgreSQL 11 only, and - // pg_proc.proisagg was removed, incompatibly + // [#7785] pg_proc.prokind was added in PostgreSQL 11 only, and + // pg_proc.proisagg was removed, incompatibly + if (is11 == null) is11 = exists(PG_PROC.PROKIND); - } return is11; } + @Override - public TableQualifier tableQualifier() { - return new DefaultTableQualifier(TABLES, TABLES.TABLE_CATALOG, TABLES.TABLE_SCHEMA, TABLES.TABLE_NAME); + protected boolean exists0(TableField field) { + return exists1(field, COLUMNS, COLUMNS.TABLE_SCHEMA, COLUMNS.TABLE_NAME, COLUMNS.COLUMN_NAME); } @Override - public ColumnQualifier columnQualifier() { - return new DefaultColumnQualifier(COLUMNS, COLUMNS.TABLE_CATALOG, COLUMNS.TABLE_SCHEMA, COLUMNS.TABLE_NAME, COLUMNS.COLUMN_NAME); + protected boolean exists0(Table table) { + return exists1(table, TABLES, TABLES.TABLE_SCHEMA, TABLES.TABLE_NAME); } boolean canCombineArrays() { @@ -929,18 +914,11 @@ public class PostgresDatabase extends AbstractDatabase { } boolean canUseRoutines() { - if (canUseRoutines == null) { - // [#7892] The information_schema.routines table is not available in all PostgreSQL - // style databases, e.g. CockroachDB - try { - create(true).fetchExists(ROUTINES); - canUseRoutines = true; - } - catch (DataAccessException e) { - canUseRoutines = false; - } - } + // [#7892] The information_schema.routines table is not available in all PostgreSQL + // style databases, e.g. CockroachDB + if (canUseRoutines == null) + canUseRoutines = exists(ROUTINES); return canUseRoutines; } diff --git a/jOOQ/src/main/java/org/jooq/conf/MiniJAXB.java b/jOOQ/src/main/java/org/jooq/conf/MiniJAXB.java deleted file mode 100644 index b9c420f7c9..0000000000 --- a/jOOQ/src/main/java/org/jooq/conf/MiniJAXB.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Licensed 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. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.conf; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.XmlAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.jooq.exception.ConfigurationException; -import org.jooq.tools.Convert; -import org.jooq.tools.reflect.Reflect; -import org.jooq.tools.reflect.ReflectException; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; - -/** - * This class allows for mashalling / unmarshalling XML content to jOOQ - * configuration objects. - *

- * With jOOQ 3.12, the JAXB dependency has been removed in favour of this home - * grown solution. Due to the modularisation that happened with JDK 9+ and the - * removal of JAXB from the JDK 11+, it is unreasonable to leave the burden of - * properly configuring transitive JAXB dependency to jOOQ users. - * - * @author Lukas Eder - */ -public class MiniJAXB { - - public static String marshal(Object object) { - StringWriter writer = new StringWriter(); - marshal(object, writer); - return writer.toString(); - } - - public static void marshal(Object object, OutputStream out) { - marshal(object, new OutputStreamWriter(out)); - } - - public static void marshal(Object object, Writer out) { - try { - XmlRootElement e = object.getClass().getAnnotation(XmlRootElement.class); - if (e != null) - out.write("<" + e.name() + ">"); - - out.write(object.toString()); - - if (e != null) - out.write(""); - } - catch (Exception e) { - throw new ConfigurationException("Cannot print object", e); - } - } - - public static T unmarshal(InputStream in, Class type) { - return unmarshal0(new InputSource(in), type); - } - - public static T unmarshal(String xml, Class type) { - return unmarshal0(new InputSource(new StringReader(xml)), type); - } - - public static T unmarshal(File xml, Class type) { - try { - return unmarshal0(new InputSource(new FileInputStream(xml)), type); - } - catch (Exception e) { - throw new ConfigurationException("Error while opening file", e); - } - } - - private static T unmarshal0(InputSource in, Class type) { - try { - Document document = builder().parse(in); - T result = Reflect.on(type).create().get(); - unmarshal0(result, document.getDocumentElement()); - return result; - } - catch (Exception e) { - throw new ConfigurationException("Error while reading xml", e); - } - } - - private static void unmarshal0(Object result, Element element) throws Exception { - if (result == null) - return; - - Class type = result.getClass(); - for (Field child : type.getDeclaredFields()) { - int modifiers = child.getModifiers(); - if (Modifier.isFinal(modifiers) || - Modifier.isStatic(modifiers)) - continue; - - XmlElementWrapper w = child.getAnnotation(XmlElementWrapper.class); - XmlElement e = child.getAnnotation(XmlElement.class); - XmlJavaTypeAdapter a = child.getAnnotation(XmlJavaTypeAdapter.class); - - String childName = child.getName(); - String childElementName = - w != null - ? "##default".equals(w.name()) - ? child.getName() - : w.name() - : e == null || "##default".equals(e.name()) - ? childName - : e.name(); - - Element childElement = child(element, childElementName); - if (childElement == null) - continue; - - Class childType = child.getType(); - if (List.class.isAssignableFrom(childType) && w != null && e != null) { - List list = new ArrayList(); - unmarshalList0(list, childElement, e.name(), (Class) ((ParameterizedType) child.getGenericType()).getActualTypeArguments()[0]); - Reflect.on(result).set(childName, list); - } - else if (childType.getAnnotation(XmlEnum.class) != null) { - Reflect.on(result).set(childName, Convert.convert(childElement.getTextContent().trim(), childType)); - } - else if (childType.getAnnotation(XmlType.class) != null) { - Object object = Reflect.on(childType).create().get(); - Reflect.on(result).set(childName, object); - - unmarshal0(object, childElement); - } - else if (a != null) { - @SuppressWarnings("unchecked") - XmlAdapter adapter = a.value().getConstructor().newInstance(); - Reflect.on(result).set(childName, adapter.unmarshal(childElement.getTextContent().trim())); - } - else { - Reflect.on(result).set(childName, Convert.convert(childElement.getTextContent().trim(), childType)); - } - } - } - - private static void unmarshalList0(List result, Element element, String name, Class type) throws Exception { - if (result == null) - return; - - NodeList list = element.getChildNodes(); - for (int i = 0; i < list.getLength(); i++) { - Node item = list.item(i); - - if (item.getNodeType() == Node.ELEMENT_NODE) { - if (name.equals(((Element) item).getTagName()) || name.equals(((Element) item).getLocalName())) { - Object o = Reflect.on(type).create().get(); - unmarshal0(o, (Element) item); - result.add(o); - } - } - } - } - - private static Element child(Element element, String name) { - NodeList list = element.getChildNodes(); - - for (int i = 0; i < list.getLength(); i++) { - Node item = list.item(i); - - if (item.getNodeType() == Node.ELEMENT_NODE) - if (name.equals(((Element) item).getTagName()) || name.equals(((Element) item).getLocalName())) - return (Element) item; - } - - return null; - } - - public static DocumentBuilder builder() { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - - // ----------------------------------------------------------------- - // [JOOX #136] FIX START: Prevent OWASP attack vectors - try { - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - } - catch (ParserConfigurationException ignore) {} - - try { - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - } - catch (ParserConfigurationException ignore) {} - - try { - factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); - } - catch (ParserConfigurationException ignore) {} - - // [JOOX #149] Not implemented on Android - try { - factory.setXIncludeAware(false); - } - catch (UnsupportedOperationException ignore) {} - - factory.setExpandEntityReferences(false); - // [JOOX #136] FIX END - // ----------------------------------------------------------------- - - // [JOOX #9] [JOOX #107] In order to take advantage of namespace-related DOM - // features, the internal builder should be namespace-aware - factory.setNamespaceAware(true); - DocumentBuilder builder = factory.newDocumentBuilder(); - - return builder; - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Appends a second JAXB annotated object to a - * first one using Maven's - * combine.children="append" semantics. - * - * @return The modified first argument. - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static T append(T first, T second) { - if (first == null) - return second; - if (second == null) - return first; - - Class klass = (Class) first.getClass(); - if (klass != second.getClass()) - throw new IllegalArgumentException("Can only append identical types"); - // [#8527] support enum types - else if (klass.isEnum()) - return first; - - // We're assuming that XJC generated objects are all in the same package - Package pkg = klass.getPackage(); - try { - T defaults = klass.getConstructor().newInstance(); - - for (Method setter : klass.getMethods()) { - if (setter.getName().startsWith("set")) { - Method getter; - - try { - getter = klass.getMethod("get" + setter.getName().substring(3)); - } - catch (NoSuchMethodException e) { - getter = klass.getMethod("is" + setter.getName().substring(3)); - } - - Class childType = setter.getParameterTypes()[0]; - Object firstChild = getter.invoke(first); - Object secondChild = getter.invoke(second); - Object defaultChild = getter.invoke(defaults); - - if (Collection.class.isAssignableFrom(childType)) - ((List) firstChild).addAll((List) secondChild); - else if (secondChild != null && (firstChild == null || firstChild.equals(defaultChild))) - setter.invoke(first, secondChild); - else if (secondChild != null && pkg == childType.getPackage()) - append(firstChild, secondChild); - else - ; // All other types cannot be merged - } - } - } - catch (Exception e) { - throw new ReflectException(e); - } - - return first; - } -} diff --git a/jOOQ/src/main/java/org/jooq/impl/CombinedCompareCondition.java b/jOOQ/src/main/java/org/jooq/impl/CombinedCompareCondition.java deleted file mode 100644 index 5ba9928271..0000000000 --- a/jOOQ/src/main/java/org/jooq/impl/CombinedCompareCondition.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed 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. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.impl; - -import java.util.ArrayList; -import java.util.Collection; - -import org.jooq.Comparator; -import org.jooq.Condition; -import org.jooq.Context; -import org.jooq.Field; -import org.jooq.LikeEscapeStep; -import org.jooq.Operator; - -final class CombinedCompareCondition extends AbstractCondition implements LikeEscapeStep { - - private static final long serialVersionUID = 1850816878293293314L; - - private final Field field; - private final Comparator comparator; - private final Quantifier quantifier; - private final Collection> values; - private Character escape; - - public CombinedCompareCondition(Field field, Comparator comparator, Quantifier quantifier, Collection> values) { - this.field = field; - this.comparator = comparator; - this.quantifier = quantifier; - this.values = values; - } - - @Override - public final Condition escape(char c) { - this.escape = c; - return this; - } - - @Override - public final void accept(Context ctx) { - Collection conditions = new ArrayList(); - - switch (comparator) { - case LIKE: - for (Field value : values) - conditions.add(escape != null ? field.like(value, escape) : field.like(value)); - break; - - case NOT_LIKE: - for (Field value : values) - conditions.add(escape != null ? field.notLike(value, escape) : field.notLike(value)); - break; - - case SIMILAR_TO: - for (Field value : values) - conditions.add(escape != null ? field.similarTo(value, escape) : field.similarTo(value)); - break; - - case NOT_SIMILAR_TO: - for (Field value : values) - conditions.add(escape != null ? field.notSimilarTo(value, escape) : field.notSimilarTo(value)); - break; - - case LIKE_IGNORE_CASE: - for (Field value : values) - conditions.add(escape != null ? field.likeIgnoreCase(value, escape) : field.likeIgnoreCase(value)); - break; - - case NOT_LIKE_IGNORE_CASE: - for (Field value : values) - conditions.add(escape != null ? field.notLikeIgnoreCase(value, escape) : field.notLikeIgnoreCase(value)); - break; - - default: - break; - } - - Condition combinedCondition = CombinedCondition.of(quantifier == Quantifier.ALL ? Operator.AND : Operator.OR, conditions); - ctx.visit(combinedCondition); - } - -}