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.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.client.Admin;
28  import org.apache.hadoop.hbase.client.Table;
29  import org.apache.hadoop.hbase.filter.ParseFilter;
30  import org.apache.hadoop.hbase.security.UserProvider;
31  import org.apache.hadoop.hbase.util.ConnectionCache;
32  import org.apache.hadoop.hbase.util.JvmPauseMonitor;
33  import org.apache.hadoop.security.UserGroupInformation;
34  import org.apache.hadoop.security.authorize.ProxyUsers;
35
36  /**
37   * Singleton class encapsulating global REST servlet state and functions.
38   */
39  @InterfaceAudience.Private
40  public class RESTServlet implements Constants {
41    private static final Log LOG = LogFactory.getLog(RESTServlet.class);
42    private static RESTServlet INSTANCE;
43    private final Configuration conf;
44    private final MetricsREST metrics;
45    private final ConnectionCache connectionCache;
46    private final UserGroupInformation realUser;
47    private final JvmPauseMonitor pauseMonitor;
48
49    static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval";
50    static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime";
51    static final String HBASE_REST_SUPPORT_PROXYUSER = "hbase.rest.support.proxyuser";
52
53    UserGroupInformation getRealUser() {
54      return realUser;
55    }
56
57    /**
58     * @return the RESTServlet singleton instance
59     */
60    public synchronized static RESTServlet getInstance() {
61      assert(INSTANCE != null);
62      return INSTANCE;
63    }
64
65    /**
66     * @param conf Existing configuration to use in rest servlet
67     * @param userProvider the login user provider
68     * @return the RESTServlet singleton instance
69     * @throws IOException
70     */
71    public synchronized static RESTServlet getInstance(Configuration conf,
72        UserProvider userProvider) throws IOException {
73      if (INSTANCE == null) {
74        INSTANCE = new RESTServlet(conf, userProvider);
75      }
76      return INSTANCE;
77    }
78
79    public synchronized static void stop() {
80      if (INSTANCE != null) {
81        INSTANCE.shutdown();
82        INSTANCE = null;
83      }
84    }
85
86    /**
87     * Constructor with existing configuration
88     * @param conf existing configuration
89     * @param userProvider the login user provider
90     * @throws IOException
91     */
92    RESTServlet(final Configuration conf,
93        final UserProvider userProvider) throws IOException {
94      this.realUser = userProvider.getCurrent().getUGI();
95      this.conf = conf;
96      registerCustomFilter(conf);
97
98      int cleanInterval = conf.getInt(CLEANUP_INTERVAL, 10 * 1000);
99      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 }