##### Coverage Report - com.ctrip.framework.apollo.portal.service.NamespaceService

Classes in this File | Line Coverage | Branch Coverage | Complexity
NamespaceService |
63% | 63/100
62% | 20/32
| 3.6666666666666665;3.667

1 |  |
     package com.ctrip.framework.apollo.portal.service;
2 |  |
3 |  |
     import com.google.gson.Gson;
4 |  |
5 |  |
     import com.ctrip.framework.apollo.common.entity.AppNamespace;
6 |  |
     import com.ctrip.framework.apollo.common.utils.BeanUtils;
7 |  |
     import com.ctrip.framework.apollo.common.utils.ExceptionUtils;
8 |  |
     import com.ctrip.framework.apollo.core.ConfigConsts;
9 |  |
     import com.ctrip.framework.apollo.core.dto.AppNamespaceDTO;
10 |  |
     import com.ctrip.framework.apollo.core.dto.ItemDTO;
11 |  |
     import com.ctrip.framework.apollo.core.dto.NamespaceDTO;
12 |  |
     import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
13 |  |
     import com.ctrip.framework.apollo.core.enums.Env;
14 |  |
     import com.ctrip.framework.apollo.core.exception.BadRequestException;
15 |  |
     import com.ctrip.framework.apollo.core.exception.ServiceException;
16 |  |
     import com.ctrip.framework.apollo.core.utils.StringUtils;
17 |  |
     import com.ctrip.framework.apollo.portal.PortalSettings;
18 |  |
     import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
19 |  |
     import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
20 |  |
     import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
21 |  |
     import com.ctrip.framework.apollo.portal.repository.AppNamespaceRepository;
22 |  |
23 |  |
     import org.slf4j.Logger;
24 |  |
     import org.slf4j.LoggerFactory;
25 |  |
     import org.springframework.beans.factory.annotation.Autowired;
26 |  |
     import org.springframework.http.HttpStatus;
27 |  |
     import org.springframework.stereotype.Service;
28 |  |
     import org.springframework.transaction.annotation.Transactional;
29 |  |
     import org.springframework.web.client.HttpClientErrorException;
30 |  |
     import org.springframework.web.client.HttpStatusCodeException;
31 |  |
32 |  |
     import java.util.Collections;
33 |  |
     import java.util.HashMap;
34 |  |
     import java.util.LinkedList;
35 |  |
     import java.util.List;
36 |  |
     import java.util.Map;
37 |  |
     import java.util.Objects;
38 |  |
39 |  |
     @Service
40 | 2 |
     public class NamespaceService {
41 |  |
42 | 2 |
       private Logger logger = LoggerFactory.getLogger(NamespaceService.class);
43 |  |
44 |  |
       @Autowired
45 |  |
       private UserInfoHolder userInfoHolder;
46 |  |
       @Autowired
47 |  |
       private AdminServiceAPI.ItemAPI itemAPI;
48 |  |
       @Autowired
49 |  |
       private AdminServiceAPI.ReleaseAPI releaseAPI;
50 |  |
       @Autowired
51 |  |
       private AdminServiceAPI.NamespaceAPI namespaceAPI;
52 |  |
       @Autowired
53 |  |
       private PortalSettings portalSettings;
54 |  |
       @Autowired
55 |  |
       private AppNamespaceRepository appNamespaceRepository;
56 |  |
       @Autowired
57 |  |
       private RoleInitializationService roleInitializationService;
58 |  |
59 | 2 |
       private Gson gson = new Gson();
60 |  |
61 |  |
62 |  |
       public List<AppNamespace> findPublicAppNamespaces() {
63 | 0 |
         return appNamespaceRepository.findByNameNot(ConfigConsts.NAMESPACE_APPLICATION);
64 |  |
       }
65 |  |
66 |  |
       public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {
67 | 0 |
         if (StringUtils.isEmpty(namespace.getDataChangeCreatedBy())) {
68 | 0 |
           namespace.setDataChangeCreatedBy(userInfoHolder.getUser().getUserId());
69 |  |
         }
70 | 0 |
         namespace.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());
71 | 0 |
         NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace);
72 |  |
73 | 0 |
         roleInitializationService.initNamespaceRoles(namespace.getAppId(), namespace.getNamespaceName());
74 | 0 |
         return createdNamespace;
75 |  |
       }
76 |  |
77 |  |
       @Transactional
78 |  |
       public void createDefaultAppNamespace(String appId) {
79 | 0 |
         if (!isAppNamespaceNameUnique(appId, appId)) {
80 | 0 |
           throw new ServiceException("appnamespace not unique");
81 |  |
         }
82 | 0 |
         AppNamespace appNs = new AppNamespace();
83 | 0 |
         appNs.setAppId(appId);
84 | 0 |
         appNs.setName(ConfigConsts.NAMESPACE_APPLICATION);
85 | 0 |
         appNs.setComment("default app namespace");
86 |  |
87 | 0 |
         String userId = userInfoHolder.getUser().getUserId();
88 | 0 |
         appNs.setDataChangeCreatedBy(userId);
89 | 0 |
         appNs.setDataChangeLastModifiedBy(userId);
90 | 0 |
         appNamespaceRepository.save(appNs);
91 | 0 |
       }
92 |  |
93 |  |
       public boolean isAppNamespaceNameUnique(String appId, String namespaceName) {
94 | 0 |
         Objects.requireNonNull(appId, "AppId must not be null");
95 | 0 |
         Objects.requireNonNull(namespaceName, "Namespace must not be null");
96 | 0 |
         return Objects.isNull(appNamespaceRepository.findByAppIdAndName(appId, namespaceName));
97 |  |
       }
98 |  |
99 |  |
       @Transactional
100 |  |
       public AppNamespace createAppNamespaceInLocal(AppNamespace appNamespace) {
101 |  |
         //not unique
102 | 0 |
         if (appNamespaceRepository.findByName(appNamespace.getName()) != null){
103 | 0 |
           throw new BadRequestException(appNamespace.getName() + "已存在");
104 |  |
         }
105 | 0 |
         AppNamespace managedAppNamespace = appNamespaceRepository.findByAppIdAndName(appNamespace.getAppId(), appNamespace.getName());
106 |  |
         //update
107 | 0 |
         if (managedAppNamespace != null){
108 | 0 |
           BeanUtils.copyEntityProperties(appNamespace, managedAppNamespace);
109 | 0 |
           return appNamespaceRepository.save(managedAppNamespace);
110 |  |
         }else {
111 | 0 |
           return appNamespaceRepository.save(appNamespace);
112 |  |
         }
113 |  |
       }
114 |  |
115 |  |
       /**
116 |  |
        * load cluster all namespace info with items
117 |  |
        */
118 |  |
       public List<NamespaceVO> findNampspaces(String appId, Env env, String clusterName) {
119 |  |
120 | 1 |
         List<NamespaceDTO> namespaces = namespaceAPI.findNamespaceByCluster(appId, env, clusterName);
121 | 1 |
         if (namespaces == null || namespaces.size() == 0) {
122 | 0 |
           return Collections.emptyList();
123 |  |
         }
124 |  |
125 | 1 |
         List<NamespaceVO> namespaceVOs = new LinkedList<>();
126 | 1 |
         for (NamespaceDTO namespace : namespaces) {
127 |  |
128 | 2 |
           NamespaceVO namespaceVO = null;
129 |  |
           try {
130 | 2 |
             namespaceVO = parseNamespace(appId, env, clusterName, namespace);
131 | 2 |
             namespaceVOs.add(namespaceVO);
132 | 0 |
           } catch (Exception e) {
133 | 0 |
             logger.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
134 | 0 |
                          appId, env, clusterName, namespace.getNamespaceName(), e);
135 | 0 |
             throw e;
136 | 2 |
           }
137 | 2 |
         }
138 |  |
139 | 1 |
         return namespaceVOs;
140 |  |
       }
141 |  |
142 |  |
       @SuppressWarnings("unchecked")
143 |  |
       private NamespaceVO parseNamespace(String appId, Env env, String clusterName, NamespaceDTO namespace) {
144 | 2 |
         NamespaceVO namespaceVO = new NamespaceVO();
145 | 2 |
         namespaceVO.setNamespace(namespace);
146 |  |
147 | 2 |
         List<NamespaceVO.ItemVO> itemVos = new LinkedList<>();
148 | 2 |
         namespaceVO.setItems(itemVos);
149 |  |
150 | 2 |
         String namespaceName = namespace.getNamespaceName();
151 |  |
152 |  |
         //latest Release
153 | 2 |
         ReleaseDTO release = null;
154 | 2 |
         Map<String, String> releaseItems = new HashMap<>();
155 |  |
         try {
156 | 2 |
           release = releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName);
157 | 2 |
           releaseItems = gson.fromJson(release.getConfigurations(), Map.class);
158 | 0 |
         } catch (HttpClientErrorException e) {
159 | 0 |
           if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
160 | 0 |
             logger.warn(ExceptionUtils.toString(e));
161 |  |
           } else {
162 | 0 |
             throw e;
163 |  |
           }
164 | 2 |
         }
165 |  |
166 |  |
         //not Release config items
167 | 2 |
         List<ItemDTO> items = itemAPI.findItems(appId, env, clusterName, namespaceName);
168 | 2 |
         int modifiedItemCnt = 0;
169 | 2 |
         for (ItemDTO itemDTO : items) {
170 |  |
171 | 4 |
           NamespaceVO.ItemVO itemVO = parseItemVO(itemDTO, releaseItems);
172 |  |
173 | 4 |
           if (itemVO.isModified()) {
174 | 2 |
             modifiedItemCnt++;
175 |  |
           }
176 |  |
177 | 4 |
           itemVos.add(itemVO);
178 | 4 |
         }
179 |  |
180 |  |
         //deleted items
181 | 2 |
         List<NamespaceVO.ItemVO> deletedItems = countDeletedItemNum(items, releaseItems);
182 | 2 |
         itemVos.addAll(deletedItems);
183 | 2 |
         modifiedItemCnt += deletedItems.size();
184 |  |
185 | 2 |
         namespaceVO.setItemModifiedCnt(modifiedItemCnt);
186 |  |
187 | 2 |
         return namespaceVO;
188 |  |
       }
189 |  |
190 |  |
       private List<NamespaceVO.ItemVO> countDeletedItemNum(List<ItemDTO> newItems, Map<String, String> releaseItems) {
191 | 2 |
         Map<String, ItemDTO> newItemMap = BeanUtils.mapByKey("key", newItems);
192 |  |
193 | 2 |
         List<NamespaceVO.ItemVO> deletedItems = new LinkedList<>();
194 | 2 |
         for (Map.Entry<String, String> entry : releaseItems.entrySet()) {
195 | 4 |
           String key = entry.getKey();
196 | 4 |
           if (newItemMap.get(key) == null) {
197 | 2 |
             NamespaceVO.ItemVO deletedItem = new NamespaceVO.ItemVO();
198 |  |
199 | 2 |
             ItemDTO deletedItemDto = new ItemDTO();
200 | 2 |
             deletedItemDto.setKey(key);
201 | 2 |
             String oldValue = entry.getValue();
202 | 2 |
             deletedItem.setItem(deletedItemDto);
203 |  |
204 | 2 |
             deletedItemDto.setValue(oldValue);
205 | 2 |
             deletedItem.setModified(true);
206 | 2 |
             deletedItem.setOldValue(oldValue);
207 | 2 |
             deletedItem.setNewValue("");
208 | 2 |
             deletedItems.add(deletedItem);
209 |  |
           }
210 | 4 |
         }
211 | 2 |
         return deletedItems;
212 |  |
       }
213 |  |
214 |  |
       private NamespaceVO.ItemVO parseItemVO(ItemDTO itemDTO, Map<String, String> releaseItems) {
215 | 4 |
         String key = itemDTO.getKey();
216 | 4 |
         NamespaceVO.ItemVO itemVO = new NamespaceVO.ItemVO();
217 | 4 |
         itemVO.setItem(itemDTO);
218 | 4 |
         String newValue = itemDTO.getValue();
219 | 4 |
         String oldValue = releaseItems.get(key);
220 |  |
         //new item or modified
221 | 4 |
         if (!StringUtils.isEmpty(key) && (oldValue == null || !newValue.equals(oldValue))) {
222 | 2 |
           itemVO.setModified(true);
223 | 2 |
           itemVO.setOldValue(oldValue == null ? "" : oldValue);
224 | 2 |
           itemVO.setNewValue(newValue);
225 |  |
         }
226 | 4 |
         return itemVO;
227 |  |
       }
228 |  |
229 |  |
     }