1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.ServiceLoader;
28
29
30
31
32
33 public class CompatibilitySingletonFactory extends CompatibilityFactory {
34 public static enum SingletonStorage {
35 INSTANCE;
36 private final Object lock = new Object();
37 private final Map<Class, Object> instances = new HashMap<Class, Object>();
38 }
39 private static final Log LOG = LogFactory.getLog(CompatibilitySingletonFactory.class);
40
41
42
43
44 protected CompatibilitySingletonFactory() { }
45
46
47
48
49
50
51 @SuppressWarnings("unchecked")
52 public static <T> T getInstance(Class<T> klass) {
53 synchronized (SingletonStorage.INSTANCE.lock) {
54 T instance = (T) SingletonStorage.INSTANCE.instances.get(klass);
55 if (instance == null) {
56 try {
57 ServiceLoader<T> loader = ServiceLoader.load(klass);
58 Iterator<T> it = loader.iterator();
59 instance = it.next();
60 if (it.hasNext()) {
61 StringBuilder msg = new StringBuilder();
62 msg.append("ServiceLoader provided more than one implementation for class: ")
63 .append(klass)
64 .append(", using implementation: ").append(instance.getClass())
65 .append(", other implementations: {");
66 while (it.hasNext()) {
67 msg.append(it.next()).append(" ");
68 }
69 msg.append("}");
70 LOG.warn(msg);
71 }
72 } catch (Exception e) {
73 throw new RuntimeException(createExceptionString(klass), e);
74 } catch (Error e) {
75 throw new RuntimeException(createExceptionString(klass), e);
76 }
77
78
79 if (instance == null) {
80 throw new RuntimeException(createExceptionString(klass));
81 }
82 SingletonStorage.INSTANCE.instances.put(klass, instance);
83 }
84 return instance;
85 }
86
87 }
88 }