1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.common.keymaster.client.zookeeper;
20
21 import com.fasterxml.jackson.databind.json.JsonMapper;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.UUID;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.curator.framework.CuratorFramework;
27 import org.apache.syncope.common.keymaster.client.api.KeymasterException;
28 import org.apache.syncope.common.keymaster.client.api.ServiceOps;
29 import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
30 import org.apache.zookeeper.CreateMode;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Autowired;
34
35
36
37
38 public class ZookeeperServiceOps implements ServiceOps {
39
40 protected static final Logger LOG = LoggerFactory.getLogger(ServiceOps.class);
41
42 protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
43
44 protected static final String SERVICE_PATH = "/services";
45
46 @Autowired
47 protected CuratorFramework client;
48
49 protected static String buildServicePath(final NetworkService.Type serviceType, final String... parts) {
50 String prefix = SERVICE_PATH + '/' + serviceType.name();
51 String suffix = StringUtils.EMPTY;
52 if (parts != null && parts.length > 0) {
53 suffix = '/' + String.join("/", parts);
54 }
55 return prefix + suffix;
56 }
57
58 @Override
59 public void register(final NetworkService service) {
60 String id = UUID.randomUUID().toString();
61 try {
62 unregister(service);
63
64 if (client.checkExists().forPath(buildServicePath(service.getType(), id)) == null) {
65 client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).
66 forPath(buildServicePath(service.getType(), id));
67 }
68
69 client.setData().forPath(
70 buildServicePath(service.getType(), id), MAPPER.writeValueAsBytes(service));
71 } catch (Exception e) {
72 LOG.error("While writing {}", buildServicePath(service.getType(), id), e);
73 throw new KeymasterException(e);
74 }
75 }
76
77 @Override
78 public void unregister(final NetworkService service) {
79 try {
80 if (client.checkExists().forPath(buildServicePath(service.getType())) != null) {
81 client.getChildren().forPath(buildServicePath(service.getType())).stream().
82 filter(child -> {
83 try {
84 return MAPPER.readValue(client.getData().forPath(
85 buildServicePath(service.getType(), child)), NetworkService.class).
86 equals(service);
87 } catch (Exception e) {
88 LOG.error("While deregistering {}", service, e);
89 throw new KeymasterException(e);
90 }
91 }).
92 findFirst().ifPresent(child -> {
93 try {
94 client.delete().forPath(buildServicePath(service.getType(), child));
95 } catch (Exception e) {
96 LOG.error("While deregistering {}", service, e);
97 throw new KeymasterException(e);
98 }
99 });
100 }
101 } catch (KeymasterException e) {
102 throw e;
103 } catch (Exception e) {
104 throw new KeymasterException(e);
105 }
106 }
107
108 @Override
109 public List<NetworkService> list(final NetworkService.Type serviceType) {
110 try {
111 if (client.checkExists().forPath(buildServicePath(serviceType)) == null) {
112 client.create().creatingParentContainersIfNeeded().forPath(buildServicePath(serviceType));
113 }
114
115 List<NetworkService> list = new ArrayList<>();
116 for (String child : client.getChildren().forPath(buildServicePath(serviceType))) {
117 list.add(MAPPER.readValue(client.getData().forPath(buildServicePath(serviceType, child)),
118 NetworkService.class));
119 }
120
121 return list;
122 } catch (Exception e) {
123 throw new KeymasterException(e);
124 }
125 }
126
127 @Override
128 public NetworkService get(final NetworkService.Type serviceType) {
129 List<NetworkService> list = list(serviceType);
130 if (list.isEmpty()) {
131 throw new KeymasterException("No registered services for type " + serviceType);
132 }
133
134
135 return list.get(0);
136 }
137 }