001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import java.io.IOException; 021import java.net.URI; 022import java.util.ServiceLoader; 023import org.apache.commons.lang3.StringUtils; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.hbase.HConstants; 026import org.apache.hadoop.hbase.security.User; 027import org.apache.hadoop.hbase.util.ReflectionUtils; 028import org.apache.yetus.audience.InterfaceAudience; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap; 033 034/** 035 * The entry point for creating a {@link ConnectionRegistry}. 036 */ 037@InterfaceAudience.Private 038final class ConnectionRegistryFactory { 039 040 private static final Logger LOG = LoggerFactory.getLogger(ConnectionRegistryFactory.class); 041 042 private static final ImmutableMap<String, ConnectionRegistryURIFactory> CREATORS; 043 static { 044 ImmutableMap.Builder<String, ConnectionRegistryURIFactory> builder = ImmutableMap.builder(); 045 for (ConnectionRegistryURIFactory factory : ServiceLoader 046 .load(ConnectionRegistryURIFactory.class)) { 047 builder.put(factory.getScheme().toLowerCase(), factory); 048 } 049 // throw IllegalArgumentException if there are duplicated keys 050 CREATORS = builder.buildOrThrow(); 051 } 052 053 private ConnectionRegistryFactory() { 054 } 055 056 /** 057 * Returns the connection registry implementation to use, for the given connection url 058 * {@code uri}. 059 * <p/> 060 * We use {@link ServiceLoader} to load different implementations, and use the scheme of the given 061 * {@code uri} to select. And if there is no protocol specified, or we can not find a 062 * {@link ConnectionRegistryURIFactory} implementation for the given scheme, we will fallback to 063 * use the old way to create the {@link ConnectionRegistry}. Notice that, if fallback happens, the 064 * specified connection url {@code uri} will not take effect, we will load all the related 065 * configurations from the given Configuration instance {@code conf} 066 */ 067 static ConnectionRegistry create(URI uri, Configuration conf, User user) throws IOException { 068 if (StringUtils.isBlank(uri.getScheme())) { 069 LOG.warn("No scheme specified for {}, fallback to use old way", uri); 070 return create(conf, user); 071 } 072 ConnectionRegistryURIFactory creator = CREATORS.get(uri.getScheme().toLowerCase()); 073 if (creator == null) { 074 LOG.warn("No creator registered for {}, fallback to use old way", uri); 075 return create(conf, user); 076 } 077 return creator.create(uri, conf, user); 078 } 079 080 /** 081 * Returns the connection registry implementation to use. 082 * <p/> 083 * This is used when we do not have a connection url, we will use the old way to load the 084 * connection registry, by checking the 085 * {@literal HConstants#CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY} configuration. 086 */ 087 static ConnectionRegistry create(Configuration conf, User user) { 088 Class<? extends ConnectionRegistry> clazz = 089 conf.getClass(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY, 090 RpcConnectionRegistry.class, ConnectionRegistry.class); 091 return ReflectionUtils.newInstance(clazz, conf, user); 092 } 093}