diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index f3233e5aa1..cea8dd0854 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -15,6 +15,7 @@ Changes/New Features: CAY-2446 Run Disjoint By Id queries outside of synchronized block CAY-2447 Crypto support for LocalDateTime +CAY-2469 Allow maxQueueWaitTime and validationQuery to be set in XML project CAY-2471 Support multiple XML project versions Bug Fixes: @@ -549,4 +550,4 @@ CAY-1804 Serialisation of long[] type was not working correctly. CAY-1806 Error importing eomodel CAY-1817 NPE during Validate Project CAY-1827 EhCache region corresponding to a cache group loses its settings after 'removeGroup' -CAY-1832 Exception when modifying objects in postLoad callback \ No newline at end of file +CAY-1832 Exception when modifying objects in postLoad callback diff --git a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java index 5a93695794..dc74496d42 100644 --- a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java +++ b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java @@ -28,6 +28,7 @@ import org.apache.cayenne.project.ProjectModule; import org.apache.cayenne.project.upgrade.UpgradeService; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10; +import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V11; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V7; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V8; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V9; @@ -49,6 +50,7 @@ public void configure(Binder binder) { .add(UpgradeHandler_V7.class) .add(UpgradeHandler_V8.class) .add(UpgradeHandler_V9.class) - .add(UpgradeHandler_V10.class); + .add(UpgradeHandler_V10.class) + .add(UpgradeHandler_V11.class); } } diff --git a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java index 88f80d3a4d..277b6cf51c 100644 --- a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java +++ b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java @@ -34,6 +34,7 @@ import org.apache.cayenne.project.upgrade.UpgradeService; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10; +import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V11; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V7; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V8; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V9; @@ -59,7 +60,8 @@ public void configure(Binder binder) { .add(UpgradeHandler_V7.class) .add(UpgradeHandler_V8.class) .add(UpgradeHandler_V9.class) - .add(UpgradeHandler_V10.class); + .add(UpgradeHandler_V10.class) + .add(UpgradeHandler_V11.class); binder.bind(ProjectSaver.class).toInstance(mock(ProjectSaver.class)); binder.bind(DataChannelDescriptorLoader.class).toInstance(mock(DataChannelDescriptorLoader.class)); diff --git a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java index db86dc81a4..e793f5724c 100644 --- a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java +++ b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java @@ -52,7 +52,7 @@ public void testUpgradeFullProjectDom() throws Exception { Document domainDocument = documentProvider.getDocument(resourceUrl); assertNotNull(domainDocument); - assertEquals("10", domainDocument.getDocumentElement().getAttribute("project-version")); + assertEquals("11", domainDocument.getDocumentElement().getAttribute("project-version")); URL dataMapUrl = getClass().getResource("test-map-v6.map.xml"); Document dataMapDocument = documentProvider.getDocument(dataMapUrl); @@ -87,4 +87,4 @@ public void testUpgradeStandAloneDataMapDom() throws Exception { private Injector getInjector() { return DIBootstrap.createInjector(new CompatibilityTestModule()); } -} \ No newline at end of file +} diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java index 614d4ed9fa..359df56908 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java @@ -26,6 +26,7 @@ import org.apache.cayenne.project.upgrade.UpgradeService; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10; +import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V11; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V7; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V8; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V9; @@ -66,7 +67,8 @@ public void configure(Binder binder) { .add(UpgradeHandler_V7.class) .add(UpgradeHandler_V8.class) .add(UpgradeHandler_V9.class) - .add(UpgradeHandler_V10.class); + .add(UpgradeHandler_V10.class) + .add(UpgradeHandler_V11.class); contributeExtensions(binder); } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectVersion.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectVersion.java new file mode 100644 index 0000000000..f7942a6d4e --- /dev/null +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectVersion.java @@ -0,0 +1,34 @@ +package org.apache.cayenne.project; + +import org.apache.cayenne.CayenneRuntimeException; + +/** + * Encapsulates compatible schema versions. + */ +public enum ProjectVersion { + + VERSION_9(null,"9"), + VERSION_10("10","10"), + VERSION_11("11","10"); + + public final String domainSchemaVersion; + public final String modelMapSchemaVersion; + + ProjectVersion(String domainSchemaVersion, String modelMapSchemaVersion) { + this.domainSchemaVersion = domainSchemaVersion; + this.modelMapSchemaVersion = modelMapSchemaVersion; + } + + public ProjectVersion getProjectVersion(String version) { + switch (version) { + case "9": + return VERSION_9; + case "10": + return VERSION_10; + case "11": + return VERSION_11; + default: + throw new CayenneRuntimeException("Invalid project version: " + version); + } + } +} diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java index d00b7b5a10..4c134d54e1 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java @@ -87,8 +87,10 @@ public class DefaultUpgradeService implements UpgradeService { private static final Logger logger = LoggerFactory.getLogger(DefaultUpgradeService.class); - public static final String UNKNOWN_VERSION = "0"; - public static final String MIN_SUPPORTED_VERSION = "6"; + private static final String UNKNOWN_VERSION = "0"; + private static final String MIN_INTERMEDIATE_SUPPORTED_VERSION = "6"; + private static final String MIN_SUPPORTED_VERSION = "10"; + private static final String MAX_SUPPORTED_VERSION = "11"; TreeMap handlers = new TreeMap<>(VersionComparator.INSTANCE); @@ -110,28 +112,26 @@ public UpgradeMetaData getUpgradeType(Resource resource) { String version = loadProjectVersion(resource); metaData.setProjectVersion(version); - metaData.setSupportedVersion(String.valueOf(Project.VERSION)); - int c1 = VersionComparator.INSTANCE.compare(version, MIN_SUPPORTED_VERSION); + int c1 = VersionComparator.INSTANCE.compare(version, MIN_INTERMEDIATE_SUPPORTED_VERSION); if (c1 < 0) { - metaData.setIntermediateUpgradeVersion(MIN_SUPPORTED_VERSION); metaData.setUpgradeType(UpgradeType.INTERMEDIATE_UPGRADE_NEEDED); return metaData; } - int c2 = VersionComparator.INSTANCE.compare(String.valueOf(Project.VERSION), version); - if (c2 < 0) { + if (VersionComparator.INSTANCE.compare(version, MIN_SUPPORTED_VERSION) < 0) { + metaData.setUpgradeType(UpgradeType.UPGRADE_NEEDED); + } else if (VersionComparator.INSTANCE.compare(version, MAX_SUPPORTED_VERSION) > 0) { metaData.setUpgradeType(UpgradeType.DOWNGRADE_NEEDED); - } else if (c2 == 0) { - metaData.setUpgradeType(UpgradeType.UPGRADE_NOT_NEEDED); } else { - metaData.setUpgradeType(UpgradeType.UPGRADE_NEEDED); + metaData.setUpgradeType(UpgradeType.UPGRADE_NOT_NEEDED); } + return metaData; } protected List getHandlersForVersion(String version) { - boolean found = MIN_SUPPORTED_VERSION.equals(version); + boolean found = MIN_INTERMEDIATE_SUPPORTED_VERSION.equals(version); List handlerList = new ArrayList<>(); for(Map.Entry entry : handlers.entrySet()) { diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java index caf7e5bb4e..c8f56acadf 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java @@ -28,8 +28,6 @@ public class UpgradeMetaData { protected UpgradeType upgradeType; protected String projectVersion; - protected String supportedVersion; - protected String intermediateUpgradeVersion; public UpgradeType getUpgradeType() { return upgradeType; @@ -47,20 +45,4 @@ public void setProjectVersion(String projectVersion) { this.projectVersion = projectVersion; } - public String getSupportedVersion() { - return supportedVersion; - } - - public void setSupportedVersion(String supportedVersion) { - this.supportedVersion = supportedVersion; - } - - public String getIntermediateUpgradeVersion() { - return intermediateUpgradeVersion; - } - - public void setIntermediateUpgradeVersion(String intermediateUpgradeVersion) { - this.intermediateUpgradeVersion = intermediateUpgradeVersion; - } - } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java new file mode 100644 index 0000000000..47aac879ef --- /dev/null +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java @@ -0,0 +1,62 @@ +/***************************************************************** + * 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.handlers; + +import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.w3c.dom.Element; + +/** + * Upgrade handler for the project version "10" introduced by 4.1.M1 release. + * Changes highlight: + * - strict schema for domain (e.g. main project document) + * - new schema for data map allowing usage of additional elements (e.g. XML extensions) + * + * @since 4.1 + */ +public class UpgradeHandler_V11 implements UpgradeHandler { + + @Override + public String getVersion() { + return "11"; + } + + @Override + public void processProjectDom(UpgradeUnit upgradeUnit) { + Element domain = upgradeUnit.getDocument().getDocumentElement(); + // introduce xml namespace and schema for domain + domain.setAttribute("xmlns","http://cayenne.apache.org/schema/11/domain"); + domain.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); + domain.setAttribute("xsi:schemaLocation", "http://cayenne.apache.org/schema/11/domain " + + "https://cayenne.apache.org/schema/11/domain.xsd"); + // update version + domain.setAttribute("project-version", getVersion()); + } + + @Override + public void processDataMapDom(UpgradeUnit upgradeUnit) { + // noop + } + + @Override + public void processModel(DataChannelDescriptor dataChannelDescriptor) { + // noop + } +} diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java index 7391d2aaa0..c4cc071bad 100644 --- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java +++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java @@ -64,10 +64,16 @@ public void getUpgradeType() throws Exception { metaData = upgradeService.getUpgradeType(getResourceForVersion("6")); assertEquals(UpgradeType.UPGRADE_NEEDED, metaData.getUpgradeType()); + metaData = upgradeService.getUpgradeType(getResourceForVersion("9")); + assertEquals(UpgradeType.UPGRADE_NEEDED, metaData.getUpgradeType()); + metaData = upgradeService.getUpgradeType(getResourceForVersion("10")); assertEquals(UpgradeType.UPGRADE_NOT_NEEDED, metaData.getUpgradeType()); metaData = upgradeService.getUpgradeType(getResourceForVersion("11")); + assertEquals(UpgradeType.UPGRADE_NOT_NEEDED, metaData.getUpgradeType()); + + metaData = upgradeService.getUpgradeType(getResourceForVersion("12")); assertEquals(UpgradeType.DOWNGRADE_NEEDED, metaData.getUpgradeType()); } @@ -160,4 +166,4 @@ private Resource getResourceForVersion(String version) { return new URLResource(getClass().getResource("handlers/cayenne-project-v"+version+".xml")); } -} \ No newline at end of file +} diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v12.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v12.xml new file mode 100644 index 0000000000..110213558a --- /dev/null +++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v12.xml @@ -0,0 +1,3 @@ + + + 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 310fb6941b..440cecb9d5 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 @@ -31,6 +31,8 @@ import java.util.List; import java.util.Map; +import static org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader.DEFAULT_PROJECT_VERSION; + /** * A descriptor of a DataChannel normally loaded from XML configuration. * @@ -43,8 +45,8 @@ public class DataChannelDescriptor implements ConfigurationNode, Serializable, X /** * 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"; - public static final String SCHEMA_XSD_LOCATION = "https://cayenne.apache.org/schema/10/domain.xsd"; + private String schemaXsd; + private String schemaXsdLocation; protected String name; protected Map properties; @@ -57,15 +59,16 @@ public DataChannelDescriptor() { properties = new HashMap<>(); dataMaps = new ArrayList<>(5); nodeDescriptors = new ArrayList<>(3); + setProjectVersion(DEFAULT_PROJECT_VERSION); } @Override public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) { encoder.start("domain") - .attribute("xmlns", SCHEMA_XSD) + .attribute("xmlns", schemaXsd) .attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance", true) - .attribute("xsi:schemaLocation", SCHEMA_XSD + " " + SCHEMA_XSD_LOCATION, true) + .attribute("xsi:schemaLocation", schemaXsd + " " + schemaXsdLocation, true) .projectVersion(); if (!properties.isEmpty()) { @@ -158,4 +161,13 @@ public String getDefaultNodeName() { public void setDefaultNodeName(String defaultDataNodeName) { this.defaultNodeName = defaultDataNodeName; } + + public String getSchemaXsd() { + return schemaXsd; + } + + public void setProjectVersion(String projectVersion) { + this.schemaXsd = "http://cayenne.apache.org/schema/" + projectVersion + "/domain"; + this.schemaXsdLocation = "https://cayenne.apache.org/schema/" + projectVersion + "/domain.xsd"; + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java index e99d78d94a..815bbf861e 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java @@ -64,15 +64,14 @@ public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) throws Except throw new ConfigurationException(message); } - long maxQueueWaitTime = properties.getLong(Constants.JDBC_MAX_QUEUE_WAIT_TIME, - UnmanagedPoolingDataSource.MAX_QUEUE_WAIT_DEFAULT); - Driver driver = objectFactory.newInstance(Driver.class, descriptor.getJdbcDriver()); return DataSourceBuilder.url(descriptor.getDataSourceUrl()).driver(driver).userName(descriptor.getUserName()) .password(descriptor.getPassword()) .pool(descriptor.getMinConnections(), descriptor.getMaxConnections()) - .maxQueueWaitTime(maxQueueWaitTime).build(); + .maxQueueWaitTime(descriptor.getMaxQueueWaitTime()) + .validationQuery(descriptor.getValidationQuery()) + .build(); } } 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 index b55e604bab..0243c20dd9 100644 --- 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 @@ -41,13 +41,15 @@ final class DataChannelHandler extends VersionAwareHandler { super(loaderContext, DOMAIN_TAG); this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader; this.descriptor = dataChannelDescriptor; - setTargetNamespace(DataChannelDescriptor.SCHEMA_XSD); } @Override protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, Attributes attributes) { + descriptor.setProjectVersion(attributes.getValue("project-version")); + setTargetNamespace(descriptor.getSchemaXsd()); + if (localName.equals(DOMAIN_TAG)) { return new DataChannelChildrenHandler(xmlDataChannelDescriptorLoader, this); } 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 index ea508f5077..cab3b87c10 100644 --- 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 @@ -55,7 +55,6 @@ public DataMapHandler(NamespaceAwareNestedTagHandler parentHandler) { public DataMapHandler(LoaderContext loaderContext) { super(loaderContext); - setTargetNamespace(DataMap.SCHEMA_XSD); } @Override @@ -68,6 +67,8 @@ protected boolean processElement(String namespaceURI, String localName, case DATA_MAP_TAG: this.dataMap = new DataMap(); + dataMap.setProjectVersion(attributes.getValue("project-version")); + setTargetNamespace(dataMap.getSchemaXsd()); return true; } 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 index 8f4065056f..cea33ab84d 100644 --- 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 @@ -167,5 +167,20 @@ void configureConnectionPool(Attributes attributes) { throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max); } } + + String maxQueueWaitTime = attributes.getValue("maxQueueWaitTime"); + if (maxQueueWaitTime != null) { + try { + dataSourceDescriptor.setMaxQueueWaitTime(Integer.parseInt(maxQueueWaitTime)); + } catch (NumberFormatException nfex) { + logger.info("Non-numeric 'maxQueueWaitTime' attribute", nfex); + throw new ConfigurationException("Non-numeric 'maxQueueWaitTime' attribute '%s'", nfex, max); + } + } + + String validationQuery = attributes.getValue("validationQuery"); + if (validationQuery != null) { + dataSourceDescriptor.setValidationQuery(validationQuery); + } } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java index f70a6ef70b..e86aa5e52c 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java @@ -30,11 +30,12 @@ public class RootDataMapHandler extends VersionAwareHandler { public RootDataMapHandler(LoaderContext loaderContext) { super(loaderContext, "data-map"); - setTargetNamespace(DataMap.SCHEMA_XSD); } @Override protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String qName, Attributes attributes) { + setTargetNamespace(DataMap.getSchemaXsdForVersion(attributes.getValue("project-version"))); + if(targetNamespace.equals(namespaceURI) && "data-map".equals(localName)) { return new DataMapHandler(this); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java index 3b90432aad..e6355f20e0 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java @@ -27,9 +27,7 @@ import org.apache.cayenne.di.AdhocObjectFactory; import org.apache.cayenne.di.Inject; import org.apache.cayenne.di.Provider; -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.InputSource; @@ -52,8 +50,12 @@ public class XMLDataChannelDescriptorLoader implements DataChannelDescriptorLoad /** * Versions of project XML files that this loader can read. + * See DefaultUpgradeService.MIN/MAX_SUPPORTED_VERSION in cayenne-project. */ - static final String[] SUPPORTED_PROJECT_VERSIONS = {"10"}; + static final String[] SUPPORTED_PROJECT_VERSIONS = {"10", "11"}; + + public static final String DEFAULT_PROJECT_VERSION = "10"; + static { Arrays.sort(SUPPORTED_PROJECT_VERSIONS); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java index 165f37bb38..08c8571c35 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java @@ -25,6 +25,7 @@ import org.apache.cayenne.configuration.ConfigurationNodeVisitor; import org.apache.cayenne.configuration.PasswordEncoding; import org.apache.cayenne.configuration.PlainTextPasswordEncoder; +import org.apache.cayenne.datasource.UnmanagedPoolingDataSource; import org.apache.cayenne.di.DIRuntimeException; import org.apache.cayenne.util.Util; import org.apache.cayenne.util.XMLEncoder; @@ -53,6 +54,7 @@ public class DataSourceInfo implements Cloneable, Serializable, XMLSerializable protected String adapterClassName; protected int minConnections = 1; protected int maxConnections = 1; + protected int maxQueueWaitTime = UnmanagedPoolingDataSource.MAX_QUEUE_WAIT_DEFAULT; protected String passwordEncoderClass = PlainTextPasswordEncoder.class.getName(); protected String passwordEncoderKey = ""; protected String passwordLocation = PASSWORD_LOCATION_MODEL; @@ -60,6 +62,7 @@ public class DataSourceInfo implements Cloneable, Serializable, XMLSerializable protected String passwordSourceFilename = ""; protected final String passwordSourceModel = "Not Applicable"; protected String passwordSourceUrl = ""; + protected String validationQuery = null; @Override public boolean equals(Object obj) { @@ -106,6 +109,10 @@ public boolean equals(Object obj) { return false; } + if (this.maxQueueWaitTime != dsi.maxQueueWaitTime) { + return false; + } + if (!Util.nullSafeEquals(this.passwordEncoderClass, dsi.passwordEncoderClass)) { return false; } @@ -130,6 +137,10 @@ public boolean equals(Object obj) { return false; } + if (!Util.nullSafeEquals(this.validationQuery, dsi.validationQuery)) { + return false; + } + return true; } @@ -137,9 +148,9 @@ public boolean equals(Object obj) { public int hashCode() { return Objects.hash(userName, password, jdbcDriver, dataSourceUrl, adapterClassName, minConnections, - maxConnections, passwordEncoderClass, passwordEncoderKey, - passwordLocation, passwordSourceFilename, passwordSourceModel, - passwordSourceUrl); + maxConnections, maxQueueWaitTime, passwordEncoderClass, + passwordEncoderKey, passwordLocation, passwordSourceFilename, + passwordSourceModel, passwordSourceUrl, validationQuery); } /** @@ -155,6 +166,8 @@ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) { encoder.start("connectionPool") .attribute("min", minConnections) .attribute("max", String.valueOf(maxConnections)) + .attribute("maxQueueWaitTime", String.valueOf(maxQueueWaitTime)) + .attribute("validationQuery", validationQuery) .end(); encoder.start("login").attribute("userName", userName); @@ -219,6 +232,22 @@ public int getMaxConnections() { return maxConnections; } + public void setMaxQueueWaitTime(int maxQueueWaitTime) { + this.maxQueueWaitTime = maxQueueWaitTime; + } + + public int getMaxQueueWaitTime() { + return maxQueueWaitTime; + } + + public void setValidationQuery(String validationQuery) { + this.validationQuery = validationQuery; + } + + public String getValidationQuery() { + return validationQuery; + } + public void setUserName(String userName) { this.userName = userName; } @@ -403,9 +432,12 @@ public String toString() { .append("\n password: "); buffer.append("**********"); - buffer.append("\n driver: ").append(jdbcDriver).append("\n db adapter class: ").append(adapterClassName) - .append("\n url: ").append(dataSourceUrl).append("\n min. connections: ").append(minConnections) - .append("\n max. connections: ").append(maxConnections); + buffer.append("\n driver: ").append(jdbcDriver) + .append("\n db adapter class: ").append(adapterClassName) + .append("\n url: ").append(dataSourceUrl) + .append("\n min. connections: ").append(minConnections) + .append("\n max. connections: ").append(maxConnections) + .append("\n max. queue wait time: ").append(maxQueueWaitTime); if (!PlainTextPasswordEncoder.class.getName().equals(passwordEncoderClass)) { buffer.append("\n encoder class: ").append(passwordEncoderClass).append("\n encoder key: ") @@ -417,6 +449,8 @@ public String toString() { .append(getPasswordSource()); } + buffer.append("\n validation query: ").append(validationQuery); + buffer.append("\n]"); return buffer.toString(); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java index 73e68f7723..c03029e3cc 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java @@ -42,6 +42,7 @@ import java.util.TreeMap; import static java.util.Collections.emptyList; +import static org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader.DEFAULT_PROJECT_VERSION; /** * Stores a collection of related mapping objects that describe database and @@ -116,8 +117,8 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable * The namespace in which the data map XML file will be created. This is * also the URI to locate a copy of the schema document. */ - public static final String SCHEMA_XSD = "http://cayenne.apache.org/schema/10/modelMap"; - public static final String SCHEMA_XSD_LOCATION = "https://cayenne.apache.org/schema/10/modelMap.xsd"; + private String schemaXsd; + private String schemaXsdLocation; protected String name; protected String location; @@ -176,6 +177,7 @@ public DataMap(String mapName, Map properties) { results = new HashMap<>(); setName(mapName); initWithProperties(properties); + setProjectVersion(DEFAULT_PROJECT_VERSION); } /** @@ -301,9 +303,9 @@ public DataMap getClientDataMap(EntityResolver serverResolver) { */ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) { encoder.start("data-map") - .attribute("xmlns", SCHEMA_XSD) + .attribute("xmlns", schemaXsd) .attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance", true) - .attribute("xsi:schemaLocation", SCHEMA_XSD + " " + SCHEMA_XSD_LOCATION, true) + .attribute("xsi:schemaLocation", schemaXsd + " " + schemaXsdLocation, true) .projectVersion() // properties .property(DEFAULT_LOCK_TYPE_PROPERTY, defaultLockType) @@ -1269,4 +1271,17 @@ public Map getSubclassesForObjEntity(ObjEntity superEntity) { return subObjectEntities; } + + public String getSchemaXsd() { + return schemaXsd; + } + + public void setProjectVersion(String projectVersion) { + this.schemaXsd = getSchemaXsdForVersion(projectVersion); + this.schemaXsdLocation = "https://cayenne.apache.org/schema/" + projectVersion + "/modelMap.xsd"; + } + + public static String getSchemaXsdForVersion(String projectVersion) { + return "http://cayenne.apache.org/schema/" + projectVersion + "/modelMap"; + } } diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/11/domain.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/11/domain.xsd new file mode 100644 index 0000000000..53840ff570 --- /dev/null +++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/11/domain.xsd @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + A generic property used by other elements. + + + + + + + + + + Link to an external file with data map. + + + + + + + + + Data node description. + + + + + + + + + + + + + + + + + + A reference to a map. + + + + + + + + + Data source configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java index a0d5151d8a..62e4bde58c 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java @@ -184,4 +184,56 @@ public void testLoadDataEverything() { assertEquals("testConfigMap3_2", node1.getDataMapNames().iterator().next()); } + + @Test + public void testProjectVersion11() { + + // create and initialize loader instance to test + XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader(); + injector.injectMembers(loader); + + String testConfigName = "testConfig6"; + URL url = getClass().getResource("cayenne-" + testConfigName + ".xml"); + + ConfigurationTree tree = loader.load(new URLResource(url)); + + assertNotNull(tree); + + DataChannelDescriptor descriptor = tree.getRootNode(); + + assertNotNull(descriptor); + assertEquals(testConfigName, descriptor.getName()); + + Collection maps = descriptor.getDataMaps(); + assertEquals(2, maps.size()); + + Iterator mapsIt = maps.iterator(); + + DataMap map1 = mapsIt.next(); + DataMap map2 = mapsIt.next(); + + assertEquals("testConfigMap3_1", map1.getName()); + assertEquals("testConfigMap3_2", map2.getName()); + + Collection nodes = descriptor.getNodeDescriptors(); + assertEquals(1, nodes.size()); + + DataNodeDescriptor node1 = nodes.iterator().next(); + assertEquals("testConfigNode6", node1.getName()); + assertNull(node1.getParameters()); + assertNotNull(node1.getDataSourceDescriptor()); + assertEquals(1, node1.getDataSourceDescriptor().getMinConnections()); + assertEquals(1, node1.getDataSourceDescriptor().getMaxConnections()); + assertEquals(2000, node1.getDataSourceDescriptor().getMaxQueueWaitTime()); + assertEquals("SELECT 1 FROM VALIDATE", node1.getDataSourceDescriptor().getValidationQuery()); + + assertEquals("org.example.test.Adapter", node1.getAdapterType()); + assertEquals("org.example.test.DataSourceFactory", node1.getDataSourceFactoryType()); + assertEquals("org.example.test.SchemaUpdateStrategy", node1.getSchemaUpdateStrategyType()); + assertNotNull(node1.getDataMapNames()); + + assertEquals(1, node1.getDataMapNames().size()); + + assertEquals("testConfigMap3_2", node1.getDataMapNames().iterator().next()); + } } diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig6.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig6.xml new file mode 100644 index 0000000000..7a3be3bf38 --- /dev/null +++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig6.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + +