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  package org.apache.hadoop.hbase.security.visibility;
19  
20  import java.io.IOException;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.util.ReflectionUtils;
27  
28  /**
29   * Manages singleton instance of {@link VisibilityLabelService}
30   */
31  @InterfaceAudience.Private
32  public class VisibilityLabelServiceManager {
33  
34    private static final Log LOG = LogFactory.getLog(VisibilityLabelServiceManager.class);
35  
36    public static final String VISIBILITY_LABEL_SERVICE_CLASS =
37        "hbase.regionserver.visibility.label.service.class";
38    private static final VisibilityLabelServiceManager INSTANCE = new VisibilityLabelServiceManager();
39  
40    private volatile VisibilityLabelService visibilityLabelService = null;
41    private String vlsClazzName = null;
42  
43    private VisibilityLabelServiceManager() {
44  
45    }
46  
47    public static VisibilityLabelServiceManager getInstance() {
48      return INSTANCE;
49    }
50  
51    /**
52     * @param conf
53     * @return singleton instance of {@link VisibilityLabelService}. The FQCN of the implementation
54     *         class can be specified using "hbase.regionserver.visibility.label.service.class".
55     * @throws IOException When VLS implementation, as specified in conf, can not be loaded.
56     */
57    public VisibilityLabelService getVisibilityLabelService(Configuration conf) throws IOException {
58      String vlsClassName = conf.get(VISIBILITY_LABEL_SERVICE_CLASS,
59          DefaultVisibilityLabelServiceImpl.class.getCanonicalName()).trim();
60      if (this.visibilityLabelService != null) {
61        checkForClusterLevelSingleConf(vlsClassName);
62        return this.visibilityLabelService;
63      }
64      synchronized (this) {
65        if (this.visibilityLabelService != null) {
66          checkForClusterLevelSingleConf(vlsClassName);
67          return this.visibilityLabelService;
68        }
69        this.vlsClazzName = vlsClassName;
70        try {
71          this.visibilityLabelService = (VisibilityLabelService) ReflectionUtils.newInstance(
72              Class.forName(vlsClassName), conf);
73        } catch (ClassNotFoundException e) {
74          throw new IOException(e);
75        }
76        return this.visibilityLabelService;
77      }
78    }
79  
80    private void checkForClusterLevelSingleConf(String vlsClassName) {
81      assert this.vlsClazzName != null;
82      if (!this.vlsClazzName.equals(vlsClassName)) {
83        LOG.warn("Trying to use table specific value for config "
84            + "'hbase.regionserver.visibility.label.service.class' which is not supported."
85            + " Will use the cluster level VisibilityLabelService class " + this.vlsClazzName);
86      }
87    }
88  
89    /**
90     * @return singleton instance of {@link VisibilityLabelService}.
91     * @throws IllegalStateException if this called before initialization of singleton instance.
92     */
93    public VisibilityLabelService getVisibilityLabelService() {
94      // By the time this method is called, the singleton instance of visibilityLabelService should
95      // have been created. And it will be created as getVisibilityLabelService(Configuration conf)
96      // is called from VC#start() and that will be the 1st thing core code do with any CP.
97      if (this.visibilityLabelService == null) {
98        throw new IllegalStateException("VisibilityLabelService not yet instantiated");
99      }
100     return this.visibilityLabelService;
101   }
102 }