CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c58b6f40 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c58b6f40 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c58b6f40 Branch: refs/heads/master Commit: c58b6f406e81de4d90abe888b763a1292c77feb8 Parents: 2c9896c Author: Nikita Timofeev <[email protected]> Authored: Tue Jul 25 12:35:50 2017 +0300 Committer: Nikita Timofeev <[email protected]> Committed: Tue Jul 25 12:35:50 2017 +0300 ---------------------------------------------------------------------- .../upgrade/v6/XMLDataMapLoader_V3_0_0_1.java | 51 - .../project/upgrade/v8/ProjectUpgrader_V8.java | 42 - .../configuration/DataChannelDescriptor.java | 46 +- .../configuration/DataNodeDescriptor.java | 39 +- .../EmptyConfigurationNodeVisitor.java | 108 ++ .../configuration/SAXNestedTagHandler.java | 131 -- .../XMLDataChannelDescriptorLoader.java | 389 ------ .../cayenne/configuration/XMLDataMapLoader.java | 57 - .../configuration/server/ServerModule.java | 11 +- .../xml/DataChannelChildrenHandler.java | 133 ++ .../configuration/xml/DataChannelHandler.java | 78 ++ .../configuration/xml/DataChannelMetaData.java | 64 + .../configuration/xml/DataMapHandler.java | 142 ++ .../xml/DataMapLoaderListener.java | 31 + .../xml/DataNodeChildrenHandler.java | 71 + .../xml/DataSourceChildrenHandler.java | 175 +++ .../configuration/xml/DbEntityHandler.java | 146 ++ .../xml/DbKeyGeneratorHandler.java | 117 ++ .../xml/DbRelationshipHandler.java | 97 ++ .../xml/DefaultDataChannelMetaData.java | 91 ++ .../xml/DefaultHandlerFactory.java | 44 + .../xml/EmbeddableAttributeHandler.java | 69 + .../configuration/xml/EmbeddableHandler.java | 75 ++ .../configuration/xml/HandlerFactory.java | 30 + .../configuration/xml/LoaderContext.java | 63 + .../xml/NamespaceAwareNestedTagHandler.java | 97 ++ .../xml/NoopDataChannelMetaData.java | 42 + .../configuration/xml/ObjEntityHandler.java | 210 +++ .../xml/ObjRelationshipHandler.java | 109 ++ .../configuration/xml/ProcedureHandler.java | 114 ++ .../xml/QueryDescriptorHandler.java | 191 +++ .../configuration/xml/RootDataMapHandler.java | 51 + .../configuration/xml/SAXNestedTagHandler.java | 175 +++ .../xml/XMLDataChannelDescriptorLoader.java | 149 +++ .../configuration/xml/XMLDataMapLoader.java | 102 ++ .../org/apache/cayenne/conn/DataSourceInfo.java | 47 +- .../java/org/apache/cayenne/exp/Expression.java | 10 +- .../java/org/apache/cayenne/map/Attribute.java | 4 +- .../org/apache/cayenne/map/CallbackMap.java | 6 +- .../java/org/apache/cayenne/map/DataMap.java | 131 +- .../org/apache/cayenne/map/DbAttribute.java | 32 +- .../java/org/apache/cayenne/map/DbEntity.java | 33 +- .../java/org/apache/cayenne/map/DbJoin.java | 24 +- .../org/apache/cayenne/map/DbKeyGenerator.java | 29 +- .../org/apache/cayenne/map/DbRelationship.java | 28 +- .../cayenne/map/EJBQLQueryDescriptor.java | 19 +- .../java/org/apache/cayenne/map/Embeddable.java | 20 +- .../apache/cayenne/map/EmbeddableAttribute.java | 26 +- .../apache/cayenne/map/EmbeddedAttribute.java | 33 +- .../org/apache/cayenne/map/EntityListener.java | 4 +- .../java/org/apache/cayenne/map/MapLoader.java | 1261 ------------------ .../org/apache/cayenne/map/ObjAttribute.java | 32 +- .../java/org/apache/cayenne/map/ObjEntity.java | 86 +- .../org/apache/cayenne/map/ObjRelationship.java | 49 +- .../java/org/apache/cayenne/map/Procedure.java | 39 +- .../apache/cayenne/map/ProcedureParameter.java | 47 +- .../cayenne/map/ProcedureQueryDescriptor.java | 36 +- .../org/apache/cayenne/map/QueryDescriptor.java | 58 +- .../cayenne/map/QueryDescriptorLoader.java | 32 +- .../cayenne/map/SQLTemplateDescriptor.java | 53 +- .../cayenne/map/SelectQueryDescriptor.java | 46 +- .../apache/cayenne/query/BaseQueryMetadata.java | 38 +- .../org/apache/cayenne/query/EJBQLQuery.java | 25 +- .../java/org/apache/cayenne/query/Ordering.java | 26 +- .../apache/cayenne/query/PrefetchTreeNode.java | 34 +- .../apache/cayenne/query/ProcedureQuery.java | 52 +- .../org/apache/cayenne/query/SQLTemplate.java | 91 +- .../org/apache/cayenne/query/SelectQuery.java | 72 +- .../reflect/LifecycleCallbackEventHandler.java | 19 +- .../cayenne/remote/IncrementalSelectQuery.java | 5 - .../org/apache/cayenne/util/XMLEncoder.java | 326 +++-- .../apache/cayenne/util/XMLSerializable.java | 4 +- .../org/apache/cayenne/schema/10/dbimport.xsd | 106 ++ .../org/apache/cayenne/schema/10/domain.xsd | 130 ++ .../org/apache/cayenne/schema/10/info.xsd | 29 + .../org/apache/cayenne/schema/10/modelMap.xsd | 356 +++++ .../XMLDataChannelDescriptorLoaderTest.java | 165 --- .../configuration/xml/BaseHandlerTest.java | 76 ++ .../configuration/xml/DbEntityHandlerTest.java | 82 ++ .../xml/DbKeyGeneratorHandlerTest.java | 51 + .../xml/DbRelationshipHandlerTest.java | 58 + .../configuration/xml/ObjEntityHandlerTest.java | 86 ++ .../xml/ObjRelationshipHandlerTest.java | 61 + .../xml/XMLDataChannelDescriptorLoaderTest.java | 171 +++ .../configuration/xml/XMLDataMapLoaderTest.java | 158 +++ .../org/apache/cayenne/map/DataMapTest.java | 41 +- .../apache/cayenne/map/MapLoaderLoadTest.java | 175 --- .../org/apache/cayenne/map/MockAttribute.java | 4 +- .../java/org/apache/cayenne/map/MockEntity.java | 4 +- .../apache/cayenne/map/MockRelationship.java | 4 +- .../apache/cayenne/map/ObjRelationshipIT.java | 6 +- .../cayenne/map/QueryDescriptorLoaderTest.java | 6 +- .../org/apache/cayenne/query/EJBQLQueryIT.java | 30 +- .../cayenne/unit/di/server/DBCleaner.java | 2 +- .../cayenne/unit/di/server/SchemaBuilder.java | 16 +- .../unit/di/server/ServerCaseModule.java | 8 +- .../src/test/resources/array-type.map.xml | 32 +- .../src/test/resources/binary-pk.map.xml | 64 +- .../src/test/resources/cay-2032.map.xml | 13 +- .../test/resources/cay743/cayenne-domain.xml | 2 +- .../src/test/resources/cay743/map1.map.xml | 6 +- .../src/test/resources/cay743/map2.map.xml | 6 +- .../src/test/resources/cayenne-array-type.xml | 5 +- .../src/test/resources/cayenne-binary-pk.xml | 5 +- .../src/test/resources/cayenne-cay-2032.xml | 3 +- .../src/test/resources/cayenne-compound.xml | 5 +- .../src/test/resources/cayenne-date-time.xml | 5 +- .../src/test/resources/cayenne-delete-rules.xml | 5 +- .../src/test/resources/cayenne-embeddable.xml | 5 +- .../src/test/resources/cayenne-empty.xml | 5 +- .../src/test/resources/cayenne-enum.xml | 3 +- .../test/resources/cayenne-extended-type.xml | 5 +- .../src/test/resources/cayenne-generated.xml | 5 +- .../src/test/resources/cayenne-generic.xml | 5 +- .../cayenne-inheritance-single-table1.xml | 3 +- .../resources/cayenne-inheritance-vertical.xml | 3 +- .../src/test/resources/cayenne-inheritance.xml | 5 +- .../cayenne-lifecycle-callbacks-order.xml | 5 +- .../src/test/resources/cayenne-lifecycles.xml | 5 +- .../src/test/resources/cayenne-lob.xml | 5 +- .../src/test/resources/cayenne-locking.xml | 3 +- .../src/test/resources/cayenne-map-to-many.xml | 5 +- .../test/resources/cayenne-meaningful-pk.xml | 5 +- .../src/test/resources/cayenne-misc-types.xml | 5 +- .../cayenne-mixed-persistence-strategy.xml | 5 +- .../src/test/resources/cayenne-multi-tier.xml | 3 +- .../src/test/resources/cayenne-multinode.xml | 3 +- .../src/test/resources/cayenne-no-pk.xml | 5 +- .../test/resources/cayenne-numeric-types.xml | 5 +- .../src/test/resources/cayenne-oneway-rels.xml | 3 +- ...nne.configuration.rop.server.test-config.xml | 4 +- .../src/test/resources/cayenne-people.xml | 3 +- .../src/test/resources/cayenne-primitive.xml | 5 +- .../src/test/resources/cayenne-qualified.xml | 3 +- .../resources/cayenne-quoted-identifiers.xml | 3 +- .../src/test/resources/cayenne-reflexive.xml | 5 +- .../cayenne-relationships-activity.xml | 3 +- .../cayenne-relationships-child-master.xml | 5 +- .../resources/cayenne-relationships-clob.xml | 3 +- ...cayenne-relationships-collection-to-many.xml | 5 +- .../cayenne-relationships-delete-rules.xml | 5 +- .../cayenne-relationships-flattened.xml | 3 +- .../cayenne-relationships-set-to-many.xml | 5 +- .../cayenne-relationships-to-many-fk.xml | 5 +- .../cayenne-relationships-to-one-fk.xml | 5 +- .../test/resources/cayenne-relationships.xml | 3 +- .../src/test/resources/cayenne-return-types.xml | 5 +- .../src/test/resources/cayenne-soft-delete.xml | 5 +- .../src/test/resources/cayenne-sus.xml | 3 +- .../test/resources/cayenne-table-primitives.xml | 5 +- .../src/test/resources/cayenne-testmap.xml | 2 +- .../src/test/resources/cayenne-things.xml | 5 +- .../src/test/resources/cayenne-toone.xml | 5 +- .../cayenne-unsupported-distinct-types.xml | 3 +- .../src/test/resources/cayenne-uuid.xml | 5 +- .../test/resources/cayenne-weighted-sort.xml | 3 +- .../src/test/resources/compound.map.xml | 124 +- .../src/test/resources/custom-name-file.xml | 2 +- .../src/test/resources/date-time.map.xml | 64 +- .../src/test/resources/delete-rules.map.xml | 124 +- .../src/test/resources/embeddable.map.xml | 6 +- cayenne-server/src/test/resources/empty.map.xml | 14 +- cayenne-server/src/test/resources/enum.map.xml | 6 +- .../src/test/resources/extended-type.map.xml | 32 +- .../src/test/resources/generated.map.xml | 180 ++- .../src/test/resources/generic.map.xml | 8 +- .../resources/inheritance-single-table1.map.xml | 18 +- .../test/resources/inheritance-vertical.map.xml | 59 +- .../src/test/resources/inheritance.map.xml | 86 +- .../resources/lifecycle-callbacks-order.map.xml | 28 +- .../src/test/resources/lifecycles.map.xml | 28 +- cayenne-server/src/test/resources/lob.map.xml | 102 +- .../src/test/resources/locking.map.xml | 10 +- .../src/test/resources/map-db1.map.xml | 6 +- .../src/test/resources/map-db2.map.xml | 10 +- .../src/test/resources/map-to-many.map.xml | 99 +- .../src/test/resources/meaningful-pk.map.xml | 74 +- .../src/test/resources/misc-types.map.xml | 72 +- .../mixed-persistence-strategy.map.xml | 68 +- .../src/test/resources/multi-tier.map.xml | 23 +- cayenne-server/src/test/resources/no-pk.map.xml | 30 +- .../src/test/resources/numeric-types.map.xml | 154 +-- .../src/test/resources/oneway-rels.map.xml | 17 +- .../configuration/cayenne-testConfig1.xml | 4 - .../configuration/cayenne-testConfig2.xml | 4 - .../configuration/cayenne-testConfig3.xml | 14 - .../configuration/testConfigMap2.map.xml | 7 - .../configuration/testConfigMap3_1.map.xml | 7 - .../configuration/testConfigMap3_2.map.xml | 7 - .../configuration/xml/DbEntityHandlerTest.xml | 25 + .../xml/DbKeyGeneratorHandlerTest.xml | 24 + .../xml/DbRelationshipHandlerTest.xml | 22 + .../configuration/xml/ObjEntityHandlerTest.xml | 38 + .../xml/ObjRelationshipHandlerTest.xml | 20 + .../configuration/xml/cayenne-testConfig1.xml | 4 + .../configuration/xml/cayenne-testConfig2.xml | 4 + .../configuration/xml/cayenne-testConfig3.xml | 14 + .../configuration/xml/testConfigMap2.map.xml | 26 + .../configuration/xml/testConfigMap3_1.map.xml | 26 + .../configuration/xml/testConfigMap3_2.map.xml | 26 + .../configuration/xml/testConfigMap4.map.xml | 314 +++++ .../src/test/resources/people.map.xml | 16 +- .../src/test/resources/primitive.map.xml | 36 +- .../src/test/resources/qualified.map.xml | 8 +- .../test/resources/quoted-identifiers.map.xml | 10 +- .../src/test/resources/reflexive.map.xml | 46 +- .../resources/relationships-activity.map.xml | 6 +- .../relationships-child-master.map.xml | 52 +- .../test/resources/relationships-clob.map.xml | 8 +- .../relationships-collection-to-many.map.xml | 46 +- .../relationships-delete-rules.map.xml | 133 +- .../resources/relationships-flattened.map.xml | 29 +- .../resources/relationships-set-to-many.map.xml | 46 +- .../resources/relationships-to-many-fk.map.xml | 92 +- .../resources/relationships-to-one-fk.map.xml | 46 +- .../src/test/resources/relationships.map.xml | 17 +- .../src/test/resources/return-types.map.xml | 180 +-- .../src/test/resources/soft-delete.map.xml | 32 +- .../src/test/resources/sus-map.map.xml | 6 +- .../src/test/resources/table-primitives.map.xml | 32 +- .../src/test/resources/testmap.map.xml | 39 +- .../src/test/resources/things.map.xml | 216 +-- cayenne-server/src/test/resources/toone.map.xml | 48 +- .../unsupported-distinct-types.map.xml | 42 +- .../resources/url conversion/cayenne-empty.xml | 4 + .../test/resources/url conversion/empty.map.xml | 9 + cayenne-server/src/test/resources/uuid.map.xml | 44 +- .../src/test/resources/weighted-sort.map.xml | 14 +- 228 files changed, 6936 insertions(+), 4946 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java ---------------------------------------------------------------------- diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java deleted file mode 100644 index 6dc3d52..0000000 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************** - * 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. - ****************************************************************/ -package org.apache.cayenne.project.upgrade.v6; - -import java.io.InputStream; -import java.net.URL; - -import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.map.MapLoader; -import org.apache.cayenne.resource.Resource; -import org.xml.sax.InputSource; - -/** - * @since 3.1 - */ -class XMLDataMapLoader_V3_0_0_1 { - - public DataMap load(Resource configurationResource) throws CayenneRuntimeException { - - MapLoader mapLoader = new MapLoader(); - URL url = configurationResource.getURL(); - - DataMap map; - - try (InputStream in = url.openStream();) { - - map = mapLoader.loadDataMap(new InputSource(in)); - } catch (Exception e) { - throw new CayenneRuntimeException("Error loading configuration from %s", e, url); - } - - return map; - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java ---------------------------------------------------------------------- diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java deleted file mode 100644 index 461d118..0000000 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************** - * 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. - ****************************************************************/ -package org.apache.cayenne.project.upgrade.v8; - -import org.apache.cayenne.di.Inject; -import org.apache.cayenne.di.Injector; -import org.apache.cayenne.project.upgrade.ProjectUpgrader; -import org.apache.cayenne.project.upgrade.UpgradeHandler; -import org.apache.cayenne.resource.Resource; - -/** - * A ProjectUpgrader that handles project upgrades from version 4.0.M3 and 7 - * to version 8. - */ -public class ProjectUpgrader_V8 implements ProjectUpgrader { - - @Inject - protected Injector injector; - - @Override - public UpgradeHandler getUpgradeHandler(Resource projectSource) { - UpgradeHandler_V8 handler = new UpgradeHandler_V8(projectSource); - injector.injectMembers(handler); - return handler; - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java index bc3929b..92bd8bb 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java @@ -40,6 +40,11 @@ public class DataChannelDescriptor implements ConfigurationNode, Serializable, X private static final long serialVersionUID = 6567527544207035602L; + /** + * The namespace in which the data map XML file will be created. + */ + public static final String SCHEMA_XSD = "http://cayenne.apache.org/schema/10/domain"; + protected String name; protected Map<String, String> properties; protected Collection<DataMap> dataMaps; @@ -53,58 +58,41 @@ public class DataChannelDescriptor implements ConfigurationNode, Serializable, X nodeDescriptors = new ArrayList<>(3); } - public void encodeAsXML(XMLEncoder encoder) { + @Override + public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) { - encoder.print("<domain"); - encoder.printProjectVersion(); - encoder.println(">"); - - encoder.indent(1); - boolean breakNeeded = false; + encoder.start("domain") + .attribute("xmlns", SCHEMA_XSD) + .attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance", true) + .attribute("xsi:schemaLocation", SCHEMA_XSD + " " + SCHEMA_XSD + ".xsd", true) + .projectVersion(); if (!properties.isEmpty()) { - breakNeeded = true; - List<String> keys = new ArrayList<>(properties.keySet()); Collections.sort(keys); for (String key : keys) { - encoder.printProperty(key, properties.get(key)); + encoder.property(key, properties.get(key)); } } if (!dataMaps.isEmpty()) { - if (breakNeeded) { - encoder.println(); - } else { - breakNeeded = true; - } - List<DataMap> maps = new ArrayList<>(this.dataMaps); Collections.sort(maps); for (DataMap dataMap : maps) { - - encoder.print("<map"); - encoder.printAttribute("name", dataMap.getName().trim()); - encoder.println("/>"); + encoder.start("map").attribute("name", dataMap.getName().trim()).end(); } } if (!nodeDescriptors.isEmpty()) { - if (breakNeeded) { - encoder.println(); - } else { - breakNeeded = true; - } - List<DataNodeDescriptor> nodes = new ArrayList<>(nodeDescriptors); Collections.sort(nodes); - encoder.print(nodes); + encoder.nested(nodes, delegate); } - encoder.indent(-1); - encoder.println("</domain>"); + delegate.visitDataChannelDescriptor(this); + encoder.end(); } public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) { http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java index 7192d0d..6ece619 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java @@ -81,57 +81,50 @@ public class DataNodeDescriptor implements ConfigurationNode, XMLSerializable, this.dataChannelDescriptor = dataChannelDescriptor; } + @Override public int compareTo(DataNodeDescriptor o) { String o1 = getName(); String o2 = o.getName(); if (o1 == null) { return (o2 != null) ? -1 : 0; - } - else if (o2 == null) { + } else if (o2 == null) { return 1; } - else { - return o1.compareTo(o2); - } + return o1.compareTo(o2); } + @Override public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) { return visitor.visitDataNodeDescriptor(this); } - public void encodeAsXML(XMLEncoder encoder) { - encoder.print("<node"); - encoder.printlnAttribute("name", name); - encoder.indent(1); - - encoder.printlnAttribute("adapter", adapterType); - encoder.printlnAttribute("factory", dataSourceFactoryType); + @Override + public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) { + encoder.start("node") + .attribute("name", name, false) + .attribute("adapter", adapterType, true) + .attribute("factory", dataSourceFactoryType, true); if (!XMLPoolingDataSourceFactory.class.getName().equals(dataSourceFactoryType)) { - encoder.printlnAttribute("parameters", parameters); + encoder.attribute("parameters", parameters); } - encoder.printlnAttribute("schema-update-strategy", schemaUpdateStrategyType); - encoder.println(">"); + encoder.attribute("schema-update-strategy", schemaUpdateStrategyType, true); if (!dataMapNames.isEmpty()) { - List<String> names = new ArrayList<>(dataMapNames); Collections.sort(names); - for (String mapName : names) { - encoder.print("<map-ref"); - encoder.printAttribute("name", mapName); - encoder.println("/>"); + encoder.start("map-ref").attribute("name", mapName).end(); } } if (dataSourceDescriptor != null && XMLPoolingDataSourceFactory.class.getName().equals(dataSourceFactoryType)) { - dataSourceDescriptor.encodeAsXML(encoder); + dataSourceDescriptor.encodeAsXML(encoder, delegate); } - encoder.indent(-1); - encoder.println("</node>"); + delegate.visitDataNodeDescriptor(this); + encoder.end(); } public String getName() { http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java new file mode 100644 index 0000000..84289d2 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java @@ -0,0 +1,108 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration; + +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.DbAttribute; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.Embeddable; +import org.apache.cayenne.map.EmbeddableAttribute; +import org.apache.cayenne.map.ObjAttribute; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.map.ObjRelationship; +import org.apache.cayenne.map.Procedure; +import org.apache.cayenne.map.ProcedureParameter; +import org.apache.cayenne.map.QueryDescriptor; + +/** + * @since 4.1 + */ +public class EmptyConfigurationNodeVisitor implements ConfigurationNodeVisitor<Void> { + @Override + public Void visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) { + return null; + } + + @Override + public Void visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) { + return null; + } + + @Override + public Void visitDataMap(DataMap dataMap) { + return null; + } + + @Override + public Void visitObjEntity(ObjEntity entity) { + return null; + } + + @Override + public Void visitDbEntity(DbEntity entity) { + return null; + } + + @Override + public Void visitEmbeddable(Embeddable embeddable) { + return null; + } + + @Override + public Void visitEmbeddableAttribute(EmbeddableAttribute attribute) { + return null; + } + + @Override + public Void visitObjAttribute(ObjAttribute attribute) { + return null; + } + + @Override + public Void visitDbAttribute(DbAttribute attribute) { + return null; + } + + @Override + public Void visitObjRelationship(ObjRelationship relationship) { + return null; + } + + @Override + public Void visitDbRelationship(DbRelationship relationship) { + return null; + } + + @Override + public Void visitProcedure(Procedure procedure) { + return null; + } + + @Override + public Void visitProcedureParameter(ProcedureParameter parameter) { + return null; + } + + @Override + public Void visitQuery(QueryDescriptor query) { + return null; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java deleted file mode 100644 index 3891e83..0000000 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java +++ /dev/null @@ -1,131 +0,0 @@ -/***************************************************************** - * 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. - ****************************************************************/ -package org.apache.cayenne.configuration; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -/** - * A superclass of nested tag handlers for parsing of XML documents with SAX. - * - * @since 3.1 - */ -public class SAXNestedTagHandler extends DefaultHandler { - - private final static Locator NOOP_LOCATOR = new Locator() { - - public int getColumnNumber() { - return -1; - } - - public int getLineNumber() { - return -1; - } - - public String getPublicId() { - return "<unknown>"; - } - - public String getSystemId() { - return "<unknown>"; - } - }; - - protected XMLReader parser; - protected ContentHandler parentHandler; - protected Locator locator; - - public SAXNestedTagHandler(XMLReader parser, SAXNestedTagHandler parentHandler) { - this.parentHandler = parentHandler; - this.parser = parser; - - if (parentHandler != null) { - locator = parentHandler.locator; - } - - if (locator == null) { - locator = NOOP_LOCATOR; - } - } - - protected String unexpectedTagMessage(String tagFound, String... tagsExpected) { - - List<String> expected = tagsExpected != null - ? Arrays.asList(tagsExpected) - : Collections.<String> emptyList(); - - return String - .format( - "tag <%s> is unexpected at [%d,%d]. The following tags are allowed here: %s", - tagFound, - locator.getColumnNumber(), - locator.getLineNumber(), - expected); - } - - protected ContentHandler createChildTagHandler( - String namespaceURI, - String localName, - String qName, - Attributes attributes) { - - // loose handling of unrecognized tags - just ignore them - return new SAXNestedTagHandler(parser, this); - } - - protected void stop() { - // pop self from the handler stack - parser.setContentHandler(parentHandler); - } - - @Override - public final void startElement( - String namespaceURI, - String localName, - String qName, - Attributes attributes) throws SAXException { - - // push child handler to the stack... - ContentHandler childHandler = createChildTagHandler( - namespaceURI, - localName, - qName, - attributes); - parser.setContentHandler(childHandler); - } - - @Override - public void endElement(String namespaceURI, String localName, String qName) - throws SAXException { - stop(); - } - - @Override - public void setDocumentLocator(Locator locator) { - this.locator = locator; - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java deleted file mode 100644 index ad9341a..0000000 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java +++ /dev/null @@ -1,389 +0,0 @@ -/***************************************************************** - * 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. - ****************************************************************/ -package org.apache.cayenne.configuration; - -import org.apache.cayenne.ConfigurationException; -import org.apache.cayenne.conn.DataSourceInfo; -import org.apache.cayenne.di.AdhocObjectFactory; -import org.apache.cayenne.di.Inject; -import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.resource.Resource; -import org.apache.cayenne.util.Util; -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.InputSource; -import org.xml.sax.XMLReader; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; - -/** - * @since 3.1 - */ -public class XMLDataChannelDescriptorLoader implements DataChannelDescriptorLoader { - - private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class); - - static final String DOMAIN_TAG = "domain"; - static final String MAP_TAG = "map"; - static final String NODE_TAG = "node"; - static final String PROPERTY_TAG = "property"; - static final String MAP_REF_TAG = "map-ref"; - static final String DATA_SOURCE_TAG = "data-source"; - - /** - * @deprecated the caller should use password resolving strategy instead of - * resolving the password on the spot. For one thing this can be - * used in the Modeler and no password may be available. - */ - @Deprecated - private static String passwordFromURL(URL url) { - InputStream inputStream = null; - String password = null; - - try { - inputStream = url.openStream(); - password = passwordFromInputStream(inputStream); - } catch (IOException exception) { - // Log the error while trying to open the stream. A null - // password will be returned as a result. - logger.warn(exception.getMessage(), exception); - } - - return password; - } - - /** - * @deprecated the caller should use password resolving strategy instead of - * resolving the password on the spot. For one thing this can be - * used in the Modeler and no password may be available. - */ - @Deprecated - private static String passwordFromInputStream(InputStream inputStream) { - String password = null; - - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) { - - password = bufferedReader.readLine(); - } catch (IOException exception) { - logger.warn(exception.getMessage(), exception); - } finally { - - try { - inputStream.close(); - } catch (IOException exception) { - } - } - - return password; - } - - @Inject - protected DataMapLoader dataMapLoader; - - @Inject - protected ConfigurationNameMapper nameMapper; - - @Inject - protected AdhocObjectFactory objectFactory; - - @Override - public ConfigurationTree<DataChannelDescriptor> load(Resource configurationResource) throws ConfigurationException { - - if (configurationResource == null) { - throw new NullPointerException("Null configurationResource"); - } - - URL configurationURL = configurationResource.getURL(); - - logger.info("Loading XML configuration resource from " + configurationURL); - - DataChannelDescriptor descriptor = new DataChannelDescriptor(); - descriptor.setConfigurationSource(configurationResource); - descriptor.setName(nameMapper.configurationNodeName(DataChannelDescriptor.class, configurationResource)); - - DataChannelHandler rootHandler; - - InputStream in = null; - - try { - in = configurationURL.openStream(); - XMLReader parser = Util.createXmlReader(); - - rootHandler = new DataChannelHandler(descriptor, parser); - parser.setContentHandler(rootHandler); - parser.setErrorHandler(rootHandler); - parser.parse(new InputSource(in)); - } catch (Exception e) { - throw new ConfigurationException("Error loading configuration from %s", e, configurationURL); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (IOException ioex) { - logger.info("failure closing input stream for " + configurationURL + ", ignoring", ioex); - } - } - - // TODO: andrus 03/10/2010 - actually provide load failures here... - return new ConfigurationTree<DataChannelDescriptor>(descriptor, null); - } - - final class DataChannelHandler extends SAXNestedTagHandler { - - private DataChannelDescriptor descriptor; - - DataChannelHandler(DataChannelDescriptor dataChannelDescriptor, XMLReader parser) { - super(parser, null); - this.descriptor = dataChannelDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals(DOMAIN_TAG)) { - return new DataChannelChildrenHandler(parser, this); - } - - logger.info(unexpectedTagMessage(localName, DOMAIN_TAG)); - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - final class DataChannelChildrenHandler extends SAXNestedTagHandler { - - private DataChannelDescriptor descriptor; - - DataChannelChildrenHandler(XMLReader parser, DataChannelHandler parentHandler) { - super(parser, parentHandler); - this.descriptor = parentHandler.descriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals(PROPERTY_TAG)) { - - String key = attributes.getValue("", "name"); - String value = attributes.getValue("", "value"); - if (key != null && value != null) { - descriptor.getProperties().put(key, value); - } - } else if (localName.equals(MAP_TAG)) { - - String dataMapName = attributes.getValue("", "name"); - Resource baseResource = descriptor.getConfigurationSource(); - - String dataMapLocation = nameMapper.configurationLocation(DataMap.class, dataMapName); - - Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation); - - logger.info("Loading XML DataMap resource from " + dataMapResource.getURL()); - - DataMap dataMap = dataMapLoader.load(dataMapResource); - dataMap.setName(dataMapName); - dataMap.setLocation(dataMapLocation); - dataMap.setConfigurationSource(dataMapResource); - dataMap.setDataChannelDescriptor(descriptor); - - descriptor.getDataMaps().add(dataMap); - } else if (localName.equals(NODE_TAG)) { - - String nodeName = attributes.getValue("", "name"); - if (nodeName == null) { - throw new ConfigurationException("Error: <node> without 'name'."); - } - - DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor(); - nodeDescriptor.setConfigurationSource(descriptor.getConfigurationSource()); - descriptor.getNodeDescriptors().add(nodeDescriptor); - - nodeDescriptor.setName(nodeName); - nodeDescriptor.setAdapterType(attributes.getValue("", "adapter")); - - String parameters = attributes.getValue("", "parameters"); - nodeDescriptor.setParameters(parameters); - - String dataSourceFactory = attributes.getValue("", "factory"); - nodeDescriptor.setDataSourceFactoryType(dataSourceFactory); - nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("", "schema-update-strategy")); - nodeDescriptor.setDataChannelDescriptor(descriptor); - - return new DataNodeChildrenHandler(parser, this, nodeDescriptor); - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - final class DataNodeChildrenHandler extends SAXNestedTagHandler { - - private DataNodeDescriptor nodeDescriptor; - - DataNodeChildrenHandler(XMLReader parser, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) { - super(parser, parentHandler); - this.nodeDescriptor = nodeDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals(MAP_REF_TAG)) { - - String mapName = attributes.getValue("", "name"); - nodeDescriptor.getDataMapNames().add(mapName); - } else if (localName.equals(DATA_SOURCE_TAG)) { - - DataSourceInfo dataSourceDescriptor = new DataSourceInfo(); - nodeDescriptor.setDataSourceDescriptor(dataSourceDescriptor); - return new DataSourceChildrenHandler(parser, this, dataSourceDescriptor); - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - class DataSourceChildrenHandler extends SAXNestedTagHandler { - - private DataSourceInfo dataSourceDescriptor; - - DataSourceChildrenHandler(XMLReader parser, DataNodeChildrenHandler parentHandler, - DataSourceInfo dataSourceDescriptor) { - super(parser, parentHandler); - this.dataSourceDescriptor = dataSourceDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals("driver")) { - String className = attributes.getValue("", "value"); - dataSourceDescriptor.setJdbcDriver(className); - } else if (localName.equals("login")) { - - logger.info("loading user name and password."); - - String encoderClass = attributes.getValue("encoderClass"); - - String encoderKey = attributes.getValue("encoderKey"); - if (encoderKey == null) { - encoderKey = attributes.getValue("encoderSalt"); - } - - String password = attributes.getValue("password"); - String passwordLocation = attributes.getValue("passwordLocation"); - String passwordSource = attributes.getValue("passwordSource"); - if (passwordSource == null) { - passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL; - } - - String username = attributes.getValue("userName"); - - dataSourceDescriptor.setPasswordEncoderClass(encoderClass); - dataSourceDescriptor.setPasswordEncoderKey(encoderKey); - dataSourceDescriptor.setPasswordLocation(passwordLocation); - dataSourceDescriptor.setPasswordSource(passwordSource); - dataSourceDescriptor.setUserName(username); - - // Replace {} in passwordSource with encoderSalt -- useful for - // EXECUTABLE - // & URL options - if (encoderKey != null) { - passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey); - } - - String encoderType = dataSourceDescriptor.getPasswordEncoderClass(); - PasswordEncoding passwordEncoder = null; - if (encoderType != null) { - passwordEncoder = objectFactory.newInstance(PasswordEncoding.class, encoderType); - } - - if (passwordLocation != null) { - if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) { - - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - URL url = classLoader.getResource(username); - if (url != null) { - password = passwordFromURL(url); - } else { - logger.error("Could not find resource in CLASSPATH: " + passwordSource); - } - } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) { - try { - password = passwordFromURL(new URL(passwordSource)); - } catch (MalformedURLException exception) { - logger.warn(exception.getMessage(), exception); - } - } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) { - if (passwordSource != null) { - try { - Process process = Runtime.getRuntime().exec(passwordSource); - password = passwordFromInputStream(process.getInputStream()); - process.waitFor(); - } catch (IOException exception) { - logger.warn(exception.getMessage(), exception); - } catch (InterruptedException exception) { - logger.warn(exception.getMessage(), exception); - } - } - } - } - - if (password != null && passwordEncoder != null) { - dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey)); - } - } else if (localName.equals("url")) { - dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value")); - } else if (localName.equals("connectionPool")) { - String min = attributes.getValue("min"); - if (min != null) { - try { - dataSourceDescriptor.setMinConnections(Integer.parseInt(min)); - } catch (NumberFormatException nfex) { - logger.info("Non-numeric 'min' attribute", nfex); - throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min); - } - } - - String max = attributes.getValue("max"); - if (max != null) { - try { - dataSourceDescriptor.setMaxConnections(Integer.parseInt(max)); - } catch (NumberFormatException nfex) { - logger.info("Non-numeric 'max' attribute", nfex); - throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max); - } - } - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java deleted file mode 100644 index d5cce91..0000000 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java +++ /dev/null @@ -1,57 +0,0 @@ -/***************************************************************** - * 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. - ****************************************************************/ -package org.apache.cayenne.configuration; - -import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.map.MapLoader; -import org.apache.cayenne.resource.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.InputSource; - -import java.io.InputStream; -import java.net.URL; - -/** - * @since 3.1 - */ -public class XMLDataMapLoader implements DataMapLoader { - - private static Logger logger = LoggerFactory.getLogger(XMLDataMapLoader.class); - - public DataMap load(Resource configurationResource) throws CayenneRuntimeException { - - // TODO: andrus 11.27.2009 - deprecate MapLoader and implement a loader - // here. MapLoader is in the wrong place, exposes ContentHandler methods and - // implements if/else contextless matching of tags... should use something like - // SAXNestedTagHandler instead. - MapLoader mapLoader = new MapLoader(); - URL url = configurationResource.getURL(); - - try (InputStream in = url.openStream()) { - return mapLoader.loadDataMap(new InputSource(in)); - } catch (Exception e) { - throw new CayenneRuntimeException( - "Error loading configuration from %s", - e, - url); - } - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java index 962bba9..c86371d 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java @@ -71,8 +71,12 @@ import org.apache.cayenne.configuration.DefaultRuntimeProperties; import org.apache.cayenne.configuration.ObjectContextFactory; import org.apache.cayenne.configuration.ObjectStoreFactory; import org.apache.cayenne.configuration.RuntimeProperties; -import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader; -import org.apache.cayenne.configuration.XMLDataMapLoader; +import org.apache.cayenne.configuration.xml.DataChannelMetaData; +import org.apache.cayenne.configuration.xml.DefaultHandlerFactory; +import org.apache.cayenne.configuration.xml.HandlerFactory; +import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData; +import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader; +import org.apache.cayenne.configuration.xml.XMLDataMapLoader; import org.apache.cayenne.dba.db2.DB2Sniffer; import org.apache.cayenne.dba.derby.DerbySniffer; import org.apache.cayenne.dba.firebird.FirebirdSniffer; @@ -403,5 +407,8 @@ public class ServerModule implements Module { binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class); binder.bind(SQLTemplateProcessor.class).to(VelocitySQLTemplateProcessor.class); + + binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class); + binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java new file mode 100644 index 0000000..9dc65af --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java @@ -0,0 +1,133 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import org.apache.cayenne.ConfigurationException; +import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.resource.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; + +/** + * @since 4.1 + */ +final class DataChannelChildrenHandler extends SAXNestedTagHandler { + + private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class); + + static final String OLD_MAP_TAG = "map"; + static final String NODE_TAG = "node"; + static final String PROPERTY_TAG = "property"; + static final String DATA_MAP_TAG = "data-map"; + + + private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader; + private DataChannelDescriptor descriptor; + + private DataNodeDescriptor nodeDescriptor; + + DataChannelChildrenHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, DataChannelHandler parentHandler) { + super(parentHandler); + this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader; + this.descriptor = parentHandler.descriptor; + } + + @Override + protected boolean processElement(String namespaceURI, String localName, Attributes attributes) { + switch (localName) { + case PROPERTY_TAG: + addProperty(attributes); + return true; + + case OLD_MAP_TAG: + addMap(attributes); + return true; + + case NODE_TAG: + addNode(attributes); + return true; + } + + return false; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, + String name, Attributes attributes) { + if (NODE_TAG.equals(localName)) { + nodeDescriptor = new DataNodeDescriptor(); + return new DataNodeChildrenHandler(xmlDataChannelDescriptorLoader, this, nodeDescriptor); + } + + if (DATA_MAP_TAG.equals(localName)) { + return new DataMapHandler(loaderContext); + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + + private void addProperty(Attributes attributes) { + String key = attributes.getValue("name"); + String value = attributes.getValue("value"); + if (key != null && value != null) { + descriptor.getProperties().put(key, value); + } + } + + private void addMap(Attributes attributes) { + String dataMapName = attributes.getValue("name"); + Resource baseResource = descriptor.getConfigurationSource(); + + String dataMapLocation = xmlDataChannelDescriptorLoader.nameMapper.configurationLocation(DataMap.class, dataMapName); + + Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation); + + logger.info("Loading XML DataMap resource from " + dataMapResource.getURL()); + + DataMap dataMap = xmlDataChannelDescriptorLoader.dataMapLoader.load(dataMapResource); + dataMap.setName(dataMapName); + dataMap.setLocation(dataMapLocation); + dataMap.setConfigurationSource(dataMapResource); + dataMap.setDataChannelDescriptor(descriptor); + + descriptor.getDataMaps().add(dataMap); + } + + private void addNode(Attributes attributes) { + String nodeName = attributes.getValue("name"); + if (nodeName == null) { + throw new ConfigurationException("Error: <node> without 'name'."); + } + + nodeDescriptor.setConfigurationSource(descriptor.getConfigurationSource()); + nodeDescriptor.setName(nodeName); + nodeDescriptor.setAdapterType(attributes.getValue("adapter")); + nodeDescriptor.setParameters(attributes.getValue("parameters")); + nodeDescriptor.setDataSourceFactoryType(attributes.getValue("factory")); + nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("schema-update-strategy")); + nodeDescriptor.setDataChannelDescriptor(descriptor); + + descriptor.getNodeDescriptors().add(nodeDescriptor); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java new file mode 100644 index 0000000..e5e4c71 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java @@ -0,0 +1,78 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.util.LocalizedStringsHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * @since 4.1 + */ +final class DataChannelHandler extends SAXNestedTagHandler { + + private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class); + + static final String DOMAIN_TAG = "domain"; + + private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader; + DataChannelDescriptor descriptor; + + DataChannelHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, DataChannelDescriptor dataChannelDescriptor, LoaderContext loaderContext) { + super(loaderContext); + this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader; + this.descriptor = dataChannelDescriptor; + } + + @Override + protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException { + switch (localName) { + case DOMAIN_TAG: + validateVersion(attributes); + return true; + } + return super.processElement(namespaceURI, localName, attributes); + } + + protected void validateVersion(Attributes attributes) { + String version = attributes.getValue("project-version"); + if(!XMLDataChannelDescriptorLoader.CURRENT_PROJECT_VERSION.equals(version)) { + throw new CayenneRuntimeException("Unsupported project version: %s, please upgrade project using Modeler v%s", + version, LocalizedStringsHandler.getString("cayenne.version")); + } + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, + String name, Attributes attributes) { + + if (localName.equals(DOMAIN_TAG)) { + return new DataChannelChildrenHandler(xmlDataChannelDescriptorLoader, this); + } + + logger.info(unexpectedTagMessage(localName, DOMAIN_TAG)); + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java new file mode 100644 index 0000000..3e0cd20 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java @@ -0,0 +1,64 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import org.apache.cayenne.configuration.ConfigurationNode; + +/** + * <p> + * Storage for all kind of meta data that is not required for runtime. + * </p> + * <p> + * Currently used by Modeler and cli tools (e.g. Maven, Ant and Gradle) to store project extra data. + * </p> + * + * <p> + * Usage: <pre> + * // attach custom information to data map + * metaData.add(dataMap, myObject); + * + * // read data + * MyObject obj = metaData.get(dataMap, MyObject.class); + * </pre> + * </p> + * + * @since 4.1 + */ +public interface DataChannelMetaData { + + /** + * Store data for object. + * + * @param key object for which we want to store data + * @param value data to store + */ + void add(ConfigurationNode key, Object value); + + /** + * + * Get meta data for object + * + * @param key object for wich we want meta data + * @param type meta data type class + * @param <T> meta data type + * @return value or {@code null} if no data available + */ + <T> T get(ConfigurationNode key, Class<T> type); +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java new file mode 100644 index 0000000..ea508f5 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java @@ -0,0 +1,142 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import java.util.Map; +import java.util.TreeMap; + +import org.apache.cayenne.map.DataMap; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * @since 4.1 + */ +public class DataMapHandler extends NamespaceAwareNestedTagHandler { + + /* This constants must be in sync with dataMap.xsd schema */ + private static final String DATA_MAP_TAG = "data-map"; + private static final String PROPERTY_TAG = "property"; + private static final String DB_ENTITY_TAG = "db-entity"; + private static final String OBJ_ENTITY_TAG = "obj-entity"; + private static final String DB_RELATIONSHIP_TAG = "db-relationship"; + private static final String OBJ_RELATIONSHIP_TAG = "obj-relationship"; + private static final String EMBEDDABLE_TAG = "embeddable"; + private static final String PROCEDURE_TAG = "procedure"; + private static final String QUERY_TAG = "query"; + + public static final String TRUE = "true"; + + private DataMap dataMap; + + private Map<String, Object> mapProperties; + + public DataMapHandler(NamespaceAwareNestedTagHandler parentHandler) { + super(parentHandler); + } + + public DataMapHandler(LoaderContext loaderContext) { + super(loaderContext); + setTargetNamespace(DataMap.SCHEMA_XSD); + } + + @Override + protected boolean processElement(String namespaceURI, String localName, + Attributes attributes) throws SAXException { + switch (localName) { + case PROPERTY_TAG: + addProperty(attributes); + return true; + + case DATA_MAP_TAG: + this.dataMap = new DataMap(); + return true; + } + + return false; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, + String qName, Attributes attributes) { + + if(namespaceURI.equals(targetNamespace)) { + switch (localName) { + case DB_ENTITY_TAG: + return new DbEntityHandler(this, dataMap); + + case OBJ_ENTITY_TAG: + return new ObjEntityHandler(this, dataMap); + + case DB_RELATIONSHIP_TAG: + return new DbRelationshipHandler(this, dataMap); + + case OBJ_RELATIONSHIP_TAG: + return new ObjRelationshipHandler(this, dataMap); + + case PROCEDURE_TAG: + return new ProcedureHandler(this, dataMap); + + case QUERY_TAG: + return new QueryDescriptorHandler(this, dataMap); + + case EMBEDDABLE_TAG: + return new EmbeddableHandler(this, dataMap); + } + } + + return super.createChildTagHandler(namespaceURI, localName, qName, attributes); + } + + @Override + protected void beforeScopeEnd() { + dataMap.initWithProperties(mapProperties); + loaderContext.dataMapLoaded(dataMap); + } + + private void addProperty(Attributes attributes) throws SAXException { + String name = attributes.getValue("name"); + if (null == name) { + throw new SAXException("MapLoader::processStartDataMapProperty(), no property name."); + } + + String value = attributes.getValue("value"); + if (null == value) { + throw new SAXException("MapLoader::processStartDataMapProperty(), no property value."); + } + + // special meaning for <property name="name" .../> + if("name".equals(name)) { + dataMap.setName(value); + return; + } + + if (mapProperties == null) { + mapProperties = new TreeMap<>(); + } + + mapProperties.put(name, value); + } + + public DataMap getDataMap() { + return dataMap; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java new file mode 100644 index 0000000..c9f4ccd --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java @@ -0,0 +1,31 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import org.apache.cayenne.map.DataMap; + +/** + * @since 4.1 + */ +public interface DataMapLoaderListener { + + void onDataMapLoaded(DataMap dataMap); + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java new file mode 100644 index 0000000..b98bd73 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java @@ -0,0 +1,71 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.conn.DataSourceInfo; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; + +/** + * @since 4.1 + */ +final class DataNodeChildrenHandler extends SAXNestedTagHandler { + + static final String DATA_SOURCE_TAG = "data-source"; + static final String MAP_REF_TAG = "map-ref"; + + private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader; + private DataNodeDescriptor nodeDescriptor; + + private DataSourceInfo dataSourceDescriptor; + + DataNodeChildrenHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) { + super(parentHandler); + this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader; + this.nodeDescriptor = nodeDescriptor; + } + + @Override + protected boolean processElement(String namespaceURI, String localName, Attributes attributes) { + switch (localName) { + case MAP_REF_TAG: + nodeDescriptor.getDataMapNames().add(attributes.getValue("name")); + return true; + + case DATA_SOURCE_TAG: + nodeDescriptor.setDataSourceDescriptor(dataSourceDescriptor); + return true; + } + + return false; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, + String name, Attributes attributes) { + if (DATA_SOURCE_TAG.equals(localName)) { + dataSourceDescriptor = new DataSourceInfo(); + return new DataSourceChildrenHandler(xmlDataChannelDescriptorLoader, this, dataSourceDescriptor); + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java new file mode 100644 index 0000000..b860b1f --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java @@ -0,0 +1,175 @@ +/***************************************************************** + * 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. + ****************************************************************/ + +package org.apache.cayenne.configuration.xml; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.cayenne.ConfigurationException; +import org.apache.cayenne.configuration.PasswordEncoding; +import org.apache.cayenne.conn.DataSourceInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; + +/** + * @since 4.1 + */ +class DataSourceChildrenHandler extends SAXNestedTagHandler { + + private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class); + + static final String DRIVER_TAG = "driver"; + static final String LOGIN_TAG = "login"; + static final String URL_TAG = "url"; + static final String CONNECTION_POOL_TAG = "connectionPool"; + + + private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader; + private DataSourceInfo dataSourceDescriptor; + + DataSourceChildrenHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, + DataNodeChildrenHandler parentHandler, + DataSourceInfo dataSourceDescriptor) { + super(parentHandler); + this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader; + this.dataSourceDescriptor = dataSourceDescriptor; + } + + @Override + protected boolean processElement(String namespaceURI, String localName, Attributes attributes) { + switch (localName) { + case DRIVER_TAG: + dataSourceDescriptor.setJdbcDriver(attributes.getValue("value")); + return true; + + case LOGIN_TAG: + configureCredentials(attributes); + return true; + + case URL_TAG: + dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value")); + return true; + + case CONNECTION_POOL_TAG: + configureConnectionPool(attributes); + return true; + } + + return false; + } + + void configureCredentials(Attributes attributes) { + logger.info("loading user name and password."); + + String encoderClass = attributes.getValue("encoderClass"); + + String encoderKey = attributes.getValue("encoderKey"); + if (encoderKey == null) { + encoderKey = attributes.getValue("encoderSalt"); + } + + String password = attributes.getValue("password"); + String passwordLocation = attributes.getValue("passwordLocation"); + String passwordSource = attributes.getValue("passwordSource"); + if (passwordSource == null) { + passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL; + } + + String username = attributes.getValue("userName"); + + dataSourceDescriptor.setPasswordEncoderClass(encoderClass); + dataSourceDescriptor.setPasswordEncoderKey(encoderKey); + dataSourceDescriptor.setPasswordLocation(passwordLocation); + dataSourceDescriptor.setPasswordSource(passwordSource); + dataSourceDescriptor.setUserName(username); + + // Replace {} in passwordSource with encoderSalt -- useful for EXECUTABLE & URL options + if (encoderKey != null) { + passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey); + } + + String encoderType = dataSourceDescriptor.getPasswordEncoderClass(); + PasswordEncoding passwordEncoder = null; + if (encoderType != null) { + passwordEncoder = xmlDataChannelDescriptorLoader.objectFactory.newInstance(PasswordEncoding.class, encoderType); + } + + if (passwordLocation != null) { + switch (passwordLocation) { + case DataSourceInfo.PASSWORD_LOCATION_CLASSPATH: + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + URL url = classLoader.getResource(username); + if (url != null) { + password = XMLDataChannelDescriptorLoader.passwordFromURL(url); + } else { + logger.error("Could not find resource in CLASSPATH: " + passwordSource); + } + break; + case DataSourceInfo.PASSWORD_LOCATION_URL: + try { + password = XMLDataChannelDescriptorLoader.passwordFromURL(new URL(passwordSource)); + } catch (MalformedURLException exception) { + logger.warn(exception.getMessage(), exception); + } + break; + case DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE: + if (passwordSource != null) { + try { + Process process = Runtime.getRuntime().exec(passwordSource); + password = XMLDataChannelDescriptorLoader.passwordFromInputStream(process.getInputStream()); + process.waitFor(); + } catch (IOException | InterruptedException exception) { + logger.warn(exception.getMessage(), exception); + } + } + break; + } + } + + if (password != null && passwordEncoder != null) { + dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey)); + } + } + + void configureConnectionPool(Attributes attributes) { + String min = attributes.getValue("min"); + if (min != null) { + try { + dataSourceDescriptor.setMinConnections(Integer.parseInt(min)); + } catch (NumberFormatException nfex) { + logger.info("Non-numeric 'min' attribute", nfex); + throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min); + } + } + + String max = attributes.getValue("max"); + if (max != null) { + try { + dataSourceDescriptor.setMaxConnections(Integer.parseInt(max)); + } catch (NumberFormatException nfex) { + logger.info("Non-numeric 'max' attribute", nfex); + throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max); + } + } + } +}
