Issue-id: OCS-9
[msb/apigateway.git] / msb-core / apiroute / apiroute-service / src / main / java / org / openo / msb / wrapper / ApiRouteServiceWrapper.java
1 /**
2  * Copyright 2016 2015-2016 ZTE, Inc. and others. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.openo.msb.wrapper;
17
18 import java.io.File;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.net.URL;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.openo.msb.api.ApiRouteInfo;
28 import org.openo.msb.api.DiscoverInfo;
29 import org.openo.msb.api.RouteServer;
30 import org.openo.msb.api.exception.ExtendedInternalServerErrorException;
31 import org.openo.msb.api.exception.ExtendedNotFoundException;
32 import org.openo.msb.api.exception.ExtendedNotSupportedException;
33 import org.openo.msb.wrapper.util.JedisUtil;
34 import org.openo.msb.wrapper.util.RegExpTestUtil;
35 import org.openo.msb.wrapper.util.RouteUtil;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import redis.clients.jedis.Jedis;
40
41
42
43 /**
44  * @ClassName: ApiRouteServiceWrapper
45  * @Description: TODO(ApiRoute服务类)
46  * @author tanghua10186366
47  * @date 2015年9月25日 上午9:44:04
48  * 
49  */
50 public class ApiRouteServiceWrapper {
51
52     private static final Logger LOGGER = LoggerFactory.getLogger(ApiRouteServiceWrapper.class);
53
54
55     private static ApiRouteServiceWrapper instance = new ApiRouteServiceWrapper();
56
57     private ApiRouteServiceWrapper() {}
58
59     public static ApiRouteServiceWrapper getInstance() {
60         return instance;
61     }
62
63     /**
64      * @Title: getAllApiRouteInstances
65      * @Description: TODO(获取全部服务列表)
66      * @param: @return
67      * @return: ApiRouteInfoBean[]
68      */
69     public ApiRouteInfo[] getAllApiRouteInstances() {
70
71
72         Jedis jedis = null;
73         ApiRouteInfo[] apiRouteList = null;
74         try {
75             jedis = JedisUtil.borrowJedisInstance();
76             if (jedis == null) {
77                 throw new ExtendedInternalServerErrorException(
78                         "fetch from jedis pool failed,null object!");
79             }
80
81             // 获取全部服务列表
82             String routekey =
83                     RouteUtil
84                             .getPrefixedKey("", RouteUtil.APIROUTE, "*", RouteUtil.ROUTE_PATH_INFO);
85             Set<String> routeSet = jedis.keys(routekey);
86             apiRouteList = new ApiRouteInfo[routeSet.size()];
87
88             int i = 0;
89             for (String routePath : routeSet) {
90                 String[] routePathArray = routePath.split(":");
91                 ApiRouteInfo apiRoute =
92                         getApiRouteInstance(routePathArray[3], routePathArray[4], jedis);
93                 apiRouteList[i] = apiRoute;
94                 i++;
95             }
96
97
98         } catch (Exception e) {
99             LOGGER.error("call redis throw exception", e);
100             throw new ExtendedInternalServerErrorException("call redis throw exception:"
101                     + e.getMessage());
102
103         } finally {
104             JedisUtil.returnJedisInstance(jedis);
105         }
106
107         return apiRouteList;
108     }
109
110
111
112     public static boolean checkRedisConnect() {
113
114         Jedis jedis = null;
115         try {
116             jedis = JedisUtil.borrowJedisInstance();
117             if (jedis != null) {
118                 return true;
119             }
120         } catch (Exception e) {
121             LOGGER.error("call redis throw exception", e);
122         } finally {
123             JedisUtil.returnJedisInstance(jedis);
124         }
125
126         return false;
127     }
128
129     /**
130      * @Title: getApiRouteInstance
131      * @Description: TODO(通过服务名+版本号获取单个服务对象信息)
132      * @param: @param serviceName
133      * @param: @param version
134      * @param: @return
135      * @return: ApiRouteInfo
136      */
137     public ApiRouteInfo getApiRouteInstance(String serviceName, String version) {
138
139         if (StringUtils.isBlank(serviceName)) {
140             throw new ExtendedNotSupportedException("serviceName  can't be empty");
141         }
142
143         if (StringUtils.isNotBlank(version)) {
144             if (!RegExpTestUtil.versionRegExpTest(version)) {
145                 throw new ExtendedNotSupportedException("version (" + version
146                         + ") is not a valid  format");
147             }
148         }
149
150
151         ApiRouteInfo apiRouteInfo = null;
152
153         Jedis jedis = null;
154         try {
155             jedis = JedisUtil.borrowJedisInstance();
156             if (jedis == null) {
157                 throw new ExtendedInternalServerErrorException(
158                         "fetch from jedis pool failed,null object!");
159             }
160
161             apiRouteInfo = getApiRouteInstance(serviceName, version, jedis);
162
163
164         } catch (Exception e) {
165             LOGGER.error("call redis throw exception", e);
166             throw new ExtendedInternalServerErrorException("call redis throw exception:"
167                     + e.getMessage());
168
169         } finally {
170             JedisUtil.returnJedisInstance(jedis);
171         }
172
173         if (null == apiRouteInfo) {
174             String errInfo =
175                     "ApiRouteInfo not found: serviceName-" + serviceName + " ,version-" + version;
176             LOGGER.warn(errInfo);
177             throw new ExtendedNotFoundException(errInfo);
178
179         }
180
181         return apiRouteInfo;
182
183     }
184
185     public ApiRouteInfo getApiRouteInstance(String serviceName, String version, Jedis jedis)
186             throws Exception {
187         if ("null".equals(version)) {
188             version = "";
189         }
190
191         ApiRouteInfo apiRouteInfo = null;
192
193
194         // 获取info信息
195         String routekey =
196                 RouteUtil.getPrefixedKey("", RouteUtil.APIROUTE, serviceName, version,
197                         RouteUtil.ROUTE_PATH_INFO);
198         Map<String, String> infomap = jedis.hgetAll(routekey);
199         if (!infomap.isEmpty()) {
200             apiRouteInfo = new ApiRouteInfo();
201             apiRouteInfo.setServiceName(serviceName);
202             apiRouteInfo.setVersion(version);
203             apiRouteInfo.setUrl(infomap.get("url"));
204             apiRouteInfo.setMetricsUrl(infomap.get("metricsUrl"));
205             apiRouteInfo.setApiJson(infomap.get("apijson"));
206             apiRouteInfo.setApiJsonType(infomap.get("apiJsonType"));
207             apiRouteInfo.setControl(infomap.get("control"));
208             apiRouteInfo.setStatus(infomap.get("status"));
209             apiRouteInfo.setVisualRange(infomap.get("visualRange"));
210             apiRouteInfo.setUseOwnUpstream(infomap.get("useOwnUpstream"));
211
212
213             // 获取负载均衡信息
214             String serviceLBkey =
215                     RouteUtil.getPrefixedKey("", RouteUtil.APIROUTE, serviceName, version,
216                             RouteUtil.ROUTE_PATH_LOADBALANCE);
217             Set<String> serviceLBset = jedis.keys(serviceLBkey + ":*");
218             int serverNum = serviceLBset.size();
219             RouteServer[] apiRouteServerList = new RouteServer[serverNum];
220             int i = 0;
221             for (String serviceInfo : serviceLBset) {
222                 Map<String, String> serviceLBmap = jedis.hgetAll(serviceInfo);
223                 RouteServer server = new RouteServer();
224                 server.setIp(serviceLBmap.get("ip"));
225                 server.setPort(serviceLBmap.get("port"));
226                 server.setWeight(Integer.parseInt(serviceLBmap.get("weight")));
227                 apiRouteServerList[i] = server;
228                 i++;
229             }
230
231             apiRouteInfo.setServers(apiRouteServerList);
232
233             // 获取生命周期信息
234
235 //            ApiRouteLifeCycle lifeCycle = new ApiRouteLifeCycle();
236 //            String serviceLifekey =
237 //                    RouteUtil.getPrefixedKey("", RouteUtil.APIROUTE, serviceName, version,
238 //                            RouteUtil.APIROUTE_PATH_LIFE);
239 //            Map<String, String> serviceLifeMap = jedis.hgetAll(serviceLifekey);
240 //
241 //            lifeCycle.setInstallPath(serviceLifeMap.get("path"));
242 //            lifeCycle.setStartScript(serviceLifeMap.get("start"));
243 //            lifeCycle.setStopScript(serviceLifeMap.get("stop"));
244 //
245 //            apiRouteInfo.setLifeCycle(lifeCycle);
246         }
247
248
249         return apiRouteInfo;
250     }
251
252     /**
253      * @Title: updateApiRouteInstance
254      * @Description: TODO(更新单个服务信息)
255      * @param: @param serviceName
256      * @param: @param version
257      * @param: @param apiRouteInfo
258      * @param: @return
259      * @return: ApiRouteInfo
260      */
261     public synchronized ApiRouteInfo updateApiRouteInstance(String serviceName, String version,
262             ApiRouteInfo apiRouteInfo, String serverPort) {
263
264         if ("null".equals(version)) {
265             version = "";
266         }
267         
268         if (StringUtils.isBlank(serviceName)) {
269             throw new ExtendedNotSupportedException("serviceName  can't be empty");
270         }
271
272         if (StringUtils.isNotBlank(version)) {
273             if (!RegExpTestUtil.versionRegExpTest(version)) {
274                 throw new ExtendedNotSupportedException("version (" + version
275                         + ") is not a valid  format");
276             }
277         }
278
279         
280
281
282         try {
283
284
285             if (serviceName.equals(apiRouteInfo.getServiceName())
286                     && version.equals(apiRouteInfo.getVersion())) {
287                 // 删除已存在负载均衡服务器信息
288                 deleteApiRoute(serviceName, version, RouteUtil.ROUTE_PATH_LOADBALANCE + "*",
289                         serverPort);
290
291             } else {
292                 // 如果已修改服务名或者版本号,先删除此服务全部已有信息
293                 deleteApiRoute(serviceName, version, "*", serverPort);
294             }
295
296
297             saveApiRouteInstance(apiRouteInfo, serverPort);
298
299
300         } catch (ExtendedNotSupportedException e) {
301             throw e;
302         } catch (Exception e) {
303             LOGGER.error("update ApiRoute throw exception", e);
304             throw new ExtendedInternalServerErrorException("update apiRouteInfo throw exception"
305                     + e.getMessage());
306
307         }
308
309         return apiRouteInfo;
310
311     }
312
313     /**
314      * @Title updateApiRouteStatus
315      * @Description TODO(更新单个服务状态)
316      * @param serviceName
317      * @param version
318      * @param status
319      * @return
320      * @return RouteResult
321      */
322     public synchronized ApiRouteInfo updateApiRouteStatus(String serviceName, String version,
323             String status) {
324
325         if ("null".equals(version)) {
326             version = "";
327         }
328         
329         if (StringUtils.isBlank(serviceName)) {
330             throw new ExtendedNotSupportedException("serviceName  can't be empty");
331         }
332
333         if (StringUtils.isNotBlank(version)) {
334             if (!RegExpTestUtil.versionRegExpTest(version)) {
335                 throw new ExtendedNotSupportedException("version (" + version
336                         + ") is not a valid  format");
337             }
338         }
339
340         if (!RouteUtil.contain(RouteUtil.statusRangeMatches, status)) {
341             throw new ExtendedNotSupportedException(
342                     "save ApiRouteInfo  Status FAIL:status is wrong,value range:("
343                             + RouteUtil.show(RouteUtil.statusRangeMatches) + ")");
344         }
345
346         ApiRouteInfo new_apiRouteInfo = getApiRouteInstance(serviceName, version);
347
348
349         // 准备info信息
350         String serviceInfokey =
351                 RouteUtil.getPrefixedKey("", RouteUtil.APIROUTE, serviceName, version,
352                         RouteUtil.ROUTE_PATH_INFO);
353         Map<String, String> serviceInfoMap = new HashMap<String, String>();
354         serviceInfoMap.put("status", status);
355
356
357         Jedis jedis = null;
358         try {
359             jedis = JedisUtil.borrowJedisInstance();
360             if (jedis == null) {
361                 throw new Exception("fetch from jedis pool failed,null object!");
362             }
363             // 保存info信息
364             jedis.hmset(serviceInfokey, serviceInfoMap);
365             new_apiRouteInfo.setStatus(status);
366
367
368         } catch (Exception e) {
369             LOGGER.error("update ApiRoute status throw exception", e);
370             throw new ExtendedInternalServerErrorException("update ApiRoute status throw exception"
371                     + e.getMessage());
372
373         } finally {
374             JedisUtil.returnJedisInstance(jedis);
375         }
376
377         return new_apiRouteInfo;
378     }
379
380
381     /**
382      * @Title: saveApiRouteInstance
383      * @Description: TODO(存储单个服务信息)
384      * @param: @param apiRouteInfo
385      * @param: @return
386      * @return: ApiRouteInfo
387      */
388     public synchronized ApiRouteInfo saveApiRouteInstance(ApiRouteInfo apiRouteInfo,
389             String serverPort) {
390
391        
392         
393         if (StringUtils.isBlank(apiRouteInfo.getServiceName())
394                 || apiRouteInfo.getServers().length == 0) {
395             throw new ExtendedNotSupportedException(
396                     "save apiRouteInfo FAIL: Some required fields are empty");
397         }
398
399         if (StringUtils.isNotBlank(apiRouteInfo.getVersion())) {
400             if (!RegExpTestUtil.versionRegExpTest(apiRouteInfo.getVersion())) {
401                 throw new ExtendedNotSupportedException("version (" + apiRouteInfo.getVersion()
402                         + ") is not a valid  format");
403             }
404         }
405
406         if (StringUtils.isNotBlank(apiRouteInfo.getUrl())) {
407             if (!RegExpTestUtil.urlRegExpTest(apiRouteInfo.getUrl())) {
408                 throw new ExtendedNotSupportedException(
409                         "save apiRouteInfo FAIL:url is not a valid format(url must be begin with /)");
410     
411             }
412         }
413
414         if (!RouteUtil.contain(RouteUtil.visualRangeRange, apiRouteInfo.getVisualRange())) {
415             throw new ExtendedNotSupportedException(
416                     "save apiRouteInfo FAIL:VisualRange is wrong,value range:("
417                             + RouteUtil.show(RouteUtil.visualRangeMatches) + ")");
418         }
419
420         if (!RouteUtil.contain(RouteUtil.controlRangeMatches, apiRouteInfo.getControl())) {
421             throw new ExtendedNotSupportedException(
422                     "save apiRouteInfo FAIL:control is wrong,value range:("
423                             + RouteUtil.show(RouteUtil.controlRangeMatches) + ")");
424         }
425
426         if (!RouteUtil.contain(RouteUtil.statusRangeMatches, apiRouteInfo.getStatus())) {
427             throw new ExtendedNotSupportedException(
428                     "save apiRouteInfo FAIL:status is wrong,value range:("
429                             + RouteUtil.show(RouteUtil.statusRangeMatches) + ")");
430         }
431
432         if (!RouteUtil.contain(RouteUtil.useOwnUpstreamRangeMatches, apiRouteInfo.getUseOwnUpstream())) {
433             throw new ExtendedNotSupportedException(
434                     "save apiRouteInfo FAIL:useOwnUpstream is wrong,value range:("
435                             + RouteUtil.show(RouteUtil.useOwnUpstreamRangeMatches) + ")");
436         }
437
438         // 检查服务实例格式
439         RouteServer[] serverList = apiRouteInfo.getServers();
440         for (int i = 0; i < serverList.length; i++) {
441             RouteServer server = serverList[i];
442             if (!RegExpTestUtil.ipRegExpTest(server.getIp())) {
443                 throw new ExtendedNotSupportedException("save apiRouteInfo FAIL:IP("
444                         + server.getIp() + ")is not a valid ip address");
445             }
446
447             if (!RegExpTestUtil.portRegExpTest(server.getPort())) {
448                 throw new ExtendedNotSupportedException("save apiRouteInfo FAIL:Port("
449                         + server.getPort() + ")is not a valid Port address");
450             }
451         }
452
453         // 准备info信息
454         String serviceInfokey =
455                 RouteUtil.getPrefixedKey(serverPort, RouteUtil.APIROUTE,
456                         apiRouteInfo.getServiceName().trim(), apiRouteInfo.getVersion().trim(),
457                         RouteUtil.ROUTE_PATH_INFO);
458         Map<String, String> serviceInfoMap = new HashMap<String, String>();
459         serviceInfoMap.put("url", "/".equals(apiRouteInfo.getUrl().trim()) ? "" : apiRouteInfo
460                 .getUrl().trim());
461         serviceInfoMap.put("apijson", apiRouteInfo.getApiJson());
462         serviceInfoMap.put("apiJsonType", apiRouteInfo.getApiJsonType());
463         serviceInfoMap.put("metricsUrl", apiRouteInfo.getMetricsUrl());
464         serviceInfoMap.put("control", apiRouteInfo.getControl());
465         serviceInfoMap.put("status", apiRouteInfo.getStatus());
466         serviceInfoMap.put("visualRange", apiRouteInfo.getVisualRange());
467         serviceInfoMap.put("useOwnUpstream", apiRouteInfo.getUseOwnUpstream());
468
469         // 准备负载均衡信息
470         String serviceLBkey =
471                 RouteUtil.getPrefixedKey(serverPort, RouteUtil.APIROUTE,
472                         apiRouteInfo.getServiceName(), apiRouteInfo.getVersion(),
473                         RouteUtil.ROUTE_PATH_LOADBALANCE);
474
475
476         Jedis jedis = null;
477         try {
478             jedis = JedisUtil.borrowJedisInstance();
479             if (jedis == null) {
480                 throw new ExtendedInternalServerErrorException(
481                         "fetch from jedis pool failed,null object!");
482             }
483             // 保存info信息
484             jedis.hmset(serviceInfokey, serviceInfoMap);
485
486             // 保存负载均衡信息
487             for (int i = 0; i < serverList.length; i++) {
488                 Map<String, String> servermap = new HashMap<String, String>();
489                 RouteServer server = serverList[i];
490
491                 servermap.put("ip", server.getIp());
492                 servermap.put("port", server.getPort());
493                 servermap.put("weight", Integer.toString(server.getWeight()));
494
495                 jedis.hmset(serviceLBkey + ":server" + (i + 1), servermap);
496             }
497             // 保存生命周期信息
498
499 //            ApiRouteLifeCycle lifeCycle = apiRouteInfo.getLifeCycle();
500 //            if (lifeCycle != null) {
501 //                String serviceLifekey =
502 //                        RouteUtil.getPrefixedKey(serverPort, RouteUtil.APIROUTE,
503 //                                apiRouteInfo.getServiceName(), apiRouteInfo.getVersion(),
504 //                                RouteUtil.APIROUTE_PATH_LIFE);
505 //                Map<String, String> serviceLifeMap = new HashMap<String, String>();
506 //                serviceLifeMap.put("path", lifeCycle.getInstallPath());
507 //                serviceLifeMap.put("start", lifeCycle.getStartScript());
508 //                serviceLifeMap.put("stop", lifeCycle.getStopScript());
509 //                jedis.hmset(serviceLifekey, serviceLifeMap);
510 //            }
511
512
513
514         } catch (Exception e) {
515             LOGGER.error("call redis throw exception", e);
516             throw new ExtendedInternalServerErrorException("call redis throw exception:"
517                     + e.getMessage());
518
519         } finally {
520             JedisUtil.returnJedisInstance(jedis);
521         }
522
523         return apiRouteInfo;
524     }
525
526
527
528     /**
529      * @Title: deleteApiRoute
530      * @Description: TODO(删除单个服务信息)
531      * @param: @param type
532      * @param: @param serviceName
533      * @param: @param version
534      * @param: @param delKey
535      * @param: @return
536      * @return: void
537      */
538     public synchronized void deleteApiRoute(String serviceName, String version, String delKey,
539             String serverPort) {
540
541         if ("null".equals(version)) {
542             version = "";
543         }
544         
545         if (StringUtils.isBlank(serviceName)) {
546             throw new ExtendedNotSupportedException("serviceName  can't be empty");
547         }
548
549         if (StringUtils.isNotBlank(version)) {
550             if (!RegExpTestUtil.versionRegExpTest(version)) {
551                 throw new ExtendedNotSupportedException("version (" + version
552                         + ") is not a valid  format");
553             }
554         }
555
556         
557         Jedis jedis = null;
558         try {
559             jedis = JedisUtil.borrowJedisInstance();
560             if (jedis == null) {
561                 throw new ExtendedInternalServerErrorException(
562                         "fetch from jedis pool failed,null object!");
563             }
564
565             // 获取info信息
566             String routekey =
567                     RouteUtil.getPrefixedKey(serverPort, RouteUtil.APIROUTE, serviceName, version,
568                             delKey);
569             Set<String> infoSet = jedis.keys(routekey);
570
571             if (infoSet.isEmpty()) {
572                 throw new ExtendedNotFoundException("delete ApiRoute FAIL:serviceName-"
573                         + serviceName + ",version:" + version + " not fond ");
574             }
575
576             String[] paths = new String[infoSet.size()];
577
578             // Set-->数组
579             infoSet.toArray(paths);
580
581             jedis.del(paths);
582
583
584         } catch (ExtendedNotFoundException e) {
585             throw e;
586         } catch (Exception e) {
587             LOGGER.error("delete ApiRoute throw exception", e);
588             throw new ExtendedInternalServerErrorException("delete ApiRoute throw exception:"
589                     + e.getMessage());
590         } finally {
591             JedisUtil.returnJedisInstance(jedis);
592         }
593
594
595     }
596
597     /**
598      * @Title: getAllApiDocs
599      * @Description: TODO(获取本地ext\initSwaggerJson目录的全部json文件目录)
600      * @param: @return
601      * @return: String[]
602      */
603     public String[] getAllApiDocs() {
604         URL apiDocsPath = ApiRouteServiceWrapper.class.getResource("/ext/initSwaggerJson");
605         if (apiDocsPath != null) {
606             String path = apiDocsPath.getPath();
607
608             try {
609                 return readfile(path);
610             } catch (FileNotFoundException e) {
611                 // TODO Auto-generated catch block
612                 LOGGER.error("read  ApiDocs Files throw FileNotFoundException", e);
613                 throw new ExtendedInternalServerErrorException("read  ApiDocs Files throw FileNotFoundException:"
614                         + e.getMessage());
615             } catch (IOException e) {
616                 // TODO Auto-generated catch block
617                 LOGGER.error("read  ApiDocs Files throw IOexception", e);
618                 throw new ExtendedInternalServerErrorException("read  ApiDocs Files throw IOexception:"
619                         + e.getMessage());
620             }
621
622         }
623
624
625         return null;
626     }
627
628     /**
629      * 读取某个文件夹下的所有文件
630      */
631     public String[] readfile(String filepath) throws FileNotFoundException, IOException {
632         File file = new File(filepath);
633         if (file.isDirectory()) {
634             String[] filelist = file.list();
635             return filelist;
636         }
637         return null;
638     }
639
640     public String getApiGatewayPort() {
641         // return JedisUtil.serverIp+":"+JedisUtil.serverPort;
642         return System.getenv("APIGATEWAY_EXPOSE_PORT") == null ? String
643                 .valueOf(JedisUtil.serverPort) : System.getenv("APIGATEWAY_EXPOSE_PORT");
644
645     }
646
647     public DiscoverInfo getServiceDiscoverInfo() {
648         return RouteUtil.discoverInfo;
649
650     }
651
652
653 }