All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.pulsar.common.net.ServiceURI Maven / Gradle / Ivy

/*
 * 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.pulsar.common.net;


import static org.apache.pulsar.shade.com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import org.apache.pulsar.shade.com.google.common.base.CharMatcher;
import org.apache.pulsar.shade.com.google.common.base.Splitter;
import org.apache.pulsar.shade.com.google.common.base.Strings;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.pulsar.shade.org.apache.commons.lang.StringUtils;

/**
 * ServiceURI represents service uri within pulsar cluster.
 *
 * 

This file is based on * {@link https://github.com/apache/bookkeeper/blob/master/bookkeeper-common/src/main/java/org/apache/bookkeeper/common/net/ServiceURI.java} */ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter @EqualsAndHashCode public class ServiceURI { private static final String BINARY_SERVICE = "pulsar"; private static final String HTTP_SERVICE = "http"; private static final String HTTPS_SERVICE = "https"; private static final String SSL_SERVICE = "ssl"; private static final int BINARY_PORT = 6650; private static final int BINARY_TLS_PORT = 6651; private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; /** * Create a service uri instance from a uri string. * * @param uriStr service uri string * @return a service uri instance * @throws NullPointerExceptionFieldParser if {@code uriStr} is null * @throws IllegalArgumentException if the given string violates RFC 2396 */ public static ServiceURI create(String uriStr) { requireNonNull(uriStr, "service uri string is null"); if (uriStr.contains("[") && uriStr.contains("]")) { // deal with ipv6 address Splitter splitter = Splitter.on(CharMatcher.anyOf(",;")); List hosts = splitter.splitToList(uriStr); if (hosts.size() > 1) { // deal with multi ipv6 hosts String firstHost = hosts.get(0); String lastHost = hosts.get(hosts.size() - 1); boolean hasPath = lastHost.contains("/"); String path = hasPath ? lastHost.substring(lastHost.indexOf("/")) : ""; firstHost += path; URI uri = URI.create(firstHost); ServiceURI serviceURI = create(uri); List multiHosts = new ArrayList<>(); multiHosts.add(serviceURI.getServiceHosts()[0]); multiHosts.addAll(hosts.subList(1, hosts.size())); multiHosts = multiHosts .stream() .map(host -> validateHostName(serviceURI.getServiceName(), serviceURI.getServiceInfos(), host)) .collect(Collectors.toList()); return new ServiceURI( serviceURI.getServiceName(), serviceURI.getServiceInfos(), serviceURI.getServiceUser(), multiHosts.toArray(new String[multiHosts.size()]), serviceURI.getServicePath(), serviceURI.getUri()); } } // a service uri first should be a valid java.net.URI URI uri = URI.create(uriStr); return create(uri); } /** * Create a service uri instance from a {@link URI} instance. * * @param uri {@link URI} instance * @return a service uri instance * @throws NullPointerException if {@code uriStr} is null * @throws IllegalArgumentException if the given string violates RFC 2396 */ public static ServiceURI create(URI uri) { requireNonNull(uri, "service uri instance is null"); String serviceName; final String[] serviceInfos; String scheme = uri.getScheme(); if (null != scheme) { scheme = scheme.toLowerCase(); final String serviceSep = "+"; String[] schemeParts = StringUtils.split(scheme, serviceSep); serviceName = schemeParts[0]; serviceInfos = new String[schemeParts.length - 1]; System.arraycopy(schemeParts, 1, serviceInfos, 0, serviceInfos.length); } else { serviceName = null; serviceInfos = new String[0]; } String userAndHostInformation = uri.getAuthority(); checkArgument(!Strings.isNullOrEmpty(userAndHostInformation), "authority component is missing in service uri : " + uri); String serviceUser; List serviceHosts; int atIndex = userAndHostInformation.indexOf('@'); Splitter splitter = Splitter.on(CharMatcher.anyOf(",;")); if (atIndex > 0) { serviceUser = userAndHostInformation.substring(0, atIndex); serviceHosts = splitter.splitToList(userAndHostInformation.substring(atIndex + 1)); } else { serviceUser = null; serviceHosts = splitter.splitToList(userAndHostInformation); } serviceHosts = serviceHosts .stream() .map(host -> validateHostName(serviceName, serviceInfos, host)) .collect(Collectors.toList()); String servicePath = uri.getPath(); checkArgument(null != servicePath, "service path component is missing in service uri : " + uri); return new ServiceURI( serviceName, serviceInfos, serviceUser, serviceHosts.toArray(new String[serviceHosts.size()]), servicePath, uri); } private static String validateHostName(String serviceName, String[] serviceInfos, String hostname) { URI uri = null; try { uri = URI.create("dummyscheme://" + hostname); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid hostname : " + hostname); } String host = uri.getHost(); if (host == null) { throw new IllegalArgumentException("Invalid hostname : " + hostname); } int port = uri.getPort(); if (port == -1) { port = getServicePort(serviceName, serviceInfos); } return host + ":" + port; } private final String serviceName; private final String[] serviceInfos; private final String serviceUser; private final String[] serviceHosts; private final String servicePath; private final URI uri; public String[] getServiceInfos() { return serviceInfos; } public String[] getServiceHosts() { return serviceHosts; } public String getServiceScheme() { if (null == serviceName) { return null; } else { if (serviceInfos.length == 0) { return serviceName; } else { return serviceName + "+" + StringUtils.join(serviceInfos, '+'); } } } private static int getServicePort(String serviceName, String[] serviceInfos) { int port; switch (serviceName.toLowerCase()) { case BINARY_SERVICE: if (serviceInfos.length == 0) { port = BINARY_PORT; } else if (serviceInfos.length == 1 && serviceInfos[0].equalsIgnoreCase(SSL_SERVICE)) { port = BINARY_TLS_PORT; } else { throw new IllegalArgumentException("Invalid pulsar service : " + serviceName + "+" + Arrays.toString(serviceInfos)); } break; case HTTP_SERVICE: port = HTTP_PORT; break; case HTTPS_SERVICE: port = HTTPS_PORT; break; default: throw new IllegalArgumentException("Invalid pulsar service : " + serviceName); } return port; } /** * Create a new URI from the service URI which only specifies one of the hosts. * @return a pulsar service URI with a single host specified */ public String selectOne() { StringBuilder sb = new StringBuilder(); if (serviceName != null) { sb.append(serviceName); for (int i = 0; i < serviceInfos.length; i++) { sb.append('+').append(serviceInfos[i]); } sb.append("://"); } if (serviceUser != null) { sb.append(serviceUser).append('@'); } int hostIndex = ThreadLocalRandom.current().nextInt(serviceHosts.length); sb.append(serviceHosts[hostIndex]); return sb.append(servicePath).toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy