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.security.UserGroupInformation;
31  import org.apache.hadoop.security.authorize.ProxyUsers;
32  import org.apache.log4j.Logger;
33  
34  /**
35   * Singleton class encapsulating global REST servlet state and functions.
36   */
37  @InterfaceAudience.Private
38  public class RESTServlet implements Constants {
39    private static final Logger LOG = Logger.getLogger(RESTServlet.class);
40    private static RESTServlet INSTANCE;
41    private final Configuration conf;
42    private final MetricsREST metrics = new MetricsREST();
43    private final ConnectionCache connectionCache;
44    private final UserGroupInformation realUser;
45  
46    static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval";
47    static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime";
48    static final String HBASE_REST_SUPPORT_PROXYUSER = "hbase.rest.support.proxyuser";
49  
50    UserGroupInformation getRealUser() {
51      return realUser;
52    }
53  
54    /**
55     * @return the RESTServlet singleton instance
56     */
57    public synchronized static RESTServlet getInstance() {
58      assert(INSTANCE != null);
59      return INSTANCE;
60    }
61  
62    /**
63     * @param conf Existing configuration to use in rest servlet
64     * @param userProvider the login user provider
65     * @return the RESTServlet singleton instance
66     * @throws IOException
67     */
68    public synchronized static RESTServlet getInstance(Configuration conf,
69        UserProvider userProvider) throws IOException {
70      if (INSTANCE == null) {
71        INSTANCE = new RESTServlet(conf, userProvider);
72      }
73      return INSTANCE;
74    }
75  
76    public synchronized static void stop() {
77      if (INSTANCE != null) {
78        INSTANCE.shutdown();
79        INSTANCE = null;
80      }
81    }
82  
83    /**
84     * Constructor with existing configuration
85     * @param conf existing configuration
86     * @param userProvider the login user provider
87     * @throws IOException
88     */
89    RESTServlet(final Configuration conf,
90        final UserProvider userProvider) throws IOException {
91      this.realUser = userProvider.getCurrent().getUGI();
92      this.conf = conf;
93      registerCustomFilter(conf);
94  
95      int cleanInterval = conf.getInt(CLEANUP_INTERVAL, 10 * 1000);
96      int maxIdleTime = conf.getInt(MAX_IDLETIME, 10 * 60 * 1000);
97      connectionCache = new ConnectionCache(
98        conf, userProvider, cleanInterval, maxIdleTime);
99      if (supportsProxyuser()) {
100       ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
101     }
102   }
103 
104   Admin getAdmin() throws IOException {
105     return connectionCache.getAdmin();
106   }
107 
108   /**
109    * Caller closes the table afterwards.
110    */
111   Table getTable(String tableName) throws IOException {
112     return connectionCache.getTable(tableName);
113   }
114 
115   Configuration getConfiguration() {
116     return conf;
117   }
118 
119   MetricsREST getMetrics() {
120     return metrics;
121   }
122 
123   /**
124    * Helper method to determine if server should
125    * only respond to GET HTTP method requests.
126    * @return boolean for server read-only state
127    */
128   boolean isReadOnly() {
129     return getConfiguration().getBoolean("hbase.rest.readonly", false);
130   }
131 
132   void setEffectiveUser(String effectiveUser) {
133     connectionCache.setEffectiveUser(effectiveUser);
134   }
135 
136   /**
137    * Shutdown any services that need to stop
138    */
139   void shutdown() {
140     if (connectionCache != null) connectionCache.shutdown();
141   }
142 
143   boolean supportsProxyuser() {
144     return conf.getBoolean(HBASE_REST_SUPPORT_PROXYUSER, false);
145   }
146 
147   private void registerCustomFilter(Configuration conf) {
148     String[] filterList = conf.getStrings(Constants.CUSTOM_FILTERS);
149     if (filterList != null) {
150       for (String filterClass : filterList) {
151         String[] filterPart = filterClass.split(":");
152         if (filterPart.length != 2) {
153           LOG.warn(
154             "Invalid filter specification " + filterClass + " - skipping");
155         } else {
156           ParseFilter.registerFilter(filterPart[0], filterPart[1]);
157         }
158       }
159     }
160   }
161 }