From 57cd6345f4ad41a54520cb87aee0866ce10377a1 Mon Sep 17 00:00:00 2001 From: ankitalode Date: Tue, 20 Jul 2021 10:27:58 +0000 Subject: [PATCH] SDK v10.3 release Signed-off-by: Ankita Lode --- bindings-generator/pom.xml | 4 +- pom.xml | 7 +- vcd-bindings-maven-plugin/pom.xml | 8 +- vcd-xjc-plugins/pom.xml | 33 +- .../api/annotation/CrossReferences.java | 50 +++ .../vcloud/api/annotation/DefaultSort.java | 56 +++ .../vmware/vcloud/api/annotation/Event.java | 50 +++ .../vcloud/api/annotation/LinkParamName.java | 48 ++ .../vcloud/api/annotation/MultiSite.java | 79 ++++ .../vcloud/api/annotation/Password.java | 46 ++ .../vcloud/api/annotation/Restricted.java | 46 ++ .../vcloud/api/annotation/Supported.java | 24 +- .../http/converters/JAXBElementConverter.java | 137 ++++++ .../api/http/converters/JAXBElementMixIn.java | 2 - .../api/http/converters/QNameMixin.java | 74 ++++ .../converters/QueryResultJsonRecords.java | 140 ++++++ .../GlobalIdToJavaTypeResolver.java | 140 ++++++ .../vcloud/api/rest/version/ApiVersion.java | 418 ++++++++++++++---- .../rest/version/ApiVersionCacheHelper.java | 2 +- .../vmware/vcloud/api/utils/Constants.java | 42 ++ .../com/vmware/vcloud/api/utils/UrnUtils.java | 116 +++++ 21 files changed, 1404 insertions(+), 118 deletions(-) create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/CrossReferences.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/DefaultSort.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Event.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/LinkParamName.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/MultiSite.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Password.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Restricted.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementConverter.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QNameMixin.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QueryResultJsonRecords.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/jaxrs/typeresolvers/GlobalIdToJavaTypeResolver.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/Constants.java create mode 100644 vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/UrnUtils.java diff --git a/bindings-generator/pom.xml b/bindings-generator/pom.xml index 9eae5e7..dd26e8b 100644 --- a/bindings-generator/pom.xml +++ b/bindings-generator/pom.xml @@ -11,14 +11,14 @@ com.vmware.vcloud vcd-api-tooling-parent - 9.7 + 10.3.0 ${project.artifactId} :: Bindings generation utility Provides custom API bindings generation beyond what can be accomplished with xjc and OpenAPI 3.7 - 1.8 + 11 2.3.0 1.72 1.2.3 diff --git a/pom.xml b/pom.xml index 4d93571..7af5d54 100644 --- a/pom.xml +++ b/pom.xml @@ -1,14 +1,9 @@ - 4.0.0 com.vmware.vcloud vcd-api-tooling-parent - 9.7 + 10.3.0 pom ${project.artifactId} :: vCloud Director REST API tooling parent Parent project housing tools and utilities to process vCloud Director APIs and build bindings diff --git a/vcd-bindings-maven-plugin/pom.xml b/vcd-bindings-maven-plugin/pom.xml index e703ad0..08ee1a4 100644 --- a/vcd-bindings-maven-plugin/pom.xml +++ b/vcd-bindings-maven-plugin/pom.xml @@ -12,7 +12,7 @@ com.vmware.vcloud vcd-api-tooling-parent - 9.7 + 10.3.0 ${project.artifactId} :: Maven plugin wrapper for bindings generation utility @@ -40,13 +40,13 @@ maven-compiler-plugin 2.5.1 - 1.8 - 1.8 + 11 + 11 maven-plugin-plugin - 3.5.1 + 3.6.0 com.vmware.vcloud:vcd-bindings-maven-plugin diff --git a/vcd-xjc-plugins/pom.xml b/vcd-xjc-plugins/pom.xml index 2421c71..f6006fb 100644 --- a/vcd-xjc-plugins/pom.xml +++ b/vcd-xjc-plugins/pom.xml @@ -10,7 +10,7 @@ com.vmware.vcloud vcd-api-tooling-parent - 9.7 + 10.3.0 jar ${project.artifactId} :: Custom plugins for XML to Java Compilation @@ -29,12 +29,37 @@ com.fasterxml.jackson.core jackson-annotations - com.fasterxml.jackson.core jackson-databind 2.12.2 - - + + + javax.ws.rs + javax.ws.rs-api + 2.0.1 + + + org.apache.commons + commons-lang3 + 3.7 + + + org.apache.cxf + cxf-core + 3.1.11 + + + + + maven-compiler-plugin + + utf8 + 11 + 11 + + + + diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/CrossReferences.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/CrossReferences.java new file mode 100644 index 0000000..d26f22a --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/CrossReferences.java @@ -0,0 +1,50 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates properties that are not explicitly contained in the model object, but can be + * used to filter a query on the model object. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +public @interface CrossReferences { + /** + * The alias name for the cross referenced property. + * + * E.g: computePolicyType in OrgVdc that refers to policyType in VdcComputePolicy + */ + String[] aliases(); +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/DefaultSort.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/DefaultSort.java new file mode 100644 index 0000000..88ca96a --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/DefaultSort.java @@ -0,0 +1,56 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation denotes the default field and direction the annotated method can use to determine + * how it should sort it's return values in the case when the caller has not provided this + * information. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface DefaultSort { + + /** + * Default field to be used when sorting results. + */ + String defaultSortField(); + + /** + * Determines direction of sort, ascending if "true". + */ + boolean sortAscending(); + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Event.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Event.java new file mode 100644 index 0000000..1dcfb2d --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Event.java @@ -0,0 +1,50 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to annotate methods that have an associated Audit Trail API Event. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Event { + + /** + * The name of the EventTopic to look up an associated Builder implementation of. + * + * @return the String name of the EventTopic. + */ + String eventTopicName(); +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/LinkParamName.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/LinkParamName.java new file mode 100644 index 0000000..f038d06 --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/LinkParamName.java @@ -0,0 +1,48 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.PARAMETER; + +/** + * This annotation is generated by the Swagger code generator on all parameters on all API methods. + * It is used to match up link parameter names during link generation. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ PARAMETER }) +public @interface LinkParamName { + + String value(); + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/MultiSite.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/MultiSite.java new file mode 100644 index 0000000..b0c4c5e --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/MultiSite.java @@ -0,0 +1,79 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.xml.bind.JAXBElement; + +import com.vmware.vcloud.api.rest.version.ApiVersion; + + +/** + * Indicates that a handler method can handle multi-site requests. A list of collection field names + * to be merged in the result body can be optionally specified. A custom response builder class can + * also be optionallyspecified to handle aggregation of the federated responses. If neither is + * specified, default aggregation implementation will be applied to the results. + */ +@Inherited +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface MultiSite { + + /** + * Specifies the list of collection names in a {@link JAXBElement} type that should be merged to + * create a multi-site response. i.e. the contents of independent response objects from multiple + * associated Org endpoints will be merged into a single collection in the response object + */ + String[] mergeCollections() default {}; + + /** + * Specifies a custom class to use to build a multi-site response object. If none specified, a + * default multi-site response builder will be used to construct a multi-site response for the + * request. Any mrgeCollections value is ignored if a custom response builder is specified + */ + Class customResponseBuilder() default Object.class; + + /** + * Specifies an {@link ApiVersion.Alias} to add support for multi-site request fanout. If none + * specified, a default {@code ApiVersion.Alias.MULTI_SITE} is used + */ + ApiVersion.Alias addedIn() default ApiVersion.Alias.MULTI_SITE; + + /** + * Specifies an {@link ApiVersion.Alias} to remove support for multi-site request fanout. If + * none specified, a default {@code ApiVersion.Alias.FUTURE} is used + */ + ApiVersion.Alias removedIn() default ApiVersion.Alias.FUTURE; +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Password.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Password.java new file mode 100644 index 0000000..7f02e60 --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Password.java @@ -0,0 +1,46 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * This annotation denotes that the annotated field contains a password. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD }) +public @interface Password { + + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Restricted.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Restricted.java new file mode 100644 index 0000000..9944db7 --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Restricted.java @@ -0,0 +1,46 @@ +package com.vmware.vcloud.api.annotation; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation denotes that the annotated field is potentially restricted. Before writing out or + * reading in this field, the API framework should determine if the caller is allowed to see/use the + * field. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD }) +public @interface Restricted { + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Supported.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Supported.java index ef9b15e..ae216bb 100644 --- a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Supported.java +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/annotation/Supported.java @@ -4,7 +4,7 @@ * #%L * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation * %% - * Copyright (C) 2018 VMware, Inc. + * Copyright (C) 2018 - 2021 VMware, Inc. * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -36,28 +36,26 @@ /** * This annotation denotes when the specific feature was introduced to the - * REST-API and if and when it was removed.

- * - * A feature is present starting from {@link #addedIn()} version inclusive, to - * {@link #removedIn()} exclusive.

- * - * This annotation is added automatically to the JAXB generated classes. + * REST-API and if and when it was removed. This annotation is added + * automatically to the JAXB generated classes. + *

+ * The feature is present starting from {@link #addedIn()} version inclusive, to + * {@link #removedIn()} exclusive. + *

*/ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE }) public @interface Supported { + public static final String VCLOUD_LEGACY_FILTER_PARAM = "vcloud_legacy"; + /** - * Version in which the feature was added, inclusive. - * - * @return a version string + * Version in which the feature was added. */ String addedIn(); /** - * Version in which the feature was removed, exclusive. - * - * @return a version string + * Version in which the feature was removed. */ String removedIn() default ""; } diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementConverter.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementConverter.java new file mode 100644 index 0000000..cd29262 --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementConverter.java @@ -0,0 +1,137 @@ +package com.vmware.vcloud.api.http.converters; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.xml.bind.JAXBElement; + + +/** + * Converts an xsd-generated type into a {@link JAXBElement} wrapped representation + */ +public class JAXBElementConverter { + + private static class ObjectFactoryInvocation { + final Object objectFactory; + final Method factoryMethod; + + ObjectFactoryInvocation(Object objectFactory, Method factoryMethod) { + this.objectFactory = objectFactory; + this.factoryMethod = factoryMethod; + } + + public JAXBElement convert(Object value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + return (JAXBElement) factoryMethod.invoke(objectFactory, value); + } + } + + + private final List objectFactories; + + private static final ConcurrentMap, ObjectFactoryInvocation> jaxbFactoryMethods = + new ConcurrentHashMap<>(); + + public JAXBElementConverter(final List objectFactories) { + this.objectFactories = new ArrayList<>(objectFactories); + } + + /** + * Locates the factory method from among the {@code ObjectFactory}s this instance was seeded + * with and converts the payload into its {@link JAXBElement} wrapped representation + * + * @param value + * xsd-generated type object to be wrapped within a {@link JAXBElement} + * @return {@link JAXBElement} wrapped representation + * + * @throws IllegalAccessException + * if there was an error invoking the factory method. + * @throws IllegalArgumentException + * if factory method to rejected the argument. + * @throws NullPointerException + * They payload to be converted has no applicable factory method to effect the + * conversion. + * @throws InvocationTargetException + * if there was an error invoking the factory method. + */ + public JAXBElement convertToJAXBElement(Object value) throws IllegalAccessException, + IllegalArgumentException, + NullPointerException, + InvocationTargetException { + + final ObjectFactoryInvocation jaxbConverter = getJAXBFactoryMethodInfo(value.getClass()); + final JAXBElement result = jaxbConverter.convert(value); + return result; + } + + /** + * For a payload type locate the {@code ObjectFactory} and the {@link Method} on that factory + * that will effect the conversion + *

+ * The pair is wrapped in an {@link ObjectFactoryInvocation} object and cached for quicker + * lookups in the future + * + * @param elementCls + * - xsd-generated type's {@link Class} + * + * @return {@link ObjectFactoryInvocation} whose {@link ObjectFactoryInvocation#convert(Object) + * convert} method can be invoked to get the {@link JAXBElement} + */ + private ObjectFactoryInvocation getJAXBFactoryMethodInfo(Class elementCls) { + return jaxbFactoryMethods.computeIfAbsent(elementCls, this::getConverter); + } + + private ObjectFactoryInvocation getConverter(Class elementCls) { + for (Object factory : objectFactories) { + Method[] methods = factory.getClass().getMethods(); + for (Method m : methods) { + Class[] pTypes = m.getParameterTypes(); + Class pType = null; + if (pTypes != null && pTypes.length == 1) { + pType = pTypes[0]; + } else { + continue; + } + + Class type = m.getReturnType(); + if (elementCls.equals(pType) && JAXBElement.class.isAssignableFrom(type)) { + return new ObjectFactoryInvocation(factory, m); + } + } + } + + return null; + } +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementMixIn.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementMixIn.java index 06db0f8..2c315a5 100644 --- a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementMixIn.java +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/JAXBElementMixIn.java @@ -50,5 +50,3 @@ public abstract class JAXBElementMixIn { @JsonValue public abstract Object getValue(); } - - diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QNameMixin.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QNameMixin.java new file mode 100644 index 0000000..789fb9e --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QNameMixin.java @@ -0,0 +1,74 @@ +package com.vmware.vcloud.api.http.converters; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import javax.xml.namespace.QName; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * A Jackson Mixin to assist in parsing {@link QName} from its string representation + *

+ * {@link QName}, which primarily consists of a {@code namespace URI} and a {@code localpart}, is + * serialized in {@code json} representation of our legacy API types as per the most commonly + * accepted way of representing it as defined by James + * Clark..
+ * Parsing such a string can be accomplished by {@link QName#valueOf(String)} method. + *

+ * {@link ObjectMapper}'s order of preference causes {@link QName#QName(String)} single argument + * constructor to be preferred over this method over a similar single argument factory method (which + * would be {@code QName#valueOf(String)}. As a result, a single string, that is formatted as above, + * is interpreted as a {@code QName} that is comprised solely of the {@code localpart} instead of + * potentially both, {@code namespace URI} and {@code localpart}. + *

+ * This mixin instructs the {@link ObjectMapper} to ignore that constructor and instead use the + * {@link QName#valueOf(String) valueOf method} as a factory method to parse the incoming string. + *

+ * De-serializing the payload is handled by {@link QName#toString()} method + *

+ * Ref:Official + * Jackson MixIn Annotations Documentation + * + * @see QName#toString() + * @see QName#valueOf(String) + */ +public abstract class QNameMixin { + + @JsonIgnore + public QNameMixin(String localPart) {} + + @JsonCreator + public static QName valueOf(String qNameAsString) { + return QName.valueOf(qNameAsString); + } + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QueryResultJsonRecords.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QueryResultJsonRecords.java new file mode 100644 index 0000000..944f611 --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/http/converters/QueryResultJsonRecords.java @@ -0,0 +1,140 @@ +/* ********************************************************************** + * Copyright 2018 VMware, Inc. All rights reserved. VMware Confidential + * *********************************************************************/ + +package com.vmware.vcloud.api.http.converters; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * Wrapper to provide access to OpenAPI query results. + * + * @since 9.7 + */ +public class QueryResultJsonRecords { + + private static final String TOTAL_METHOD = "getResultTotal"; + private static final String COUNT_METHOD = "getPageCount"; + private static final String PAGE_METHOD = "getPage"; + private static final String PAGE_SIZE_METHOD = "getPageSize"; + private static final String GET_VALUES_METHOD = "getValues"; + private static final String SET_VALUES_METHOD = "setValues"; + + private final int resultTotal; + private final int pageCount; + private final int page; + private final int pageSize; + private final List values; + + public QueryResultJsonRecords(Object openApiResults) { + try { + this.resultTotal = getInt(openApiResults, TOTAL_METHOD); + this.pageCount = getInt(openApiResults, COUNT_METHOD); + this.page = getInt(openApiResults, PAGE_METHOD); + this.pageSize = getInt(openApiResults, PAGE_SIZE_METHOD); + List valueResults = getList(openApiResults, GET_VALUES_METHOD); + + // Client might set valueResults to be immutable list but this class assume list is mutable in MultisiteOpenApiFilter. + if (valueResults == null || valueResults.size() == 0) { + this.values = new ArrayList<>(); + } else { + this.values = new ArrayList<>(valueResults); + } + setList(openApiResults, SET_VALUES_METHOD, values); + + } catch (SecurityException | ReflectiveOperationException e) { + throw new IllegalArgumentException("Unable to create JSON record from provided object", e); + } + } + + private int getInt(Object object, String methodName) throws ReflectiveOperationException, SecurityException { + final Object invokeMethod = invokeMethod(object, methodName); + if (!(invokeMethod instanceof Integer)) { + throwException(object, methodName); + } + + return (int) invokeMethod; + } + + @SuppressWarnings("unchecked") + private List getList(Object object, String methodName) throws ReflectiveOperationException, SecurityException { + final Object invokeMethod = invokeMethod(object, methodName); + if (!(invokeMethod instanceof List)) { + throwException(object, methodName); + } + + return (List) invokeMethod; + } + + @SuppressWarnings("unchecked") + private void setList(Object object, String methodName, List values) throws ReflectiveOperationException, SecurityException { + final Method method = object.getClass().getMethod(methodName, List.class); + method.invoke(object, values); + } + + private void throwException(Object object, String methodName) throws ReflectiveOperationException { + throw new ReflectiveOperationException("Unexpected return type from " + methodName + " on " + object.getClass().getSimpleName()); + } + + /** + * Invokes {@code methodName} on the provided {@link Object} and returns + * the result. + */ + private Object invokeMethod(Object object, String methodName) throws ReflectiveOperationException, SecurityException { + final Method method = object.getClass().getMethod(methodName); + final Object result = method.invoke(object); + return result; + } + + public int getResultTotal() { + return resultTotal; + } + + public int getPageCount() { + return pageCount; + } + + public int getPage() { + return page; + } + + public int getPageSize() { + return pageSize; + } + + public List getValues() { + return values; + } + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/jaxrs/typeresolvers/GlobalIdToJavaTypeResolver.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/jaxrs/typeresolvers/GlobalIdToJavaTypeResolver.java new file mode 100644 index 0000000..c763d9b --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/jaxrs/typeresolvers/GlobalIdToJavaTypeResolver.java @@ -0,0 +1,140 @@ +package com.vmware.vcloud.api.rest.jaxrs.typeresolvers; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.xml.bind.JAXBElement; + +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.databind.jsontype.impl.MinimalClassNameIdResolver; + +import org.apache.cxf.common.util.ClasspathScanner; + +/** + * This class scans the rest schema classes and builds a map of simple class names to java classes. + * This class is used by a DeserializationProblemHandler to resolve type names that cannot be + * resolved by the standard deserialization process. + * + */ +public final class GlobalIdToJavaTypeResolver extends MinimalClassNameIdResolver { + + private final List apiClassPackages; + + private final Class restApiJsonMarkerAnnotation; + + private final Class schemaClass; + + /* This is an id-to-List> mapping because some id's can have more than one Class associated with them: + * e.g., "Property" + * ./com/vmware/vcloud/api/rest/schema/ovf/Property + * ./com/vmware/vcloud/api/rest/schema/ovf/environment/Property + */ + final private Map>> idToTypeList; + + final ObjectMapper mapper; + + + public GlobalIdToJavaTypeResolver(final List apiClassPackages, + final Class restApiJsonMarkerAnnotation, + final Class schemaClass, final ObjectMapper mapper) { + super(mapper.getDeserializationConfig().constructType(java.lang.Object.class), + mapper.getTypeFactory(), LaissezFaireSubTypeValidator.instance); + this.apiClassPackages = apiClassPackages; + this.restApiJsonMarkerAnnotation = restApiJsonMarkerAnnotation; + this.schemaClass = schemaClass; + idToTypeList = getIdToJavaTypeMap(); + this.mapper = mapper; + } + + @Override + public String idFromValue(Object value) { + if (value instanceof JAXBElement) { + return (((javax.xml.bind.JAXBElement) value).getDeclaredType().getSimpleName()); + //TODO enhance to scan for JsonTypeName annotations: https://jira.eng.vmware.com/browse/VTEN-3181 + } else { + return super.idFromValue(value); + } + } + + + public JavaType getJavaTypeForId(final DeserializationContext ctxt, final String subTypeId) { + + if (idToTypeList.get(subTypeId) == null) { + return null; + } + + final Class classForId = idToTypeList.get(subTypeId).get(0); + return ctxt.constructType(classForId); + } + + + private Map>> getIdToJavaTypeMap() { + final Map>> result = new HashMap<>(); + final List> apiClasses = getRestApiClassesWithJsonMarkerAnnotation(); + apiClasses.stream().forEach(c -> { + final String classId = c.getSimpleName(); + List> classListForId = result.computeIfAbsent(classId, k -> new ArrayList<>()); + classListForId.add(c); + }); + return result; + } + + + private List> getRestApiClassesWithJsonMarkerAnnotation() { + + final List> classes = new ArrayList<>(); + //Make sure we use the rest-api-schemas loader. If we use the class loader for rest-api-toolkit (the 'this' class loader), + //it loads the wrong com.vmware.vcloud.api.rest package. + final ClassLoader restSchemaClassLoader = schemaClass.getClassLoader(); + + try { + classes.addAll(ClasspathScanner + .findClasses(apiClassPackages, Arrays.asList(restApiJsonMarkerAnnotation), + restSchemaClassLoader) + .values().stream().flatMap(Collection::stream).collect(Collectors.toList())); + } catch (ClassNotFoundException | IOException e) { + //Ignore + } + return classes; + } + +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersion.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersion.java index 4b29169..170e506 100644 --- a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersion.java +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersion.java @@ -29,184 +29,250 @@ * #L% */ -import java.util.Arrays; +import java.io.Serializable; +import java.util.Comparator; import java.util.List; +import java.util.NavigableMap; import java.util.Set; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.stream.Collectors; import com.vmware.vcloud.api.annotation.Supported; /** + * API version and alias handling. *

- * Enum with supported API version. - *

- * IMPORTANT! Versions are compared using the natural enum order, so keep them in ascending - * order! - *

- * See https://wiki.eng.vmware.com/CloudAPI/CompatibilityAndVersioning for rules related to adding - * new API versions + * See https://confluence.eng.vmware.com/pages/viewpage.action?spaceKey=VCD&title=API+Development+Guide#APIDevelopmentGuide-APIVersions + * for details related to API versioning + * * @since 1.5.0 */ -public enum ApiVersion { +public class ApiVersion implements Comparable, Serializable { + + private static final long serialVersionUID = 1L; + + private static final String ALPHA_VERSION_TAIL = ".0-alpha"; + + private static final String FUTURE_VERSION_ALIAS = ""; + + private static final Comparator VERSION_STRING_COMPARATOR = new Comparator<>() { + private final Function split = s -> { + final String[] tokens = s.split("\\."); + if (tokens.length > 2) { + throw new AssertionError("Comparator must be updated to handle x.y.z"); + } + return new int[] { Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1]) }; + }; + @Override + public int compare(String s1, String s2) { + final int[] v1 = split.apply(s1); + final int[] v2 = split.apply(s2); + if (v1[0] == v2[0]) { + return Integer.compare(v1[1], v2[1]); + } + return Integer.compare(v1[0], v2[0]); + } + }; + + /** + * Map holding all valid API versions, mapped to their version string. + *

+ * The highest supported version will always (and only) indicate alpha support. + */ + private static final NavigableMap VERSIONS = new TreeMap<>(VERSION_STRING_COMPARATOR); + + /* + * New API versions should be added below, each will automatically be + * added to the above map used by the rest of the {@code ApiVersion} class. + *

+ * Order of the below doesn't strictly matter since the containing map will be + * ordered based on the version string, not insertion order. But adding items + * in their appropriate order is encouraged for increased readability. + *

+ * When adding a version corresponding to a new product version (i.e. not a + * patch) you will typically want to also deprecate the API version(s) + * corresponding to the oldest non-deprecated product version. See above-linked + * confluence for further guidance. + */ /** Introduced in product version 1.0 / Redwood */ @Deprecated - VERSION_1_0("1.0", true), + public static final ApiVersion VERSION_1_0 = new ApiVersion(1, 0, true); /** Introduced in product version 1.5 / Toledo */ @Deprecated - VERSION_1_5("1.5", true), + public static final ApiVersion VERSION_1_5 = new ApiVersion(1, 5, true); /** Introduced in product version 5.1 / T2 */ @Deprecated - VERSION_5_1("5.1", true), + public static final ApiVersion VERSION_5_1 = new ApiVersion(5, 1, true); /** Introduced in product version 5.5 / OP */ @Deprecated - VERSION_5_5("5.5", true), + public static final ApiVersion VERSION_5_5 = new ApiVersion(5, 5, true); /** Introduced in product version 5.6 / Northstar */ @Deprecated - VERSION_5_6("5.6", true), + public static final ApiVersion VERSION_5_6 = new ApiVersion(5, 6, true); /** Introduced in product version 5.7 */ @Deprecated - VERSION_5_7("5.7", true), + public static final ApiVersion VERSION_5_7 = new ApiVersion(5, 7, true); /** Introduced in product version 5.8 */ @Deprecated - VERSION_5_8("5.8", true), + public static final ApiVersion VERSION_5_8 = new ApiVersion(5, 8, true); /** Introduced in product version 5.9 */ @Deprecated - VERSION_5_9("5.9", true), + public static final ApiVersion VERSION_5_9 = new ApiVersion(5, 9, true); /** Introduced in product version 6.1 */ @Deprecated - VERSION_5_10("5.10", true), + public static final ApiVersion VERSION_5_10 = new ApiVersion(5, 10, true); /** Introduced in product version 6.2 */ @Deprecated - VERSION_5_11("5.11", true), + public static final ApiVersion VERSION_5_11 = new ApiVersion(5, 11, true); /** Introduced in product version 6.3 */ @Deprecated - VERSION_5_12("5.12", true), + public static final ApiVersion VERSION_5_12 = new ApiVersion(5, 12, true); /** Introduced in product version 6.4 */ @Deprecated - VERSION_6_0("6.0", true), + public static final ApiVersion VERSION_6_0 = new ApiVersion(6, 0, true); /** Introduced in product version 6.5 */ @Deprecated - VERSION_7_0("7.0", true), - - /** Reserved for potential use in a release between 6.5 and 7.1 */ - //VERSION_8_0("8.0", true), + public static final ApiVersion VERSION_7_0 = new ApiVersion(7, 0, true); /** Introduced in product version 7.1 */ @Deprecated - VERSION_9_0("9.0", true), + public static final ApiVersion VERSION_9_0 = new ApiVersion(9, 0, true); /** Introduced in product version 8.1 */ @Deprecated - VERSION_11_0("11.0", true), + public static final ApiVersion VERSION_11_0 = new ApiVersion(11, 0, true); /** Introduced in product version 8.2 */ @Deprecated - VERSION_12_0("12.0", true), + public static final ApiVersion VERSION_12_0 = new ApiVersion(12, 0, true); /** Introduced in product version 8.3 */ @Deprecated - VERSION_13_0("13.0", true), + public static final ApiVersion VERSION_13_0 = new ApiVersion(13, 0, true); /** Introduced in product version 8.4 */ @Deprecated - VERSION_14_0("14.0", true), + public static final ApiVersion VERSION_14_0 = new ApiVersion(14, 0, true); /** Introduced in product version 8.6 */ @Deprecated - VERSION_16_0("16.0", true), + public static final ApiVersion VERSION_16_0 = new ApiVersion(16, 0, true); /** Introduced in product version 8.7 */ @Deprecated - VERSION_17_0("17.0", true), + public static final ApiVersion VERSION_17_0 = new ApiVersion(17, 0, true); /** Introduced in product version 8.8 */ @Deprecated - VERSION_18_0("18.0", true), + public static final ApiVersion VERSION_18_0 = new ApiVersion(18, 0, true); /** Introduced in product version 8.9 */ @Deprecated - VERSION_19_0("19.0", true), + public static final ApiVersion VERSION_19_0 = new ApiVersion(19, 0, true); /** Introduced in product version 8.10 / Riverfront */ @Deprecated - VERSION_20_0("20.0", true), + public static final ApiVersion VERSION_20_0 = new ApiVersion(20, 0, true); /** Introduced in product version 8.11 */ @Deprecated - VERSION_21_0("21.0", true), + public static final ApiVersion VERSION_21_0 = new ApiVersion(21, 0, true); /** Introduced in product version 8.12 */ @Deprecated - VERSION_22_0("22.0", true), + public static final ApiVersion VERSION_22_0 = new ApiVersion(22, 0, true); /** Introduced in product version 8.13 */ @Deprecated - VERSION_23_0("23.0", true), + public static final ApiVersion VERSION_23_0 = new ApiVersion(23, 0, true); /** Introduced in product version 8.14 */ @Deprecated - VERSION_24_0("24.0", true), + public static final ApiVersion VERSION_24_0 = new ApiVersion(24, 0, true); /** Introduced in product version 8.15 */ @Deprecated - VERSION_25_0("25.0", true), + public static final ApiVersion VERSION_25_0 = new ApiVersion(25, 0, true); /** Introduced in product version 8.16 */ @Deprecated - VERSION_26_0("26.0", true), + public static final ApiVersion VERSION_26_0 = new ApiVersion(26, 0, true); - /** Introduced in product version Sunglow (8.20) - * Despite being deprecated, this version will stick around for a long time. - */ + /** Introduced in product version Sunglow (8.20) */ @Deprecated - VERSION_27_0("27.0", true), + public static final ApiVersion VERSION_27_0 = new ApiVersion(27, 0, true); /** Introduced in product version 8.21 **/ @Deprecated - VERSION_28_0("28.0", true), + public static final ApiVersion VERSION_28_0 = new ApiVersion(28, 0, true); /** Introduced in product version Trifecta (9.0) **/ - VERSION_29_0("29.0"), + @Deprecated + public static final ApiVersion VERSION_29_0 = new ApiVersion(29, 0, true); /** Introduced in product version Ulysses (9.1) **/ - VERSION_30_0("30.0"), + @Deprecated + public static final ApiVersion VERSION_30_0 = new ApiVersion(30, 0, true); /** Introduced in product version Vulcan (9.5) **/ - VERSION_31_0("31.0"), + @Deprecated + public static final ApiVersion VERSION_31_0 = new ApiVersion(31, 0, true); + + /** Introduced in product version Wellington (9.7) **/ + @Deprecated + public static final ApiVersion VERSION_32_0 = new ApiVersion(32, 0, true); - /** Introduced in product version Wellington **/ - VERSION_32_0("32.0"), + /** Introduced in product version Xendi (10.0) **/ + public static final ApiVersion VERSION_33_0 = new ApiVersion(33, 0, true); - /** Larger than all versions. Keep last! */ - VERSION_MAX(""); + /** Introduced in product version Yorktown (10.1) **/ + public static final ApiVersion VERSION_34_0 = new ApiVersion(34, 0); + + /** Introduced in product version Zeus (10.2) **/ + public static final ApiVersion VERSION_35_0 = new ApiVersion(35, 0); + + /** Zeus update 2 **/ + public static final ApiVersion VERSION_35_2 = new ApiVersion(35, 2); + + /** Product version Andromeda **/ + public static final ApiVersion VERSION_36_0 = new ApiVersion(36, 0); + + /** Product version Betelgeuse **/ + public static final ApiVersion VERSION_37_0 = new ApiVersion(37, 0); + + /** Represents a hypothetical future version greater than all existing supported versions **/ + public static final ApiVersion VERSION_FUTURE = new ApiVersion(Integer.MAX_VALUE, Integer.MAX_VALUE); /** * This enum will help manage all API version alias mappings. */ public enum Alias { - MIN_SUPPORTED(ApiVersion.VERSION_20_0), + MIN_SUPPORTED(ApiVersion.VERSION_31_0), + ALPHA(getAlphaVersion()), + FUTURE(ApiVersion.VERSION_FUTURE), OBJECT_EXTENSIBILITY(ApiVersion.VERSION_16_0), VM_AFFINITY_RULES(ApiVersion.VERSION_20_0), - MAX_SUPPORTED(ApiVersion.VERSION_32_0), + MAX_SUPPORTED(ApiVersion.VERSION_36_0), VAPP_AUTO_NATURE(ApiVersion.VERSION_22_0), VDC_ADOPT_RP(ApiVersion.VERSION_22_0), PERSIST_TABLE_ACCESS(ApiVersion.VERSION_22_0), VDC_PERMISSIONS(ApiVersion.VERSION_11_0), OPTIMIZED_REVERT_VAPP_WORKFLOW(ApiVersion.VERSION_14_0), VDC_TEMPLATES(ApiVersion.VERSION_5_7), - FUTURE(ApiVersion.VERSION_MAX), ORG_RIGHTS_ROLES(ApiVersion.VERSION_27_0), MULTI_SITE(ApiVersion.VERSION_29_0), VM_HOST_AFFINITY(ApiVersion.VERSION_27_0), @@ -236,6 +302,7 @@ public enum Alias { PVDC_TAGGING_SUPPORT(ApiVersion.VERSION_31_0), ORG_ASSOC_RESP_UPDATE(ApiVersion.VERSION_31_0), OIDC_SUPPORT(ApiVersion.VERSION_31_0), + @Deprecated PROBE_REMOTE_LIBRARY(ApiVersion.VERSION_31_0), RBAC_2(ApiVersion.VERSION_31_0), RESERVED_BUS_UNIT_NUMBER(ApiVersion.VERSION_31_0), @@ -246,6 +313,7 @@ public enum Alias { SITE_ORG_ASSOCIATIONS_QUERY(ApiVersion.VERSION_31_0), ORG_VDC_NETWORKING(ApiVersion.VERSION_32_0), CPOM(ApiVersion.VERSION_32_0), + CPOM_PROVIDER(ApiVersion.VERSION_33_0), GENERIC_VDC_TYPE(ApiVersion.VERSION_32_0), VC_NONE_NETWORK(ApiVersion.VERSION_32_0), PREFERENCES(ApiVersion.VERSION_32_0), @@ -260,7 +328,50 @@ public enum Alias { NSXT_EDGE_DNS(ApiVersion.VERSION_32_0), CREATE_BLANK_VM(ApiVersion.VERSION_32_0), INSTANTIATE_VM_TEMPLATE(ApiVersion.VERSION_32_0), - SECURITY_CONTEXT_CACHE_IN_DB(ApiVersion.VERSION_32_0), + VAPP_LOCALID_VM_QUERY(ApiVersion.VERSION_33_0), + NSXT_SERVICES(ApiVersion.VERSION_33_0), + VM_SIZING_POLICY(ApiVersion.VERSION_33_0), + AUTH_HEADERS_LOGIN_ONLY(ApiVersion.VERSION_33_0), + VM_REAPPLY_COMPUTE_POLICY(ApiVersion.VERSION_33_0), + VDC_MAX_COMPUTE_POLICY_CREATE(ApiVersion.VERSION_33_0), + VC_RESOURCE_POOLS(ApiVersion.VERSION_33_0), + ALLOW_ACTIVITY_ACCESS_IN_MAINT_MODE(ApiVersion.VERSION_33_0), + API_EXPLORER_VIEW(ApiVersion.VERSION_33_0), + AUDIT_TRAIL(ApiVersion.VERSION_33_0), + SECURITY_CONTEXT_CACHE_IN_DB(ApiVersion.VERSION_33_0), + INCLUDE_API_VERSION_IN_AUTH_LOCATION(ApiVersion.VERSION_33_0), + VDC_COMPUTE_POLICIES(ApiVersion.VERSION_33_0), + CENTRAL_SSL_MANAGEMENT(ApiVersion.VERSION_34_0), + GATEWAY_EDGE_CLUSTER_CONFIGURATION(ApiVersion.VERSION_34_0), + STORAGE_POLICY_CAPABILITIES(ApiVersion.VERSION_34_0), + PROXY_CONFIGURATION(ApiVersion.VERSION_34_0), + QUERY_LIST_GENERATED_OPERATIONS(ApiVersion.VERSION_34_0), + GENERAL_ACL(ApiVersion.VERSION_35_0), + QUOTA_POLICY(ApiVersion.VERSION_35_0), + AVI_SUPPORT(ApiVersion.VERSION_35_0), + SLAAC_SUPPORT(ApiVersion.VERSION_35_0), + CPOM_MULTISITE(ApiVersion.VERSION_35_0), + EVENT_PROCESSING_SUPPORT(ApiVersion.VERSION_35_0), + FLEX_VDC_GROUP_SUPPORT(ApiVersion.VERSION_35_0), + EXTENSION_TOKENS(ApiVersion.VERSION_35_0), + PVDC_INHERITABLE_SETTINGS(ApiVersion.VERSION_35_0), + VDC_KUBERNETES_POLICY(ApiVersion.VERSION_35_0), + FILTER_ENCODED_REMOVED(ApiVersion.VERSION_35_0), + HOST_NUM_CPU(ApiVersion.VERSION_35_2), + CPOM_ANDROMEDA(ApiVersion.VERSION_36_0), + OAUTH_PROVIDER_CONFIG(ApiVersion.VERSION_36_0), + LDAP_SYNC_FLAG(ApiVersion.VERSION_35_2), + ALLOWED_ORIGINS(ApiVersion.VERSION_36_0), + SITE_DB_COLLATION(ApiVersion.VERSION_36_0), + DISK_MIGRATION(ApiVersion.VERSION_36_0), + STORAGE_ENTITY_TYPE_LIMITING(ApiVersion.VERSION_35_2), + ETAG_SUPPORT(ApiVersion.VERSION_35_2), + FIPS(ApiVersion.VERSION_35_2), + TAG(ApiVersion.VERSION_36_0), + RDE_HOOKS(ApiVersion.VERSION_36_0), + RDE_UPGRADE(ApiVersion.VERSION_36_0), + LEGACY_LOGIN_REMOVAL(getAlphaVersion()), + K8S_UNIFIED(getAlphaVersion()), ; private final ApiVersion mapping; @@ -272,11 +383,6 @@ public enum Alias { this.parentAlias = null; } - Alias(Alias alias) { - this.mapping = null; - this.parentAlias = alias; - } - /** * @return the aliased API Version */ @@ -289,24 +395,49 @@ public ApiVersion getMapping() { } } + private static final String VERSION_FORMAT = "%d.%d"; + private final String version; private final boolean isDeprecated; - ApiVersion(String version) { - this.version = version; - this.isDeprecated = false; + private final int majorVersion; + + private final int minorVersion; + + private Boolean isAlpha = null; + + private ApiVersion(int majorVersion, int minorVersion) { + this(majorVersion, minorVersion, false); } - ApiVersion(String version, boolean isDeprecated) { - this.version = version; + private ApiVersion(int majorVersion, int minorVersion, boolean isDeprecated) { + this.majorVersion = majorVersion; + this.minorVersion = minorVersion; this.isDeprecated = isDeprecated; + if (majorVersion == Integer.MAX_VALUE && minorVersion == Integer.MAX_VALUE) { + this.version = ""; + // This does NOT get put in VERSIONS because it's not a "real" version, just a convenience + } else { + this.version = String.format(VERSION_FORMAT, majorVersion, minorVersion); + VERSIONS.put(version, this); + } + } + + private boolean isAlpha() { + if (isAlpha == null) { + isAlpha = VERSIONS.lastKey().equals(this.version); + } + return isAlpha; } /** * @return the version as string */ public String value() { + if (isAlpha()) { + return version + ALPHA_VERSION_TAIL; + } return version; } @@ -323,13 +454,34 @@ public boolean isDeprecated() { * @throws IllegalArgumentException if the version is not recognized */ public static ApiVersion fromValue(String v) { - if (!ApiVersionCacheHelper.instance.isCached(v)) { - if (!ApiVersionCacheHelper.instance.isAliasCached(v)) { - throw new IllegalArgumentException("Unknown API version: " + v); + if (v == null || FUTURE_VERSION_ALIAS.equals(v)) { + return VERSION_FUTURE; + } + + final String ver; + if (v.contains(ALPHA_VERSION_TAIL)) { + /* Strip out anything after the Alpha tail (this may include a build + * identifier but such information is only for consumer's benefit, not + * for limiting compatibility across alpha requests). */ + ver = v.replaceFirst(ALPHA_VERSION_TAIL + ".*", ALPHA_VERSION_TAIL); + } else { + ver = v; + } + + if (!ApiVersionCacheHelper.instance.isCached(ver)) { + if (!ApiVersionCacheHelper.instance.isAliasCached(ver)) { + throw new IllegalArgumentException("Unknown API version: " + ver); } - return ApiVersionCacheHelper.instance.getAliasValue(v); + return ApiVersionCacheHelper.instance.getAliasValue(ver); + } + return ApiVersionCacheHelper.instance.getValue(ver); + } + + public static boolean isValidApiVersion(String v) { + if (!ApiVersionCacheHelper.instance.isCached(v) && !FUTURE_VERSION_ALIAS.equals(v)) { + return ApiVersionCacheHelper.instance.isAliasCached(v); } - return ApiVersionCacheHelper.instance.getValue(v); + return true; } /** @@ -350,13 +502,6 @@ public boolean isInRange(Supported s) { * @return {@code true} if min <= this < max */ public boolean isInRange(final ApiVersion min, final ApiVersion max) { - // TODO This check shouldn't be here. It only masks a real problem - // somewhere, as the requested version should never be equal to - // VERSION_MAX. - if (max == VERSION_MAX) { - return min.compareTo(this) <= 0; - } - return min.compareTo(this) <= 0 && this.compareTo(max) < 0; } @@ -372,6 +517,29 @@ public boolean isAtLeast(final ApiVersion version) { return this.compareTo(version) >= 0; } + /** + * Tests if the Api Version represented by this {@code ApiVersion} is greater than or equal to + * the given {@code Alias}. + * @param alias Alias to compare to + * @return true if this {@code ApiVersion} is greater than or equal to {@code alias}, false + * otherwise + */ + public boolean isAtLeast(final Alias alias) { + return isAtLeast(alias.getMapping()); + } + + /** + * Tests if this {@code ApiVersion} is greater than the given one. + * + * @param version + * the version to compare this version to + * @return true if this {@code ApiVersion} is greater than or equal to {@code version}, false + * otherwise + */ + public boolean isGreaterThan(final ApiVersion version) { + return this.compareTo(version) > 0; + } + /** * Tests if this {@code ApiVersion} is less than or equal to the given one. * @@ -384,6 +552,30 @@ public boolean isAtMost(final ApiVersion version) { return this.compareTo(version) <= 0; } + /** + * Tests if this {@code ApiVersion} is less than the given one. + * + * @param version + * the version to compare this version to + * @return true if this {@code ApiVersion} is less than {@code version}, false + * otherwise + */ + public boolean isLessThan(final ApiVersion version) { + return this.compareTo(version) < 0; + } + + /** + * Tests if this {@code ApiVersion} is less than the given ${@code ApiVersion.Alias}. + * + * @param alias + * the alias to compare this version to + * @return true if this {@code ApiVersion} is less than {@code alias}, false + * otherwise + */ + public boolean isLessThan(final Alias alias) { + return isLessThan(alias.getMapping()); + } + /** * @return {@code true} if this version falls within the supported range * of the {@link Supported} annotation (including if no range is provided) @@ -425,13 +617,9 @@ public static boolean isAnAlias(String aliasStr) { */ public static List getRange(final ApiVersion minApiVersion, final ApiVersion maxApiVersion) { - - final int startIndex = minApiVersion.ordinal(); - final int endIndex = maxApiVersion.ordinal() + 1; - - final ApiVersion[] values = ApiVersion.values(); - - return Arrays.asList(Arrays.copyOfRange(values, startIndex, endIndex)); + return VERSIONS.values().stream() + .filter(api -> api.isAtLeast(minApiVersion) && api.isAtMost(maxApiVersion)) + .collect(Collectors.toList()); } /** @@ -445,6 +633,64 @@ public static List getRange(final ApiVersion minApiVersion, public static List getRangeAbove(final ApiVersion minApiVersion) { return getRange(minApiVersion, Alias.MAX_SUPPORTED.getMapping()); } + + /** + * Returns the ApiVersion preceding the given ApiVersion intended for use only for ApiVersion + * 29.0 and above. + * + * @param apiVersion + * @return ApiVersion preceding given version. + * @throws UnsupportedOperationException + * for ApiVersion 28.0 and below + */ + public static ApiVersion getPreviousVersion(final ApiVersion apiVersion) + throws UnsupportedOperationException { + if (apiVersion.isLessThan(VERSION_29_0)) { + throw new UnsupportedOperationException( + "Only supported for API version 29.0 and above."); + } + /* We could compute this for each version and cache it but at present + * the only non-test call to this is a single call from a CMT command + * so there's no need to optimize it presently. */ + ApiVersion previous = null; + for (ApiVersion version : VERSIONS.values()) { + if (version.equals(apiVersion)) { + return previous; + } + previous = version; + } + return null; + } + + @Override + public int compareTo(ApiVersion other) { + if (other == null) { + return 1; + } + + if (this.majorVersion == other.majorVersion) { + return Integer.compare(this.minorVersion, other.minorVersion); + } + + return Integer.compare(this.majorVersion, other.majorVersion); + } + + @Override + public String toString() { + return value(); + } + + public static ApiVersion getAlphaVersion() { + return VERSIONS.lastEntry().getValue(); + } + + public static ApiVersion[] values() { + return VERSIONS.values().toArray(new ApiVersion[0]); + } + + public static ApiVersion valueOf(String apiVersion) { + return fromValue(apiVersion); + } } diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersionCacheHelper.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersionCacheHelper.java index 8732069..8f728db 100644 --- a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersionCacheHelper.java +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/rest/version/ApiVersionCacheHelper.java @@ -4,7 +4,7 @@ * #%L * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation * %% - * Copyright (C) 2018 VMware, Inc. + * Copyright (C) 2018 - 2021 VMware, Inc. * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/Constants.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/Constants.java new file mode 100644 index 0000000..41220f5 --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/Constants.java @@ -0,0 +1,42 @@ +package com.vmware.vcloud.api.utils; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +/** + * Constants related to REST API. + */ +public class Constants { + /** + * Represents a date pattern for {@link java.util.Date} formatting. + */ + public static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXX"; + + public static final String SYSTEM_ORG = "system"; +} diff --git a/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/UrnUtils.java b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/UrnUtils.java new file mode 100644 index 0000000..a71041a --- /dev/null +++ b/vcd-xjc-plugins/src/main/java/com/vmware/vcloud/api/utils/UrnUtils.java @@ -0,0 +1,116 @@ +package com.vmware.vcloud.api.utils; + +/*- + * #%L + * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation + * %% + * Copyright (C) 2018 - 2021 VMware, Inc. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +/** + * A set of utilities for processing URNs + */ +public class UrnUtils { + protected static final int NAMESPACE_IND = 1; + protected static final int TYPE_IND = 2; + private static final int NSS_IND = 3; + protected static final int ID_IND = 4; + + protected static final String URN_DENOTATION = "urn"; + protected static final String URN_SEPARATOR = ":"; + + private static final String NAMESPACE_REGEX = "([a-z0-9][a-z0-9-]{0,31})"; + private static final String TYPE_REGEX = "([^\\/\\s" + URN_SEPARATOR + "]+)"; + private static final String NSS_REGEX = "?([^\\/\\s]*)"; + private static final String UUID_REGEX = + "([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})"; + protected static final Pattern UUID_PATTERN = Pattern.compile(UUID_REGEX); + private static final String VALUE_REGEX = "([\\w-]+)"; + private static final String URN_FORMAT_REGEX = + URN_DENOTATION + URN_SEPARATOR + NAMESPACE_REGEX + URN_SEPARATOR + TYPE_REGEX + + URN_SEPARATOR + NSS_REGEX + URN_SEPARATOR + VALUE_REGEX; + private static final String URN_REGEX = + URN_DENOTATION + URN_SEPARATOR + NAMESPACE_REGEX + URN_SEPARATOR + TYPE_REGEX + + URN_SEPARATOR + NSS_REGEX + URN_SEPARATOR + UUID_REGEX; + private static final Pattern URN_PATTERN = Pattern.compile("^" + URN_REGEX + "$", 0); + private static final Pattern URN_FORMAT_PATTERN = Pattern.compile("^" + URN_FORMAT_REGEX + "$", 0); + + protected static String[] getParts(String vcdId) { + if (StringUtils.isBlank(vcdId)) { + return null; + } + + final Matcher idMatcher = URN_FORMAT_PATTERN.matcher(vcdId); + if (!idMatcher.matches()) { + return null; + } + + return new String[]{ + URN_DENOTATION, idMatcher.group(NAMESPACE_IND), idMatcher.group(TYPE_IND), + idMatcher.group(NSS_IND), idMatcher.group(ID_IND)}; + } + + /** + * Gets entity id from VCD ID. + * + * @param vcdId a VCD ID + * @return the corresponding id or null if the vcd id cannot be parsed + */ + public static String getEntityId(String vcdId) { + final String[] parts = getParts(vcdId); + if (parts == null) { + return null; + } + return parts[UrnUtils.ID_IND]; + } + + + /** + * Checks whether provided href is a valid urn with a UUID value + * @param href + * @return true is href is actually urn + */ + public static boolean isUrn(String href) { + if (StringUtils.isBlank(href)) { + return false; + } + return URN_PATTERN.matcher(href).matches(); + } + + /** + * Checks that the href is in urn format + */ + public static boolean hasValidUrnFormat(String href) { + if (StringUtils.isBlank(href)) { + return false; + } + return URN_FORMAT_PATTERN.matcher(href).matches(); + } +}