3c4a7621b208b19566b0d8f1b7b2426d6739cb01
[ccsdk/features.git] / sdnr / wt / data-provider / provider / src / main / java / org / onap / ccsdk / features / sdnr / wt / dataprovider / http / DataTreeHttpServlet.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.dataprovider.http;
23
24 import java.io.BufferedReader;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.UnsupportedEncodingException;
29 import java.net.URLDecoder;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Optional;
33 import java.util.regex.Matcher;
34 import java.util.regex.Pattern;
35 import javax.servlet.ServletException;
36 import javax.servlet.http.HttpServlet;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39 import org.json.JSONObject;
40 import org.onap.ccsdk.features.sdnr.wt.common.database.HtDatabaseClient;
41 import org.onap.ccsdk.features.sdnr.wt.dataprovider.impl.DataTreeProviderImpl;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.Entity;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * @author Michael Dürre
48  *
49  */
50 public class DataTreeHttpServlet extends HttpServlet {
51
52     private static final long serialVersionUID = 1L;
53     private final DataTreeProviderImpl dataTreeProvider;
54     private static final Logger LOG = LoggerFactory.getLogger(DataTreeHttpServlet.class);
55
56     public DataTreeHttpServlet() {
57         super();
58         this.dataTreeProvider = new DataTreeProviderImpl();
59     }
60
61     /**
62      * @param client
63      */
64     public void setDatabaseClient(HtDatabaseClient client) {
65         this.dataTreeProvider.setDatabaseClient(client);
66
67     }
68
69     public static String readPayload(HttpServletRequest request) throws IOException {
70
71         String body = null;
72         StringBuilder stringBuilder = new StringBuilder();
73         BufferedReader bufferedReader = null;
74         IOException toThrow = null;
75         try (InputStream inputStream = request.getInputStream()) {
76
77             if (inputStream != null) {
78                 bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
79                 char[] charBuffer = new char[128];
80                 int bytesRead = -1;
81                 while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
82                     stringBuilder.append(charBuffer, 0, bytesRead);
83                 }
84             } else {
85                 stringBuilder.append("");
86             }
87         } catch (IOException ex) {
88             toThrow = ex;
89         } finally {
90             if (bufferedReader != null) {
91                 try {
92                     bufferedReader.close();
93                 } catch (IOException ex) {
94                     LOG.debug("problem closing reader:", ex);
95                     toThrow = ex;
96                 }
97             }
98         }
99         if (toThrow != null) {
100             throw toThrow;
101         }
102         body = stringBuilder.toString();
103         return body;
104     }
105
106     @Override
107     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
108         final String uri = req.getRequestURI();
109         LOG.debug("GET request for {}", uri);
110         final EntityWithTree e = getEntity(uri);
111         if (e != null) {
112             LOG.info("GET request for {} to e={} with tree={}", uri, e.entity, e.tree);
113             switch (e.entity) {
114                 case Inventoryequipment:
115                     DataTreeObject o = this.dataTreeProvider.readInventoryTree(e.tree, null);
116                     this.doJsonResponse(resp, o);
117                     break;
118                 default:
119                     this.notAvailble(resp);
120                     break;
121             }
122         } else {
123             LOG.debug("unable to find entity for uri {}", uri);
124         }
125     }
126
127     @Override
128     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
129         final String uri = req.getRequestURI();
130         String filter = null;
131         try {
132             final String body = readPayload(req);
133             JSONObject data = new JSONObject(body);
134             if (data.has("query")) {
135                 filter = data.getString("query");
136             }
137
138         } catch (Exception e) {
139             LOG.warn("problem reading payload: {}", e);
140         }
141         LOG.debug("POST request for {}", uri);
142         final EntityWithTree e = getEntity(uri);
143         if (e != null) {
144             switch (e.entity) {
145                 case Inventoryequipment:
146                     DataTreeObject o = this.dataTreeProvider.readInventoryTree(e.tree, filter);
147                     this.doJsonResponse(resp, o);
148                     break;
149                 default:
150                     this.notAvailble(resp);
151                     break;
152             }
153         }
154     }
155
156     /**
157      * @param resp
158      */
159     private void notAvailble(HttpServletResponse resp) {
160         try {
161             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
162         } catch (IOException e) {
163
164         }
165     }
166
167     public static EntityWithTree getEntity(String uri) {
168         final String regex = "^\\/tree\\/read-(.*)-tree\\/?(.*)$";
169         final Pattern pattern = Pattern.compile(regex);
170         final Matcher matcher = pattern.matcher(uri);
171         if (matcher.find() && matcher.groupCount() > 0) {
172             try {
173                 Optional<Entity> oe = Entity.forName(matcher.group(1));
174                 if (oe.isPresent()) {
175                     return new EntityWithTree(oe.get(), matcher.groupCount() > 1 ? matcher.group(2) : null);
176                 } else {
177                     LOG.warn("unable to find entity for name {}", matcher.group(1));
178                 }
179             } catch (Exception e2) {
180                 LOG.warn("unable to parse {} into entity: ", matcher.group(2), e2);
181             }
182         }
183         return null;
184
185     }
186
187     private void doJsonResponse(HttpServletResponse resp, DataTreeObject data) {
188         resp.setHeader("Content-Type", "application/json");
189         try {
190             resp.getWriter().write(data.toJSON());
191         } catch (IOException e) {
192             LOG.warn("problem sending response: ", e);
193         }
194     }
195
196     public static class EntityWithTree {
197         public final Entity entity;
198         public final List<String> tree;
199
200         @Override
201         public String toString() {
202             return "EntityWithTree [entity=" + entity + ", tree=" + tree + "]";
203         }
204
205         /**
206         *
207         * @param e database enttity to access
208         * @param tree tree description
209         *   e.g. nodeA           => tree entry for node-id=nodeA
210         *        nodeA/key0      => tree entry for node-id=nodeA and uuid=key0 and tree-level=0
211         *        nodeA/key0/key1 => tree entry for node-id=nodeA and uuid=key1 and tree-level=1
212         *
213         */
214         public EntityWithTree(Entity e, String tree) {
215             this.entity = e;
216             if (tree != null) {
217                 if (tree.startsWith("/")) {
218                     tree = tree.substring(1);
219                 }
220                 if (tree.endsWith("/")) {
221                     tree = tree.substring(0, tree.length() - 1);
222                 }
223                 String[] tmp = tree.split("\\/");
224                 this.tree = new ArrayList<>();
225                 for (int i = 0; i < tmp.length; i++) {
226                     try {
227                         String s = URLDecoder.decode(tmp[i], "utf-8");
228                         if (s != null && s.length() > 0) {
229                             this.tree.add(s);
230                         }
231                     } catch (UnsupportedEncodingException e1) {
232                         LOG.warn("problem urldecode {}: {}", tmp[i], e);
233                     }
234                 }
235             } else {
236                 this.tree = null;
237             }
238         }
239     }
240 }