View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.rest;
20  
21  import java.io.IOException;
22  
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.client.Admin;
26  import org.apache.hadoop.hbase.client.Table;
27  import org.apache.hadoop.hbase.filter.ParseFilter;
28  import org.apache.hadoop.hbase.security.UserProvider;
29  import org.apache.hadoop.hbase.util.ConnectionCache;
30  import org.apache.hadoop.hbase.util.JvmPauseMonitor;
31  import org.apache.hadoop.security.UserGroupInformation;
32  import org.apache.hadoop.security.authorize.ProxyUsers;
33  import org.apache.log4j.Logger;
34  
35  /**
36   * Singleton class encapsulating global REST servlet state and functions.
37   */
38  @InterfaceAudience.Private
39  public class RESTServlet implements Constants {
40    private static final Logger LOG = Logger.getLogger(RESTServlet.class);
41    private static RESTServlet INSTANCE;
42    private final Configuration conf;
43    private final MetricsREST metrics;
44    private final ConnectionCache connectionCache;
45    private final UserGroupInformation realUser;
46    private final JvmPauseMonitor pauseMonitor;
47  
48    static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval";
49    static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime";
50    static final String HBASE_REST_SUPPORT_PROXYUSER = "hbase.rest.support.proxyuser";
51  
52    UserGroupInformation getRealUser() {
53      return realUser;
54    }
55  
56    /**
57     * @return the RESTServlet singleton instance
58     */
59    public synchronized static RESTServlet getInstance() {
60      assert(INSTANCE != null);
61      return INSTANCE;
62    }
63  
64    /**
65     * @param conf Existing configuration to use in rest servlet
66     * @param userProvider the login user provider
67     * @return the RESTServlet singleton instance
68     * @throws IOException
69     */
70    public synchronized static RESTServlet getInstance(Configuration conf,
71        UserProvider userProvider) throws IOException {
72      if (INSTANCE == null) {
73        INSTANCE = new RESTServlet(conf, userProvider);
74      }
75      return INSTANCE;
76    }
77  
78    public synchronized static void stop() {
79      if (INSTANCE != null) {
80        INSTANCE.shutdown();
81        INSTANCE = null;
82      }
83    }
84  
85    /**
86     * Constructor with existing configuration
87     * @param conf existing configuration
88     * @param userProvider the login user provider
89     * @throws IOException
90     */
91    RESTServlet(final Configuration conf,
92        final UserProvider userProvider) throws IOException {
93      this.realUser = userProvider.getCurrent().getUGI();
94      this.conf = conf;
95      registerCustomFilter(conf);
96  
97      int cleanInterval = conf.getInt(CLEANUP_INTERVAL, 10 * 1000);
98      int maxIdleTime = conf.getInt(MAX_IDLETIME, 10 * 60 * 1000);
99      connectionCache = new ConnectionCache(
100       conf, userProvider, cleanInterval, maxIdleTime);
101     if (supportsProxyuser()) {
102       ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
103     }
104 
105     metrics = new MetricsREST();
106 
107     pauseMonitor = new JvmPauseMonitor(conf, metrics.getSource());
108     pauseMonitor.start();
109   }
110 
111   Admin getAdmin() throws IOException {
112     return connectionCache.getAdmin();
113   }
114 
115   /**
116    * Caller closes the table afterwards.
117    */
118   Table getTable(String tableName) throws IOException {
119     return connectionCache.getTable(tableName);
120   }
121 
122   Configuration getConfiguration() {
123     return conf;
124   }
125 
126   MetricsREST getMetrics() {
127     return metrics;
128   }
129 
130   /**
131    * Helper method to determine if server should
132    * only respond to GET HTTP method requests.
133    * @return boolean for server read-only state
134    */
135   boolean isReadOnly() {
136     return getConfiguration().getBoolean("hbase.rest.readonly", false);
137   }
138 
139   void setEffectiveUser(String effectiveUser) {
140     connectionCache.setEffectiveUser(effectiveUser);
141   }
142 
143   /**
144    * Shutdown any services that need to stop
145    */
146   void shutdown() {
147     if (pauseMonitor != null) pauseMonitor.stop();
148     if (connectionCache != null) connectionCache.shutdown();
149   }
150 
151   boolean supportsProxyuser() {
152     return conf.getBoolean(HBASE_REST_SUPPORT_PROXYUSER, false);
153   }
154 
155   private void registerCustomFilter(Configuration conf) {
156     String[] filterList = conf.getStrings(Constants.CUSTOM_FILTERS);
157     if (filterList != null) {
158       for (String filterClass : filterList) {
159         String[] filterPart = filterClass.split(":");
160         if (filterPart.length != 2) {
161           LOG.warn(
162             "Invalid filter specification " + filterClass + " - skipping");
163         } else {
164           ParseFilter.registerFilter(filterPart[0], filterPart[1]);
165         }
166       }
167     }
168   }
169 }