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