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 */ 018 019package org.apache.hadoop.hbase.rest; 020 021import java.io.IOException; 022 023import org.apache.hadoop.conf.Configuration; 024import org.apache.yetus.audience.InterfaceAudience; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027import org.apache.hadoop.hbase.client.Admin; 028import org.apache.hadoop.hbase.client.Table; 029import org.apache.hadoop.hbase.filter.ParseFilter; 030import org.apache.hadoop.hbase.security.UserProvider; 031import org.apache.hadoop.hbase.util.ConnectionCache; 032import org.apache.hadoop.hbase.util.JvmPauseMonitor; 033import org.apache.hadoop.security.UserGroupInformation; 034import org.apache.hadoop.security.authorize.ProxyUsers; 035 036/** 037 * Singleton class encapsulating global REST servlet state and functions. 038 */ 039@InterfaceAudience.Private 040public class RESTServlet implements Constants { 041 private static final Logger LOG = LoggerFactory.getLogger(RESTServlet.class); 042 private static RESTServlet INSTANCE; 043 private final Configuration conf; 044 private final MetricsREST metrics; 045 private final ConnectionCache connectionCache; 046 private final UserGroupInformation realUser; 047 private final JvmPauseMonitor pauseMonitor; 048 049 static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval"; 050 static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime"; 051 static final String HBASE_REST_SUPPORT_PROXYUSER = "hbase.rest.support.proxyuser"; 052 053 UserGroupInformation getRealUser() { 054 return realUser; 055 } 056 057 /** 058 * @return the RESTServlet singleton instance 059 */ 060 public synchronized static RESTServlet getInstance() { 061 assert(INSTANCE != null); 062 return INSTANCE; 063 } 064 065 /** 066 * @param conf Existing configuration to use in rest servlet 067 * @param userProvider the login user provider 068 * @return the RESTServlet singleton instance 069 * @throws IOException 070 */ 071 public synchronized static RESTServlet getInstance(Configuration conf, 072 UserProvider userProvider) throws IOException { 073 if (INSTANCE == null) { 074 INSTANCE = new RESTServlet(conf, userProvider); 075 } 076 return INSTANCE; 077 } 078 079 public synchronized static void stop() { 080 if (INSTANCE != null) { 081 INSTANCE.shutdown(); 082 INSTANCE = null; 083 } 084 } 085 086 /** 087 * Constructor with existing configuration 088 * @param conf existing configuration 089 * @param userProvider the login user provider 090 * @throws IOException 091 */ 092 RESTServlet(final Configuration conf, 093 final UserProvider userProvider) throws IOException { 094 this.realUser = userProvider.getCurrent().getUGI(); 095 this.conf = conf; 096 registerCustomFilter(conf); 097 098 int cleanInterval = conf.getInt(CLEANUP_INTERVAL, 10 * 1000); 099 int maxIdleTime = conf.getInt(MAX_IDLETIME, 10 * 60 * 1000); 100 connectionCache = new ConnectionCache( 101 conf, userProvider, cleanInterval, maxIdleTime); 102 if (supportsProxyuser()) { 103 ProxyUsers.refreshSuperUserGroupsConfiguration(conf); 104 } 105 106 metrics = new MetricsREST(); 107 108 pauseMonitor = new JvmPauseMonitor(conf, metrics.getSource()); 109 pauseMonitor.start(); 110 } 111 112 Admin getAdmin() throws IOException { 113 return connectionCache.getAdmin(); 114 } 115 116 /** 117 * Caller closes the table afterwards. 118 */ 119 Table getTable(String tableName) throws IOException { 120 return connectionCache.getTable(tableName); 121 } 122 123 Configuration getConfiguration() { 124 return conf; 125 } 126 127 MetricsREST getMetrics() { 128 return metrics; 129 } 130 131 /** 132 * Helper method to determine if server should 133 * only respond to GET HTTP method requests. 134 * @return boolean for server read-only state 135 */ 136 boolean isReadOnly() { 137 return getConfiguration().getBoolean("hbase.rest.readonly", false); 138 } 139 140 void setEffectiveUser(String effectiveUser) { 141 connectionCache.setEffectiveUser(effectiveUser); 142 } 143 144 /** 145 * Shutdown any services that need to stop 146 */ 147 void shutdown() { 148 if (pauseMonitor != null) pauseMonitor.stop(); 149 if (connectionCache != null) connectionCache.shutdown(); 150 } 151 152 boolean supportsProxyuser() { 153 return conf.getBoolean(HBASE_REST_SUPPORT_PROXYUSER, false); 154 } 155 156 private void registerCustomFilter(Configuration conf) { 157 String[] filterList = conf.getStrings(Constants.CUSTOM_FILTERS); 158 if (filterList != null) { 159 for (String filterClass : filterList) { 160 String[] filterPart = filterClass.split(":"); 161 if (filterPart.length != 2) { 162 LOG.warn( 163 "Invalid filter specification " + filterClass + " - skipping"); 164 } else { 165 ParseFilter.registerFilter(filterPart[0], filterPart[1]); 166 } 167 } 168 } 169 } 170}