1 /*******************************************************************************
2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright © 2021 Orange.
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 *******************************************************************************/
25 package org.onap.dmaap.mr.client.impl;
27 import com.att.nsa.apiClient.credentials.ApiCredential;
28 import com.att.nsa.apiClient.http.HttpException;
29 import com.att.nsa.apiClient.http.HttpObjectNotFoundException;
30 import java.io.IOException;
31 import java.net.MalformedURLException;
32 import java.util.Collection;
34 import java.util.TreeSet;
35 import org.json.JSONArray;
36 import org.json.JSONException;
37 import org.json.JSONObject;
38 import org.onap.dmaap.mr.client.MRIdentityManager;
39 import org.onap.dmaap.mr.client.MRTopicManager;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public class MRMetaClient extends MRBaseClient implements MRTopicManager, MRIdentityManager {
44 private static final String BASE_URI_TOPIC = "/topics";
45 private static final String BASE_URI_APIKEY = "/apiKeys";
47 private static final String PARAM_DESCRIPTION = "description";
48 private static final String PARAM_EMAIL = "email";
50 private static final Logger logger = LoggerFactory.getLogger(MRMetaClient.class);
52 public MRMetaClient(Collection<String> baseUrls) throws MalformedURLException {
57 public Set<String> getTopics() throws IOException {
58 final TreeSet<String> set = new TreeSet<>();
60 final JSONObject topicSet = get(BASE_URI_TOPIC);
61 final JSONArray a = topicSet.getJSONArray("topics");
62 for (int i = 0; i < a.length(); i++) {
63 set.add(a.getString(i));
65 } catch (HttpObjectNotFoundException e) {
66 getLog().warn("No /topics endpoint on service.");
67 logger.error("HttpObjectNotFoundException: ", e);
68 } catch (JSONException e) {
69 getLog().warn("Bad /topics result from service.");
70 logger.error("JSONException: ", e);
71 } catch (HttpException e) {
72 throw new IOException(e);
78 public TopicInfo getTopicMetadata(String topic) throws HttpObjectNotFoundException, IOException {
80 final JSONObject topicData = get(BASE_URI_TOPIC + "/" + MRConstants.escape(topic));
81 return new TopicInfo() {
83 public String getOwner() {
84 return topicData.optString("owner", null);
88 public String getDescription() {
89 return topicData.optString(PARAM_DESCRIPTION, null);
93 public Set<String> getAllowedProducers() {
94 final JSONObject acl = topicData.optJSONObject("writerAcl");
95 if (acl != null && acl.optBoolean("enabled", true)) {
96 return jsonArrayToSet(acl.optJSONArray("users"));
102 public Set<String> getAllowedConsumers() {
103 final JSONObject acl = topicData.optJSONObject("readerAcl");
104 if (acl != null && acl.optBoolean("enabled", true)) {
105 return jsonArrayToSet(acl.optJSONArray("users"));
110 } catch (JSONException e) {
111 throw new IOException(e);
112 } catch (HttpException e) {
113 throw new IOException(e);
118 public void createTopic(String topicName, String topicDescription, int partitionCount, int replicationCount) throws HttpException, IOException {
119 final JSONObject o = new JSONObject();
120 o.put("topicName", topicName);
121 o.put("topicDescription", topicDescription);
122 o.put("partitionCount", partitionCount);
123 o.put("replicationCount", replicationCount);
124 post(BASE_URI_TOPIC + "/create", o, false);
128 public void deleteTopic(String topic) throws HttpException, IOException {
129 delete(BASE_URI_TOPIC + "/" + MRConstants.escape(topic));
133 public boolean isOpenForProducing(String topic) throws HttpObjectNotFoundException, IOException {
134 return null == getAllowedProducers(topic);
138 public Set<String> getAllowedProducers(String topic) throws HttpObjectNotFoundException, IOException {
139 return getTopicMetadata(topic).getAllowedProducers();
143 public void allowProducer(String topic, String apiKey) throws HttpObjectNotFoundException, HttpException, IOException {
144 put(BASE_URI_TOPIC + "/" + MRConstants.escape(topic) + "/producers/" + MRConstants.escape(apiKey), new JSONObject());
148 public void revokeProducer(String topic, String apiKey) throws HttpException, IOException {
149 delete(BASE_URI_TOPIC + "/" + MRConstants.escape(topic) + "/producers/" + MRConstants.escape(apiKey));
153 public boolean isOpenForConsuming(String topic) throws HttpObjectNotFoundException, IOException {
154 return null == getAllowedConsumers(topic);
158 public Set<String> getAllowedConsumers(String topic) throws HttpObjectNotFoundException, IOException {
159 return getTopicMetadata(topic).getAllowedConsumers();
163 public void allowConsumer(String topic, String apiKey) throws HttpObjectNotFoundException, HttpException, IOException {
164 put(BASE_URI_TOPIC + "/" + MRConstants.escape(topic) + "/consumers/" + MRConstants.escape(apiKey), new JSONObject());
168 public void revokeConsumer(String topic, String apiKey) throws HttpException, IOException {
169 delete(BASE_URI_TOPIC + "/" + MRConstants.escape(topic) + "/consumers/" + MRConstants.escape(apiKey));
173 public ApiCredential createApiKey(String email, String description) throws HttpException, MRApiException, IOException {
175 final JSONObject o = new JSONObject();
176 o.put(PARAM_EMAIL, email);
177 o.put(PARAM_DESCRIPTION, description);
178 final JSONObject reply = post(BASE_URI_APIKEY + "/create", o, true);
179 return new ApiCredential(reply.getString("key"), reply.getString("secret"));
180 } catch (JSONException e) {
181 // the response doesn't meet our expectation
182 throw new MRApiException("The API key response is incomplete.", e);
187 public ApiKey getApiKey(String apiKey) throws HttpObjectNotFoundException, HttpException, IOException {
188 final JSONObject keyEntry = get(BASE_URI_APIKEY + "/" + MRConstants.escape(apiKey));
189 if (keyEntry == null) {
193 return new ApiKey() {
195 public String getEmail() {
196 final JSONObject aux = keyEntry.optJSONObject("aux");
198 return aux.optString(PARAM_EMAIL);
204 public String getDescription() {
205 final JSONObject aux = keyEntry.optJSONObject("aux");
207 return aux.optString(PARAM_DESCRIPTION);
215 public void updateCurrentApiKey(String email, String description) throws HttpObjectNotFoundException, HttpException, IOException {
216 final JSONObject o = new JSONObject();
218 o.put(PARAM_EMAIL, email);
220 if (description != null) {
221 o.put(PARAM_DESCRIPTION, description);
223 patch(BASE_URI_APIKEY + "/" + MRConstants.escape(getCurrentApiKey()), o);
227 public void deleteCurrentApiKey() throws HttpException, IOException {
228 delete(BASE_URI_APIKEY + "/" + MRConstants.escape(getCurrentApiKey()));