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