| /* |
| * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package org.glassfish.jersey.client; |
| |
| import java.net.URI; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.ws.rs.core.Link; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.UriBuilder; |
| |
| import org.glassfish.jersey.internal.guava.Preconditions; |
| import org.glassfish.jersey.uri.JerseyQueryParamStyle; |
| import org.glassfish.jersey.uri.internal.JerseyUriBuilder; |
| |
| /** |
| * Jersey implementation of {@link javax.ws.rs.client.WebTarget JAX-RS client target} |
| * contract. |
| * |
| * @author Marek Potociar |
| */ |
| public class JerseyWebTarget implements javax.ws.rs.client.WebTarget, Initializable<JerseyWebTarget> { |
| |
| private final ClientConfig config; |
| private final UriBuilder targetUri; |
| |
| /** |
| * Create new web target instance. |
| * |
| * @param uri target URI. |
| * @param parent parent client. |
| */ |
| /*package*/ JerseyWebTarget(String uri, JerseyClient parent) { |
| this(UriBuilder.fromUri(uri), parent.getConfiguration()); |
| } |
| |
| /** |
| * Create new web target instance. |
| * |
| * @param uri target URI. |
| * @param parent parent client. |
| */ |
| /*package*/ JerseyWebTarget(URI uri, JerseyClient parent) { |
| this(UriBuilder.fromUri(uri), parent.getConfiguration()); |
| } |
| |
| /** |
| * Create new web target instance. |
| * |
| * @param uriBuilder builder for the target URI. |
| * @param parent parent client. |
| */ |
| /*package*/ JerseyWebTarget(UriBuilder uriBuilder, JerseyClient parent) { |
| this(uriBuilder.clone(), parent.getConfiguration()); |
| } |
| |
| /** |
| * Create new web target instance. |
| * |
| * @param link link to the target URI. |
| * @param parent parent client. |
| */ |
| /*package*/ JerseyWebTarget(Link link, JerseyClient parent) { |
| // TODO handle relative links |
| this(UriBuilder.fromUri(link.getUri()), parent.getConfiguration()); |
| } |
| |
| /** |
| * Create new web target instance. |
| * |
| * @param uriBuilder builder for the target URI. |
| * @param that original target to copy the internal data from. |
| */ |
| protected JerseyWebTarget(UriBuilder uriBuilder, JerseyWebTarget that) { |
| this(uriBuilder, that.config); |
| } |
| |
| /** |
| * Create new web target instance. |
| * |
| * @param uriBuilder builder for the target URI. |
| * @param clientConfig target configuration. |
| */ |
| protected JerseyWebTarget(UriBuilder uriBuilder, ClientConfig clientConfig) { |
| clientConfig.checkClient(); |
| |
| this.targetUri = uriBuilder; |
| this.config = clientConfig.snapshot(); |
| } |
| |
| @Override |
| public URI getUri() { |
| checkNotClosed(); |
| try { |
| return targetUri.build(); |
| } catch (IllegalArgumentException ex) { |
| throw new IllegalStateException(ex.getMessage(), ex); |
| } |
| } |
| |
| private void checkNotClosed() { |
| config.getClient().checkNotClosed(); |
| } |
| |
| @Override |
| public UriBuilder getUriBuilder() { |
| checkNotClosed(); |
| return targetUri.clone(); |
| } |
| |
| @Override |
| public JerseyWebTarget path(String path) throws NullPointerException { |
| checkNotClosed(); |
| Preconditions.checkNotNull(path, "path is 'null'."); |
| |
| return new JerseyWebTarget(getUriBuilder().path(path), this); |
| } |
| |
| @Override |
| public JerseyWebTarget matrixParam(String name, Object... values) throws NullPointerException { |
| checkNotClosed(); |
| Preconditions.checkNotNull(name, "Matrix parameter name must not be 'null'."); |
| |
| if (values == null || values.length == 0 || (values.length == 1 && values[0] == null)) { |
| return new JerseyWebTarget(getUriBuilder().replaceMatrixParam(name, (Object[]) null), this); |
| } |
| |
| checkForNullValues(name, values); |
| return new JerseyWebTarget(getUriBuilder().matrixParam(name, values), this); |
| } |
| |
| @Override |
| public JerseyWebTarget queryParam(String name, Object... values) throws NullPointerException { |
| checkNotClosed(); |
| UriBuilder uriBuilder = getUriBuilder(); |
| Object queryParamProperty = this.getConfiguration().getProperty(ClientProperties.QUERY_PARAM_STYLE); |
| if (queryParamProperty instanceof JerseyQueryParamStyle && uriBuilder instanceof JerseyUriBuilder) { |
| ((JerseyUriBuilder) uriBuilder).setQueryParamStyle((JerseyQueryParamStyle) queryParamProperty); |
| } |
| return new JerseyWebTarget(JerseyWebTarget.setQueryParam(uriBuilder, name, values), this); |
| } |
| |
| private static UriBuilder setQueryParam(UriBuilder uriBuilder, String name, Object[] values) { |
| if (values == null || values.length == 0 || (values.length == 1 && values[0] == null)) { |
| return uriBuilder.replaceQueryParam(name, (Object[]) null); |
| } |
| |
| checkForNullValues(name, values); |
| return uriBuilder.queryParam(name, values); |
| } |
| |
| private static void checkForNullValues(String name, Object[] values) { |
| Preconditions.checkNotNull(name, "name is 'null'."); |
| |
| List<Integer> indexes = new LinkedList<Integer>(); |
| for (int i = 0; i < values.length; i++) { |
| if (values[i] == null) { |
| indexes.add(i); |
| } |
| } |
| final int failedIndexCount = indexes.size(); |
| if (failedIndexCount > 0) { |
| final String valueTxt; |
| final String indexTxt; |
| if (failedIndexCount == 1) { |
| valueTxt = "value"; |
| indexTxt = "index"; |
| } else { |
| valueTxt = "values"; |
| indexTxt = "indexes"; |
| } |
| |
| throw new NullPointerException( |
| String.format("'null' %s detected for parameter '%s' on %s : %s", |
| valueTxt, name, indexTxt, indexes.toString())); |
| } |
| } |
| |
| @Override |
| public JerseyInvocation.Builder request() { |
| checkNotClosed(); |
| JerseyInvocation.Builder b = new JerseyInvocation.Builder(getUri(), config.snapshot()); |
| return onBuilder(b); |
| } |
| |
| @Override |
| public JerseyInvocation.Builder request(String... acceptedResponseTypes) { |
| checkNotClosed(); |
| JerseyInvocation.Builder b = new JerseyInvocation.Builder(getUri(), config.snapshot()); |
| onBuilder(b).request().accept(acceptedResponseTypes); |
| return b; |
| } |
| |
| @Override |
| public JerseyInvocation.Builder request(MediaType... acceptedResponseTypes) { |
| checkNotClosed(); |
| JerseyInvocation.Builder b = new JerseyInvocation.Builder(getUri(), config.snapshot()); |
| onBuilder(b).request().accept(acceptedResponseTypes); |
| return b; |
| } |
| |
| @Override |
| public JerseyWebTarget resolveTemplate(String name, Object value) throws NullPointerException { |
| return resolveTemplate(name, value, true); |
| } |
| |
| @Override |
| public JerseyWebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath) throws NullPointerException { |
| checkNotClosed(); |
| Preconditions.checkNotNull(name, "name is 'null'."); |
| Preconditions.checkNotNull(value, "value is 'null'."); |
| |
| return new JerseyWebTarget(getUriBuilder().resolveTemplate(name, value, encodeSlashInPath), this); |
| } |
| |
| @Override |
| public JerseyWebTarget resolveTemplateFromEncoded(String name, Object value) |
| throws NullPointerException { |
| checkNotClosed(); |
| Preconditions.checkNotNull(name, "name is 'null'."); |
| Preconditions.checkNotNull(value, "value is 'null'."); |
| |
| return new JerseyWebTarget(getUriBuilder().resolveTemplateFromEncoded(name, value), this); |
| } |
| |
| @Override |
| public JerseyWebTarget resolveTemplates(Map<String, Object> templateValues) throws NullPointerException { |
| return resolveTemplates(templateValues, true); |
| } |
| |
| @Override |
| public JerseyWebTarget resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath) |
| throws NullPointerException { |
| checkNotClosed(); |
| checkTemplateValues(templateValues); |
| |
| if (templateValues.isEmpty()) { |
| return this; |
| } else { |
| return new JerseyWebTarget(getUriBuilder().resolveTemplates(templateValues, encodeSlashInPath), this); |
| } |
| } |
| |
| @Override |
| public JerseyWebTarget resolveTemplatesFromEncoded(Map<String, Object> templateValues) |
| throws NullPointerException { |
| checkNotClosed(); |
| checkTemplateValues(templateValues); |
| |
| if (templateValues.isEmpty()) { |
| return this; |
| } else { |
| return new JerseyWebTarget(getUriBuilder().resolveTemplatesFromEncoded(templateValues), this); |
| } |
| } |
| |
| /** |
| * Check template values for {@code null} values. Throws {@code NullPointerException} if the name-value map or any of the |
| * names or encoded values in the map is {@code null}. |
| * |
| * @param templateValues map to check. |
| * @throws NullPointerException if the name-value map or any of the names or encoded values in the map |
| * is {@code null}. |
| */ |
| private void checkTemplateValues(final Map<String, Object> templateValues) throws NullPointerException { |
| Preconditions.checkNotNull(templateValues, "templateValues is 'null'."); |
| |
| for (final Map.Entry entry : templateValues.entrySet()) { |
| Preconditions.checkNotNull(entry.getKey(), "name is 'null'."); |
| Preconditions.checkNotNull(entry.getValue(), "value is 'null'."); |
| } |
| } |
| |
| @Override |
| public JerseyWebTarget register(Class<?> providerClass) { |
| checkNotClosed(); |
| config.register(providerClass); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Object provider) { |
| checkNotClosed(); |
| config.register(provider); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Class<?> providerClass, int bindingPriority) { |
| checkNotClosed(); |
| config.register(providerClass, bindingPriority); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Class<?> providerClass, Class<?>... contracts) { |
| checkNotClosed(); |
| config.register(providerClass, contracts); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Class<?> providerClass, Map<Class<?>, Integer> contracts) { |
| checkNotClosed(); |
| config.register(providerClass, contracts); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Object provider, int bindingPriority) { |
| checkNotClosed(); |
| config.register(provider, bindingPriority); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Object provider, Class<?>... contracts) { |
| checkNotClosed(); |
| config.register(provider, contracts); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget register(Object provider, Map<Class<?>, Integer> contracts) { |
| checkNotClosed(); |
| config.register(provider, contracts); |
| return this; |
| } |
| |
| @Override |
| public JerseyWebTarget property(String name, Object value) { |
| checkNotClosed(); |
| config.property(name, value); |
| return this; |
| } |
| |
| @Override |
| public ClientConfig getConfiguration() { |
| checkNotClosed(); |
| return config.getConfiguration(); |
| } |
| |
| @Override |
| public JerseyWebTarget preInitialize() { |
| config.preInitialize(); |
| return this; |
| } |
| |
| @Override |
| public String toString() { |
| return "JerseyWebTarget { " + targetUri.toTemplate() + " }"; |
| } |
| |
| private static JerseyInvocation.Builder onBuilder(JerseyInvocation.Builder builder) { |
| new InvocationBuilderListenerStage(builder.request().getInjectionManager()).invokeListener(builder); |
| return builder; |
| } |
| } |