Skip to content

Package: EndpointInfoServiceImpl

EndpointInfoServiceImpl

nameinstructionbranchcomplexitylinemethod
EndpointInfoServiceImpl()
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
addSectionToPredicate(KapuaQuery, String)
M: 27 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
checkDuplicateEndpointInfo(KapuaId, KapuaId, String, String, int, String)
M: 96 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 16 C: 0
0%
M: 1 C: 0
0%
count(KapuaQuery)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
count(KapuaQuery, String)
M: 9 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
countAllEndpointsInScope(EntityManager, KapuaId, String)
M: 21 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
create(EndpointInfoCreator)
M: 94 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 22 C: 0
0%
M: 1 C: 0
0%
delete(KapuaId, KapuaId)
M: 40 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 10 C: 0
0%
M: 1 C: 0
0%
find(KapuaId, KapuaId)
M: 67 C: 0
0%
M: 8 C: 0
0%
M: 5 C: 0
0%
M: 15 C: 0
0%
M: 1 C: 0
0%
lambda$count$7(Object)
M: 10 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$create$0(EndpointInfoCreator, EntityManager)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$delete$2(KapuaId, KapuaId, EntityManager)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$delete$3(KapuaId, KapuaId, EntityManager)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$find$4(KapuaId, EntityManager)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$null$5(KapuaQuery)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$query$8(Object)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$traverse$6(EndpointInfoServiceImpl.myBifunction, KapuaQuery, Predicate, String, EntityManager)
M: 62 C: 0
0%
M: 14 C: 0
0%
M: 8 C: 0
0%
M: 15 C: 0
0%
M: 1 C: 0
0%
lambda$update$1(EndpointInfo, EntityManager)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
query(KapuaQuery)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
query(KapuaQuery, String)
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 23 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
traverse(KapuaQuery, String, EndpointInfoServiceImpl.myBifunction, Predicate)
M: 25 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
update(EndpointInfo)
M: 91 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 22 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others
3: *
4: * This program and the accompanying materials are made
5: * available under the terms of the Eclipse Public License 2.0
6: * which is available at https://www.eclipse.org/legal/epl-2.0/
7: *
8: * SPDX-License-Identifier: EPL-2.0
9: *
10: * Contributors:
11: * Eurotech - initial API and implementation
12: *******************************************************************************/
13: package org.eclipse.kapua.service.endpoint.internal;
14:
15: import org.eclipse.kapua.KapuaEntityNotFoundException;
16: import org.eclipse.kapua.KapuaEntityUniquenessException;
17: import org.eclipse.kapua.KapuaException;
18: import org.eclipse.kapua.commons.jpa.EntityManager;
19: import org.eclipse.kapua.commons.security.KapuaSecurityUtils;
20: import org.eclipse.kapua.commons.service.internal.AbstractKapuaService;
21: import org.eclipse.kapua.commons.util.ArgumentValidator;
22: import org.eclipse.kapua.commons.util.CommonsValidationRegex;
23: import org.eclipse.kapua.locator.KapuaLocator;
24: import org.eclipse.kapua.locator.KapuaProvider;
25: import org.eclipse.kapua.model.KapuaEntityAttributes;
26: import org.eclipse.kapua.model.domain.Actions;
27: import org.eclipse.kapua.model.id.KapuaId;
28: import org.eclipse.kapua.model.query.KapuaQuery;
29: import org.eclipse.kapua.model.query.predicate.AndPredicate;
30: import org.eclipse.kapua.model.query.predicate.AttributePredicate.Operator;
31: import org.eclipse.kapua.model.query.predicate.QueryPredicate;
32: import org.eclipse.kapua.service.account.Account;
33: import org.eclipse.kapua.service.account.AccountService;
34: import org.eclipse.kapua.service.authorization.AuthorizationService;
35: import org.eclipse.kapua.service.authorization.permission.PermissionFactory;
36: import org.eclipse.kapua.service.endpoint.EndpointInfo;
37: import org.eclipse.kapua.service.endpoint.EndpointInfoAttributes;
38: import org.eclipse.kapua.service.endpoint.EndpointInfoCreator;
39: import org.eclipse.kapua.service.endpoint.EndpointInfoDomains;
40: import org.eclipse.kapua.service.endpoint.EndpointInfoFactory;
41: import org.eclipse.kapua.service.endpoint.EndpointInfoListResult;
42: import org.eclipse.kapua.service.endpoint.EndpointInfoQuery;
43: import org.eclipse.kapua.service.endpoint.EndpointInfoService;
44:
45: import java.util.AbstractMap;
46: import java.util.ArrayList;
47: import java.util.List;
48: import java.util.Map;
49: import java.util.function.Predicate;
50:
51: /**
52: * {@link EndpointInfoService} implementation.
53: *
54: * @since 1.0.0
55: */
56: @KapuaProvider
57: public class EndpointInfoServiceImpl
58: extends AbstractKapuaService
59: implements EndpointInfoService {
60:
61: private static final KapuaLocator LOCATOR = KapuaLocator.getInstance();
62:
63: private static final AccountService ACCOUNT_SERVICE = LOCATOR.getService(AccountService.class);
64:
65: private static final AuthorizationService AUTHORIZATION_SERVICE = LOCATOR.getService(AuthorizationService.class);
66: private static final PermissionFactory PERMISSION_FACTORY = LOCATOR.getFactory(PermissionFactory.class);
67:
68: private static final EndpointInfoFactory ENDPOINT_INFO_FACTORY = LOCATOR.getFactory(EndpointInfoFactory.class);
69:
70: private static final String ENDPOINT_INFO_CREATOR_SCHEMA = "endpointInfoCreator.schema";
71: private static final String ENDPOINT_INFO_CREATOR_DNS = "endpointInfoCreator.dns";
72: private static final String ENDPOINT_INFO_SCHEMA = "endpointInfo.schema";
73: private static final String ENDPOINT_INFO_DNS = "endpointInfo.dns";
74:
75: public EndpointInfoServiceImpl() {
76: super(EndpointEntityManagerFactory.getInstance(), null);
77: }
78:
79: @Override
80: public EndpointInfo create(EndpointInfoCreator endpointInfoCreator)
81: throws KapuaException {
82: ArgumentValidator.notNull(endpointInfoCreator, "endpointInfoCreator");
83: ArgumentValidator.notNull(endpointInfoCreator.getScopeId(), "endpointInfoCreator.scopeId");
84: ArgumentValidator.notNull(endpointInfoCreator.getEndpointType(), "endpointInfoCreator.endpointType");
85:
86: ArgumentValidator.notEmptyOrNull(endpointInfoCreator.getSchema(), ENDPOINT_INFO_CREATOR_SCHEMA);
87: ArgumentValidator.match(endpointInfoCreator.getSchema(), CommonsValidationRegex.URI_SCHEME, ENDPOINT_INFO_CREATOR_SCHEMA);
88: ArgumentValidator.lengthRange(endpointInfoCreator.getSchema(), 1, 64, ENDPOINT_INFO_CREATOR_SCHEMA);
89:
90: ArgumentValidator.notEmptyOrNull(endpointInfoCreator.getDns(), ENDPOINT_INFO_CREATOR_DNS);
91: ArgumentValidator.match(endpointInfoCreator.getDns(), CommonsValidationRegex.URI_DNS, ENDPOINT_INFO_CREATOR_DNS);
92: ArgumentValidator.lengthRange(endpointInfoCreator.getDns(), 1, 1024, ENDPOINT_INFO_CREATOR_DNS);
93:
94: ArgumentValidator.notNegative(endpointInfoCreator.getPort(), "endpointInfoCreator.port");
95: ArgumentValidator.numRange(endpointInfoCreator.getPort(), 1, 65535, "endpointInfoCreator.port");
96:
97: //
98: // Check Access
99:• KapuaId scopeIdPermission = endpointInfoCreator.getEndpointType().equals(EndpointInfo.ENDPOINT_TYPE_CORS) ?
100: endpointInfoCreator.getScopeId() : null;
101: AUTHORIZATION_SERVICE.checkPermission(
102: PERMISSION_FACTORY.newPermission(EndpointInfoDomains.ENDPOINT_INFO_DOMAIN, Actions.write, scopeIdPermission)
103: );
104:
105: //
106: // Check duplicate endpoint
107: checkDuplicateEndpointInfo(
108: endpointInfoCreator.getScopeId(),
109: null,
110: endpointInfoCreator.getSchema(),
111: endpointInfoCreator.getDns(),
112: endpointInfoCreator.getPort(),
113: endpointInfoCreator.getEndpointType());
114:
115: //
116: // Do create
117: return entityManagerSession.doTransactedAction(em -> EndpointInfoDAO.create(em, endpointInfoCreator));
118: }
119:
120: @Override
121: public EndpointInfo update(EndpointInfo endpointInfo) throws KapuaException {
122: ArgumentValidator.notNull(endpointInfo, "endpointInfo");
123: ArgumentValidator.notNull(endpointInfo.getScopeId(), "endpointInfo.scopeId");
124:
125: ArgumentValidator.notEmptyOrNull(endpointInfo.getSchema(), ENDPOINT_INFO_SCHEMA);
126: ArgumentValidator.match(endpointInfo.getSchema(), CommonsValidationRegex.URI_SCHEME, ENDPOINT_INFO_SCHEMA);
127: ArgumentValidator.lengthRange(endpointInfo.getSchema(), 1, 64, ENDPOINT_INFO_SCHEMA);
128:
129: ArgumentValidator.notEmptyOrNull(endpointInfo.getDns(), ENDPOINT_INFO_DNS);
130: ArgumentValidator.match(endpointInfo.getDns(), CommonsValidationRegex.URI_DNS, ENDPOINT_INFO_DNS);
131: ArgumentValidator.lengthRange(endpointInfo.getDns(), 1, 1024, ENDPOINT_INFO_DNS);
132:
133: ArgumentValidator.notNegative(endpointInfo.getPort(), "endpointInfo.port");
134: ArgumentValidator.numRange(endpointInfo.getPort(), 1, 65535, "endpointInfo.port");
135:
136: //
137: // Check Access
138:• KapuaId scopeIdPermission = endpointInfo.getEndpointType().equals(EndpointInfo.ENDPOINT_TYPE_CORS) ?
139: endpointInfo.getScopeId() : null;
140: AUTHORIZATION_SERVICE.checkPermission(
141: PERMISSION_FACTORY.newPermission(EndpointInfoDomains.ENDPOINT_INFO_DOMAIN, Actions.write, scopeIdPermission)
142: );
143:
144: //
145: // Check duplicate endpoint
146: checkDuplicateEndpointInfo(
147: endpointInfo.getScopeId(),
148: endpointInfo.getId(),
149: endpointInfo.getSchema(),
150: endpointInfo.getDns(),
151: endpointInfo.getPort(),
152: endpointInfo.getEndpointType());
153:
154: //
155: // Do update
156: return entityManagerSession.doTransactedAction(em -> EndpointInfoDAO.update(em, endpointInfo));
157: }
158:
159: @Override
160: public void delete(KapuaId scopeId, KapuaId endpointInfoId) throws KapuaException {
161: ArgumentValidator.notNull(scopeId, "scopeId");
162: ArgumentValidator.notNull(endpointInfoId, "endpointInfoId");
163:
164: //
165: // Check Access
166: EndpointInfo endpointInfoToDelete = entityManagerSession.doAction(em -> EndpointInfoDAO.find(em, scopeId, endpointInfoId));
167: KapuaId scopeIdPermission = null;
168:• if (endpointInfoToDelete != null && endpointInfoToDelete.getEndpointType().equals(EndpointInfo.ENDPOINT_TYPE_CORS)) {
169: scopeIdPermission = scopeId;
170: }
171:
172: AUTHORIZATION_SERVICE.checkPermission(
173: PERMISSION_FACTORY.newPermission(EndpointInfoDomains.ENDPOINT_INFO_DOMAIN, Actions.delete, scopeIdPermission)
174: );
175:
176: //
177: // Do delete
178: entityManagerSession.doTransactedAction(em -> EndpointInfoDAO.delete(em, scopeId, endpointInfoId));
179: }
180:
181: @Override
182: public EndpointInfo find(KapuaId scopeId, KapuaId endpointInfoId)
183: throws KapuaException {
184: ArgumentValidator.notNull(scopeId, "scopeId");
185: ArgumentValidator.notNull(endpointInfoId, "endpointInfoId");
186:
187: //
188: // Check Access
189:
190: AUTHORIZATION_SERVICE.checkPermission(
191: PERMISSION_FACTORY.newPermission(EndpointInfoDomains.ENDPOINT_INFO_DOMAIN, Actions.read, scopeId)
192: );
193:
194: EndpointInfo endpointInfoToFind = entityManagerSession.doAction(em -> EndpointInfoDAO.find(em, KapuaId.ANY, endpointInfoId)); // search the endpoint in any scope
195:
196:• if (endpointInfoToFind == null) {
197: throw new KapuaEntityNotFoundException(EndpointInfo.TYPE, endpointInfoId);
198: }
199:
200:• if (endpointInfoToFind.getScopeId().equals(scopeId)) { //found in the specified scope, search finish here
201: return endpointInfoToFind;
202: }
203: //found but in another scope...is defined in the scope of the first Account that has defined endpoints? (proceeding upwards)
204: String type = endpointInfoToFind.getEndpointType();
205: //now find the endpoints of the search type that I can use (aka, the nearest proceeding upwards in Accounts hierarchy)
206: EndpointInfoQuery query = ENDPOINT_INFO_FACTORY.newQuery(scopeId);
207: EndpointInfoListResult nearestUsableEndpoints = query(query, type);
208:
209:• if (nearestUsableEndpoints.isEmpty() || ! nearestUsableEndpoints.getFirstItem().getScopeId().equals(endpointInfoToFind.getScopeId())) { //the second condition is equivalent to verify if the searched endpoint is in this list
210: throw new KapuaEntityNotFoundException(EndpointInfo.TYPE, endpointInfoId);
211: } else {
212: return endpointInfoToFind;
213: }
214: }
215:
216: /**
217: * Traverse the account hierarchy bottom-up to search for {@link EndpointInfo} respecting the given query,
218: * performing for each layer the given operationToPerform until the given emptinessPredicate dictates to stop OR when endpoints of the same section are found in one layer
219: * In other terms, this method applies a given function to the "nearest usable endpoints", aka the ones that I see in a given scopeID
220: *
221: * @param query The query to filter the {@link EndpointInfo}s.
222: * @param section section of {@link EndpointInfo} where we want to search the information
223: * @param operationToPerform function to apply at each layer
224: * @param emptinessPredicate predicate that dictates to stop the traversal when false
225: */
226: public Object traverse(KapuaQuery query, String section, myBifunction<EntityManager, KapuaQuery, Object, KapuaException> operationToPerform, Predicate<Object> emptinessPredicate)
227: throws KapuaException {
228: ArgumentValidator.notNull(query, "query");
229:
230: //
231: // Check Access
232: AUTHORIZATION_SERVICE.checkPermission(
233: PERMISSION_FACTORY.newPermission(EndpointInfoDomains.ENDPOINT_INFO_DOMAIN, Actions.read, query.getScopeId())
234: );
235: addSectionToPredicate(query, section);
236:
237: //
238: // Do Query
239: return entityManagerSession.doAction(em -> {
240: Object res = operationToPerform.apply(em, query);
241:
242:• if (emptinessPredicate.test(res) && query.getScopeId() != null) { //query did not find results
243:
244: KapuaId originalScopeId = query.getScopeId();
245:
246: do {
247: // First check if there are any endpoint AT ALL specified in this scope/layer
248:• if (countAllEndpointsInScope(em, query.getScopeId(), section)) {
249: // There are endpoints (even not matching the query), exit because I found the "nearest usable" endpoints which don't have what I'm searching
250: break;
251: }
252: Account account = KapuaSecurityUtils.doPrivileged(() -> ACCOUNT_SERVICE.find(query.getScopeId()));
253:
254:• if (account == null) {
255: throw new KapuaEntityNotFoundException(Account.TYPE, query.getScopeId());
256: }
257:• if (account.getScopeId() == null) {
258: // Query was originally on root account, and querying on parent scope id would mean querying in null,
259: // i.e. querying on all accounts. Since that's not what we want, break away.
260: break;
261: }
262: query.setScopeId(account.getScopeId());
263: res = operationToPerform.apply(em, query);
264: }
265:• while (query.getScopeId() != null && emptinessPredicate.test(res));
266:
267: query.setScopeId(originalScopeId);
268: }
269:
270: return res;
271: });
272: }
273:
274: @Override
275: public long count(KapuaQuery query) throws KapuaException {
276: return count(query, EndpointInfo.ENDPOINT_TYPE_RESOURCE);
277: }
278:
279: @Override
280: public long count(KapuaQuery query, String section) throws KapuaException {
281:• return (long) traverse(query, section, EndpointInfoDAO::count, a -> (long)a == 0);
282: }
283:
284: @Override
285: public EndpointInfoListResult query(KapuaQuery query) throws KapuaException {
286: return query(query, EndpointInfo.ENDPOINT_TYPE_RESOURCE);
287: }
288:
289: public EndpointInfoListResult query(KapuaQuery query, String section) throws KapuaException {
290: return (EndpointInfoListResult) traverse(query, section, EndpointInfoDAO::query, a -> ((EndpointInfoListResult)a).isEmpty());
291: }
292:
293: //
294: // Private methods and interfaces
295: //
296:
297: //this interface is created solely because java complains if you pass lambdas throwing checked exception
298: //to overcome this, I created this interface which is a custom form of a Bifunction throwing the checked KapuaException
299: @FunctionalInterface
300: private interface myBifunction<A, B, C, E extends KapuaException> {
301: C apply(A input1, B input2) throws E;
302: }
303:
304: /**
305: * Checks whether another {@link EndpointInfo} already exists with the given values.
306: *
307: * @param scopeId The ScopeId of the {@link EndpointInfo}
308: * @param entityId The entity id, if exists. On update you need to exclude the same entity.
309: * @param schema The {@link EndpointInfo#getSchema()} value.
310: * @param dns The {@link EndpointInfo#getDns()} value.
311: * @param port The {@link EndpointInfo#getPort()} value.
312: * @param type The {@link EndpointInfo#getEndpointType()} value.
313: * @throws KapuaException if the values provided matches another {@link EndpointInfo}
314: * @since 1.0.0
315: */
316: private void checkDuplicateEndpointInfo(KapuaId scopeId, KapuaId entityId, String schema, String dns, int port, String type) throws KapuaException {
317:
318: EndpointInfoQuery query = new EndpointInfoQueryImpl(scopeId);
319:
320: AndPredicate andPredicate = query.andPredicate(
321: query.attributePredicate(EndpointInfoAttributes.SCHEMA, schema),
322: query.attributePredicate(EndpointInfoAttributes.DNS, dns),
323: query.attributePredicate(EndpointInfoAttributes.PORT, port)
324: );
325:
326:• if (entityId != null) {
327: andPredicate.and(query.attributePredicate(KapuaEntityAttributes.ENTITY_ID, entityId, Operator.NOT_EQUAL));
328: }
329:
330: query.setPredicate(andPredicate);
331:
332:• if (count(query,type) > 0) {
333: List<Map.Entry<String, Object>> uniquesFieldValues = new ArrayList<>();
334: uniquesFieldValues.add(new AbstractMap.SimpleEntry<>(KapuaEntityAttributes.SCOPE_ID, scopeId));
335: uniquesFieldValues.add(new AbstractMap.SimpleEntry<>(EndpointInfoAttributes.SCHEMA, schema));
336: uniquesFieldValues.add(new AbstractMap.SimpleEntry<>(EndpointInfoAttributes.DNS, dns));
337: uniquesFieldValues.add(new AbstractMap.SimpleEntry<>(EndpointInfoAttributes.PORT, port));
338:
339: throw new KapuaEntityUniquenessException(EndpointInfo.TYPE, uniquesFieldValues);
340: }
341: }
342:
343: private boolean countAllEndpointsInScope(EntityManager em, KapuaId scopeId, String section) throws KapuaException {
344: EndpointInfoQuery totalQuery = ENDPOINT_INFO_FACTORY.newQuery(scopeId);
345: addSectionToPredicate(totalQuery, section);
346: long totalCount = EndpointInfoDAO.count(em, totalQuery);
347:• return totalCount != 0;
348: }
349:
350: private void addSectionToPredicate(KapuaQuery query, String section) {
351: QueryPredicate sectionPredicate = query.attributePredicate(EndpointInfoAttributes.ENDPOINT_TYPE, section);
352: QueryPredicate currentPredicate = query.getPredicate();
353:• query.setPredicate(currentPredicate == null ? sectionPredicate : query.andPredicate(currentPredicate, sectionPredicate));
354: }
355:
356: }