This is an automated email from the ASF dual-hosted git repository. shuber pushed a commit to branch UNOMI-554-improve-server-info in repository https://gitbox.apache.org/repos/asf/unomi.git
commit 4be5e1058d926071fa78c6577098c8803d189718 Author: Serge Huber <[email protected]> AuthorDate: Wed Mar 9 18:01:24 2022 +0100 UNOMI-554 Improve server identification & various bug fixes - Add /cxs/privacy/infos endpoint to retrieve all server information - Make it possible to override server information and extend it - Add build number, build date, build timestamp and scm branch reporting - Add possibility to override startup logo - Refactor BundleWatcher - Fix negative test event type bug. - Fix bug in GraphQL JSON schema integration --- .../main/java/org/apache/unomi/api/ServerInfo.java | 48 ++++ .../apache/unomi/api/services/PrivacyService.java | 14 +- .../unomi/privacy/rest/PrivacyServiceEndPoint.java | 6 + extensions/privacy-extension/services/pom.xml | 6 + .../unomi/privacy/internal/PrivacyServiceImpl.java | 23 +- .../resources/OSGI-INF/blueprint/blueprint.xml | 3 + .../types/resolvers/CDPEventInterfaceResolver.java | 2 +- .../test/java/org/apache/unomi/itests/AllITs.java | 1 + .../test/java/org/apache/unomi/itests/BaseIT.java | 198 +++++++++++++++ .../org/apache/unomi/itests/PrivacyServiceIT.java | 81 ++++++ .../schemas/events/negative-test-event-type.json | 13 + lifecycle-watcher/pom.xml | 8 + .../org/apache/unomi/lifecycle/BundleWatcher.java | 276 +-------------------- .../{BundleWatcher.java => BundleWatcherImpl.java} | 118 +++++++-- .../resources/OSGI-INF/blueprint/blueprint.xml | 4 +- .../main/resources/{logo.txt => unomi-logo.txt} | 2 - .../impl/schemas/UnomiPropertyTypeKeyword.java | 6 +- .../META-INF/cxs/schemas/events/view.json | 1 - 18 files changed, 504 insertions(+), 306 deletions(-) diff --git a/api/src/main/java/org/apache/unomi/api/ServerInfo.java b/api/src/main/java/org/apache/unomi/api/ServerInfo.java index 2006a1f..7b80f94 100644 --- a/api/src/main/java/org/apache/unomi/api/ServerInfo.java +++ b/api/src/main/java/org/apache/unomi/api/ServerInfo.java @@ -17,6 +17,8 @@ package org.apache.unomi.api; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; @@ -27,10 +29,16 @@ public class ServerInfo { private String serverIdentifier; private String serverVersion; + private String serverBuildNumber; + private Date serverBuildDate; + private String serverTimestamp; + private String serverScmBranch; private List<EventInfo> eventTypes; private Map<String,String> capabilities; + private List<String> logoLines = new ArrayList<>(); + public ServerInfo() { } @@ -50,6 +58,38 @@ public class ServerInfo { this.serverVersion = serverVersion; } + public String getServerBuildNumber() { + return serverBuildNumber; + } + + public void setServerBuildNumber(String serverBuildNumber) { + this.serverBuildNumber = serverBuildNumber; + } + + public Date getServerBuildDate() { + return serverBuildDate; + } + + public void setServerBuildDate(Date serverBuildDate) { + this.serverBuildDate = serverBuildDate; + } + + public String getServerTimestamp() { + return serverTimestamp; + } + + public void setServerTimestamp(String serverTimestamp) { + this.serverTimestamp = serverTimestamp; + } + + public String getServerScmBranch() { + return serverScmBranch; + } + + public void setServerScmBranch(String serverScmBranch) { + this.serverScmBranch = serverScmBranch; + } + public List<EventInfo> getEventTypes() { return eventTypes; } @@ -65,4 +105,12 @@ public class ServerInfo { public void setCapabilities(Map<String, String> capabilities) { this.capabilities = capabilities; } + + public List<String> getLogoLines() { + return logoLines; + } + + public void setLogoLines(List<String> logoLines) { + this.logoLines = logoLines; + } } diff --git a/api/src/main/java/org/apache/unomi/api/services/PrivacyService.java b/api/src/main/java/org/apache/unomi/api/services/PrivacyService.java index 35f11be..3f7d555 100644 --- a/api/src/main/java/org/apache/unomi/api/services/PrivacyService.java +++ b/api/src/main/java/org/apache/unomi/api/services/PrivacyService.java @@ -28,13 +28,23 @@ import java.util.List; public interface PrivacyService { /** - * Retrieves the server information, including the name and version of the server, the event types - * if recognizes as well as the capabilities supported by the system. + * Retrieves the default base Apache Unomi server information, including the name and version of the server, build + * time information and the event types + * if recognizes as well as the capabilities supported by the system. For more detailed information about the system + * and extensions use the getServerInfos method. * @return a ServerInfo object with all the server information */ ServerInfo getServerInfo(); /** + * Retrieves the list of the server information objects, that include extensions. Each object includes the + * name and version of the server, build time information and the event types + * if recognizes as well as the capabilities supported by the system. + * @return a list of ServerInfo objects with all the server information + */ + List<ServerInfo> getServerInfos(); + + /** * Deletes the current profile (but has no effect on sessions and events). This will delete the * persisted profile and replace it with a new empty one with the same profileId. * @param profileId the identifier of the profile to delete and replace diff --git a/extensions/privacy-extension/rest/src/main/java/org/apache/unomi/privacy/rest/PrivacyServiceEndPoint.java b/extensions/privacy-extension/rest/src/main/java/org/apache/unomi/privacy/rest/PrivacyServiceEndPoint.java index c4c990a..8c3dafc 100644 --- a/extensions/privacy-extension/rest/src/main/java/org/apache/unomi/privacy/rest/PrivacyServiceEndPoint.java +++ b/extensions/privacy-extension/rest/src/main/java/org/apache/unomi/privacy/rest/PrivacyServiceEndPoint.java @@ -57,6 +57,12 @@ public class PrivacyServiceEndPoint { return privacyService.getServerInfo(); } + @GET + @Path("/infos") + public List<ServerInfo> getServerInfos() { + return privacyService.getServerInfos(); + } + @DELETE @Path("/profiles/{profileId}") public Response deleteProfileData(@PathParam("profileId") String profileId, @QueryParam("withData") @DefaultValue("false") boolean withData, diff --git a/extensions/privacy-extension/services/pom.xml b/extensions/privacy-extension/services/pom.xml index 5a0ede7..b7e337d 100644 --- a/extensions/privacy-extension/services/pom.xml +++ b/extensions/privacy-extension/services/pom.xml @@ -53,6 +53,12 @@ <artifactId>osgi.core</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.apache.unomi</groupId> + <artifactId>unomi-lifecycle-watcher</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> </dependencies> <build> diff --git a/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java b/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java index 3d3d68d..64c3a5f 100644 --- a/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java +++ b/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java @@ -21,6 +21,7 @@ import org.apache.unomi.api.*; import org.apache.unomi.api.services.EventService; import org.apache.unomi.api.services.PrivacyService; import org.apache.unomi.api.services.ProfileService; +import org.apache.unomi.lifecycle.BundleWatcher; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; import org.osgi.framework.BundleContext; @@ -40,6 +41,7 @@ public class PrivacyServiceImpl implements PrivacyService { private ProfileService profileService; private EventService eventService; private BundleContext bundleContext; + private BundleWatcher bundleWatcher; public PrivacyServiceImpl() { logger.info("Initializing privacy service..."); @@ -61,12 +63,20 @@ public class PrivacyServiceImpl implements PrivacyService { this.bundleContext = bundleContext; } + public void setBundleWatcher(BundleWatcher bundleWatcher) { + this.bundleWatcher = bundleWatcher; + } + @Override public ServerInfo getServerInfo() { - ServerInfo serverInfo = new ServerInfo(); - serverInfo.setServerIdentifier("Apache Unomi"); - serverInfo.setServerVersion(bundleContext.getBundle().getVersion().toString()); + List<ServerInfo> serverInfos = bundleWatcher.getServerInfos(); + ServerInfo serverInfo = serverInfos.get(0); // Unomi is always be the first entry + + addUnomiInfo(serverInfo); + return serverInfo; + } + private void addUnomiInfo(ServerInfo serverInfo) { // let's retrieve all the event types the server has seen. Map<String, Long> eventTypeCounts = persistenceService.aggregateWithOptimizedQuery(null, new TermsAggregate("eventType"), Event.ITEM_TYPE); List<EventInfo> eventTypes = new ArrayList<EventInfo>(); @@ -79,7 +89,12 @@ public class PrivacyServiceImpl implements PrivacyService { serverInfo.setEventTypes(eventTypes); serverInfo.setCapabilities(new HashMap<String, String>()); - return serverInfo; + } + + public List<ServerInfo> getServerInfos() { + List<ServerInfo> serverInfos = bundleWatcher.getServerInfos(); + addUnomiInfo(serverInfos.get(0)); + return serverInfos; } @Override diff --git a/extensions/privacy-extension/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/extensions/privacy-extension/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 1b56fe9..85f9e3c 100644 --- a/extensions/privacy-extension/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/extensions/privacy-extension/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -29,6 +29,8 @@ <reference id="profileService" interface="org.apache.unomi.api.services.ProfileService"/> + <reference id="bundleWatcher" interface="org.apache.unomi.lifecycle.BundleWatcher" /> + <!-- Privacy service --> <bean id="privacyServiceImpl" class="org.apache.unomi.privacy.internal.PrivacyServiceImpl"> @@ -36,6 +38,7 @@ <property name="eventService" ref="eventService" /> <property name="profileService" ref="profileService" /> <property name="bundleContext" ref="blueprintBundleContext"/> + <property name="bundleWatcher" ref="bundleWatcher"/> </bean> <service id="privacyService" ref="privacyServiceImpl" interface="org.apache.unomi.api.services.PrivacyService"/> </blueprint> diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java index fc15ed4..9f62673 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java @@ -34,7 +34,7 @@ public class CDPEventInterfaceResolver extends BaseTypeResolver { final CDPEventInterface eventInterface = env.getObject(); final JSONSchema eventSchema = schemaRegistry.getSchema("https://unomi.apache.org/schemas/json/events/" + eventInterface.getEvent().getEventType() + "/1-0-0"); if (eventSchema != null) { - final String typeName = UnomiToGraphQLConverter.convertEventType(eventSchema.getSchemaId()); + final String typeName = UnomiToGraphQLConverter.convertEventType(eventSchema.getName()); return env.getSchema().getObjectType(typeName); } else { return super.getType(env); diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java b/itests/src/test/java/org/apache/unomi/itests/AllITs.java index d632872..facb730 100644 --- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java +++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java @@ -51,6 +51,7 @@ import org.junit.runners.Suite.SuiteClasses; ContextServletIT.class, SecurityIT.class, RuleServiceIT.class, + PrivacyServiceIT.class, GroovyActionsServiceIT.class, GraphQLEventIT.class, GraphQLListIT.class, diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java index d39569b..102d107 100644 --- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java @@ -19,6 +19,22 @@ package org.apache.unomi.itests; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.*; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.rules.Rule; @@ -28,6 +44,7 @@ import org.apache.unomi.api.services.SchemaRegistry; import org.apache.unomi.lifecycle.BundleWatcher; import org.apache.unomi.persistence.spi.CustomObjectMapper; import org.apache.unomi.persistence.spi.PersistenceService; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.runner.RunWith; @@ -51,8 +68,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.function.Predicate; @@ -77,6 +102,11 @@ public abstract class BaseIT { protected static final String URL = "http://localhost:" + HTTP_PORT; protected static final String KARAF_DIR = "target/exam"; protected static final String UNOMI_KEY = "670c26d1cc413346c3b2fd9ce65dab41"; + protected static final ContentType JSON_CONTENT_TYPE = ContentType.create("application/json"); + protected static final String BASE_URL = "http://localhost"; + protected static final String BASIC_AUTH_USER_NAME = "karaf"; + protected static final String BASIC_AUTH_PASSWORD = "karaf"; + protected static final int REQUEST_TIMEOUT = 60000; @Inject @Filter(timeout = 600000) @@ -104,14 +134,24 @@ public abstract class BaseIT { @Filter(timeout = 600000) protected SchemaRegistry schemaRegistry; + private CloseableHttpClient httpClient; + @Before public void waitForStartup() throws InterruptedException { while (!bundleWatcher.isStartupComplete()) { LOGGER.info("Waiting for startup to complete..."); Thread.sleep(1000); } + httpClient = initHttpClient(); + } + + @After + public void shutdown() { + closeHttpClient(httpClient); + httpClient = null; } + protected void removeItems(final Class<? extends Item> ...classes) throws InterruptedException { Condition condition = new Condition(definitionsService.getConditionType("matchAllCondition")); for (Class<? extends Item> aClass : classes) { @@ -362,4 +402,162 @@ public abstract class BaseIT { 100); rulesService.refreshRules(); } + + public String getFullUrl(String url) throws Exception { + return BASE_URL + ":" + HTTP_PORT + url; + } + + protected <T> T get(final String url, Class<T> clazz) { + CloseableHttpResponse response = null; + try { + final HttpGet httpGet = new HttpGet(getFullUrl(url)); + response = executeHttpRequest(httpGet); + if (response.getStatusLine().getStatusCode() == 200) { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(response.getEntity().getContent(), clazz); + } else { + return null; + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + protected CloseableHttpResponse post(final String url, final String resource) { + try { + final HttpPost request = new HttpPost(getFullUrl(url)); + + if (resource != null) { + final String resourceAsString = resourceAsString(resource); + request.setEntity(new StringEntity(resourceAsString, JSON_CONTENT_TYPE)); + } + + return executeHttpRequest(request); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + protected void delete(final String url) { + CloseableHttpResponse response = null; + try { + final HttpDelete httpDelete = new HttpDelete(getFullUrl(url)); + response = executeHttpRequest(httpDelete); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + protected CloseableHttpResponse executeHttpRequest(HttpUriRequest request) throws IOException { + System.out.println("Executing request " + request.getMethod() + " " + request.getURI() + "..."); + CloseableHttpResponse response = httpClient.execute(request); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != 200) { + String content = null; + if (response.getEntity() != null) { + InputStream contentInputStream = response.getEntity().getContent(); + if (contentInputStream != null) { + content = IOUtils.toString(response.getEntity().getContent()); + } + } + LOGGER.error("Response status code: {}, reason: {}, content:{}", response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase(), content); + } + return response; + } + + protected String resourceAsString(final String resource) { + final java.net.URL url = bundleContext.getBundle().getResource(resource); + try (InputStream stream = url.openStream()) { + final ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(objectMapper.readTree(stream)); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + public static CloseableHttpClient initHttpClient() { + long requestStartTime = System.currentTimeMillis(); + BasicCredentialsProvider credsProvider = null; + credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + AuthScope.ANY, + new UsernamePasswordCredentials(BASIC_AUTH_USER_NAME, BASIC_AUTH_PASSWORD)); + HttpClientBuilder httpClientBuilder = HttpClients.custom().useSystemProperties().setDefaultCredentialsProvider(credsProvider); + + try { + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, new TrustManager[]{new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, + String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, + String authType) { + } + }}, new SecureRandom()); + + Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)) + .build(); + + PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + poolingHttpClientConnectionManager.setMaxTotal(10); + + httpClientBuilder.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) + .setConnectionManager(poolingHttpClientConnectionManager); + + } catch (NoSuchAlgorithmException | KeyManagementException e) { + LOGGER.error("Error creating SSL Context", e); + } + + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(REQUEST_TIMEOUT) + .setSocketTimeout(REQUEST_TIMEOUT) + .setConnectionRequestTimeout(REQUEST_TIMEOUT) + .build(); + httpClientBuilder.setDefaultRequestConfig(requestConfig); + + if (LOGGER.isDebugEnabled()) { + long totalRequestTime = System.currentTimeMillis() - requestStartTime; + LOGGER.debug("Init HttpClient executed in " + totalRequestTime + "ms"); + } + + return httpClientBuilder.build(); + } + + public static void closeHttpClient(CloseableHttpClient httpClient) { + try { + if (httpClient != null) { + httpClient.close(); + } + } catch (IOException e) { + LOGGER.error("Could not close httpClient: " + httpClient, e); + } + } + } diff --git a/itests/src/test/java/org/apache/unomi/itests/PrivacyServiceIT.java b/itests/src/test/java/org/apache/unomi/itests/PrivacyServiceIT.java new file mode 100644 index 0000000..0c4f8a3 --- /dev/null +++ b/itests/src/test/java/org/apache/unomi/itests/PrivacyServiceIT.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package org.apache.unomi.itests; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.apache.unomi.api.PartialList; +import org.apache.unomi.persistence.spi.CustomObjectMapper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerSuite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerSuite.class) +public class PrivacyServiceIT extends BaseIT { + + protected static final String PRIVACY_ENDPOINT = "/cxs/privacy"; + private static final int DEFAULT_TRYING_TIMEOUT = 2000; + private static final int DEFAULT_TRYING_TRIES = 30; + + @Before + public void setUp() throws InterruptedException, IOException { + keepTrying("Couldn't find privacy endpoint", + () -> get(PRIVACY_ENDPOINT + "/info", Map.class), + serverInfo -> serverInfo != null, + DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES); + } + + @Test + public void testServerInfo() throws IOException { + Map<String,Object> serverInfo = get(PRIVACY_ENDPOINT + "/info", Map.class); + assertNotNull("Server info is null", serverInfo); + assertEquals("Server identifier is incorrect", "Apache Unomi", serverInfo.get("serverIdentifier")); + } + + @Test + public void testServerInfos() throws IOException { + List<Map<String,Object>> serverInfos = get(PRIVACY_ENDPOINT + "/infos", List.class); + assertEquals("Server info list is invalid", 1, serverInfos.size()); + assertEquals("Server identifier is incorrect", "Apache Unomi", serverInfos.get(0).get("serverIdentifier")); + } + +} diff --git a/itests/src/test/resources/schemas/events/negative-test-event-type.json b/itests/src/test/resources/schemas/events/negative-test-event-type.json new file mode 100644 index 0000000..fe4d299 --- /dev/null +++ b/itests/src/test/resources/schemas/events/negative-test-event-type.json @@ -0,0 +1,13 @@ +{ + "$id": "https://unomi.apache.org/schemas/json/events/negative-test-event-type/1-0-0", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "self":{ + "vendor":"org.apache.unomi", + "name":"events/negative-test-event-type", + "format":"jsonschema", + "version":"1-0-0" + }, + "title": "TestEvent", + "type": "object", + "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }] +} \ No newline at end of file diff --git a/lifecycle-watcher/pom.xml b/lifecycle-watcher/pom.xml index 93a60ec..f3a5192 100644 --- a/lifecycle-watcher/pom.xml +++ b/lifecycle-watcher/pom.xml @@ -34,6 +34,12 @@ <groupId>org.osgi</groupId> <artifactId>osgi.core</artifactId> </dependency> + <dependency> + <groupId>org.apache.unomi</groupId> + <artifactId>unomi-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> </dependencies> <build> @@ -64,6 +70,8 @@ <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency> <Implementation-Build>${buildNumber}</Implementation-Build> <Implementation-TimeStamp>${timestamp}</Implementation-TimeStamp> + <Implementation-ScmBranch>${scmBranch}</Implementation-ScmBranch> + <Implementation-ServerIdentifier>Apache Unomi</Implementation-ServerIdentifier> </instructions> </configuration> </plugin> diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java index 31eec3b..06c28a6 100644 --- a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java +++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java @@ -16,276 +16,24 @@ */ package org.apache.unomi.lifecycle; -import org.osgi.framework.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.unomi.api.ServerInfo; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimerTask; -import java.util.concurrent.*; -import java.util.stream.Collectors; /** - * This class listens to the global Apache Unomi bundle lifecycle, to provide statistics and state of the overall - * system. It notably displays messages for successfull or unsuccessfull startups as well as startup times. + * Interface for the bundle watcher system in Apache Unomi. It allows to know if startup has completed as well as + * server information such as identifier, versions, build information and more. */ -public class BundleWatcher implements SynchronousBundleListener, ServiceListener { +public interface BundleWatcher { - private static final Logger logger = LoggerFactory.getLogger(BundleWatcher.class.getName()); + /** + * Retrieves the list of the server information objects, that include extensions. Each object includes the + * name and version of the server, build time information and the event types + * if recognizes as well as the capabilities supported by the system. + * @return a list of ServerInfo objects with all the server information + */ + List<ServerInfo> getServerInfos(); - private long startupTime; - private Map<String, Boolean> requiredBundles = new ConcurrentHashMap<>(); - - private ScheduledExecutorService scheduler; - private ScheduledFuture<?> scheduledFuture; - - private String requiredServices; - private Set<Filter> requiredServicesFilters = new LinkedHashSet<>(); - private long matchedRequiredServicesCount = 0; - - private BundleContext bundleContext; - private boolean startupMessageAlreadyDisplayed = false; - private boolean shutdownMessageAlreadyDisplayed = false; - private List<String> logoLines = new ArrayList<>(); - - private Integer checkStartupStateRefreshInterval = 60; - - public void setRequiredBundles(Map<String, Boolean> requiredBundles) { - this.requiredBundles = new ConcurrentHashMap<>(requiredBundles); - } - - public void setCheckStartupStateRefreshInterval(Integer checkStartupStateRefreshInterval) { - this.checkStartupStateRefreshInterval = checkStartupStateRefreshInterval; - } - - public void setRequiredServices(String requiredServices) { - this.requiredServices = requiredServices; - String[] requiredServiceArray = requiredServices.split(","); - requiredServicesFilters.clear(); - for (String requiredService : requiredServiceArray) { - try { - requiredServicesFilters.add(bundleContext.createFilter(requiredService.trim())); - } catch (InvalidSyntaxException e) { - logger.error("Error creating require service filter {}", requiredService.trim(), e); - } - } - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - public void init() { - scheduler = Executors.newSingleThreadScheduledExecutor(); - checkExistingBundles(); - bundleContext.addBundleListener(this); - bundleContext.addServiceListener(this); - loadLogo(); - startupTime = System.currentTimeMillis(); - System.out.println("Initializing Unomi..."); - logger.info("Bundle watcher initialized."); - } - - private boolean allBundleStarted() { - return getInactiveBundles().isEmpty(); - } - - private void displayLogsForInactiveBundles() { - getInactiveBundles().forEach(inactiveBundle -> logger - .warn("The bundle {} is in not active, some errors could happen when using the application", inactiveBundle)); - } - - private List<String> getInactiveBundles() { - return requiredBundles.entrySet().stream().filter(entry -> !entry.getValue()).map(Map.Entry::getKey).collect(Collectors.toList()); - - } - - public void destroy() { - bundleContext.removeServiceListener(this); - bundleContext.removeBundleListener(this); - if (scheduledFuture != null) { - scheduledFuture.cancel(true); - } - logger.info("Bundle watcher shutdown."); - } - - public void checkExistingBundles() { - for (Bundle bundle : bundleContext.getBundles()) { - if (bundle.getSymbolicName().startsWith("org.apache.unomi") && requiredBundles.containsKey(bundle.getSymbolicName())) { - if (bundle.getState() == Bundle.ACTIVE) { - requiredBundles.put(bundle.getSymbolicName(), true); - } else { - requiredBundles.put(bundle.getSymbolicName(), false); - } - } - } - checkStartupComplete(); - } - - @Override - public void bundleChanged(BundleEvent event) { - switch (event.getType()) { - case BundleEvent.STARTING: - break; - case BundleEvent.STARTED: - if (event.getBundle().getSymbolicName().startsWith("org.apache.unomi") && requiredBundles.containsKey(event.getBundle().getSymbolicName())) { - logger.info("Bundle {} was started.", event.getBundle().getSymbolicName()); - requiredBundles.put(event.getBundle().getSymbolicName(), true); - checkStartupComplete(); - } - break; - case BundleEvent.STOPPING: - break; - case BundleEvent.STOPPED: - if (event.getBundle().getSymbolicName().startsWith("org.apache.unomi") && requiredBundles.containsKey(event.getBundle().getSymbolicName())) { - logger.info("Bundle {} was stopped", event.getBundle().getSymbolicName()); - requiredBundles.put(event.getBundle().getSymbolicName(), false); - } - break; - default: - break; - } - } - - @Override - public void serviceChanged(ServiceEvent event) { - ServiceReference serviceReference = event.getServiceReference(); - if (serviceReference == null) { - return; - } - switch (event.getType()) { - case ServiceEvent.REGISTERED: - addStartedService(serviceReference); - checkStartupComplete(); - break; - case ServiceEvent.MODIFIED: - break; - case ServiceEvent.UNREGISTERING: - removeStartedService(serviceReference); - break; - } - } - - private void addStartedService(ServiceReference serviceReference) { - for (Filter requiredService : requiredServicesFilters) { - if (requiredService.match(serviceReference)) { - matchedRequiredServicesCount++; - } - } - } - - private void removeStartedService(ServiceReference serviceReference) { - for (Filter requiredService : requiredServicesFilters) { - if (requiredService.match(serviceReference)) { - matchedRequiredServicesCount--; - if (!shutdownMessageAlreadyDisplayed) { - System.out.println("Apache Unomi shutting down..."); - logger.info("Apache Unomi no longer available, as required service {} is shutdown !", serviceReference); - shutdownMessageAlreadyDisplayed = true; - } - startupMessageAlreadyDisplayed = false; - } - } - } - - private void displayLogsForInactiveServices() { - requiredServicesFilters.forEach(requiredServicesFilter -> { - ServiceReference[] serviceReference = new ServiceReference[0]; - String filterToString = requiredServicesFilter.toString(); - try { - serviceReference = bundleContext.getServiceReferences((String) null, filterToString); - } catch (InvalidSyntaxException e) { - logger.error("Failed to get the service reference for {}", filterToString, e); - } - if (serviceReference == null) { - logger.warn("No service found for the filter {}, some errors could happen when using the application", filterToString); - } - }); - } - - private void checkStartupComplete() { - if (!isStartupComplete()) { - if (scheduledFuture == null || scheduledFuture.isCancelled()) { - TimerTask task = new TimerTask() { - @Override - public void run() { - displayLogsForInactiveBundles(); - displayLogsForInactiveServices(); - checkStartupComplete(); - } - }; - scheduledFuture = scheduler - .scheduleWithFixedDelay(task, checkStartupStateRefreshInterval, checkStartupStateRefreshInterval, TimeUnit.SECONDS); - } - return; - } - if (scheduledFuture != null) { - scheduledFuture.cancel(true); - scheduledFuture = null; - } - if (!startupMessageAlreadyDisplayed) { - long totalStartupTime = System.currentTimeMillis() - startupTime; - if (!logoLines.isEmpty()) { - logoLines.forEach(System.out::println); - } - String buildNumber = "n/a"; - if (bundleContext.getBundle().getHeaders().get("Implementation-Build") != null) { - buildNumber = bundleContext.getBundle().getHeaders().get("Implementation-Build"); - } - String timestamp = "n/a"; - if (bundleContext.getBundle().getHeaders().get("Implementation-TimeStamp") != null) { - timestamp = bundleContext.getBundle().getHeaders().get("Implementation-TimeStamp"); - } - String versionMessage = - " " + bundleContext.getBundle().getVersion().toString() + " Build:" + buildNumber + " Timestamp:" + timestamp; - System.out.println(versionMessage); - System.out.println("--------------------------------------------------------------------------"); - System.out.println( - "Successfully started " + requiredBundles.size() + " bundles and " + requiredServicesFilters.size() + " " + "required " - + "services in " + totalStartupTime + " ms"); - logger.info("Apache Unomi version: {}", versionMessage); - logger.info("Apache Unomi successfully started {} bundles and {} required services in {} ms", requiredBundles.size(), - requiredServicesFilters.size(), totalStartupTime); - startupMessageAlreadyDisplayed = true; - shutdownMessageAlreadyDisplayed = false; - } - } - - public boolean isStartupComplete() { - return allBundleStarted() && matchedRequiredServicesCount == requiredServicesFilters.size(); - } - - private void loadLogo() { - URL logoURL = bundleContext.getBundle().getResource("logo.txt"); - if (logoURL != null) { - BufferedReader bufferedReader = null; - try { - bufferedReader = new BufferedReader(new InputStreamReader(logoURL.openStream())); - String line; - while ((line = bufferedReader.readLine()) != null) { - if (!line.trim().startsWith("#")) { - logoLines.add(line); - } - } - } catch (IOException e) { - logger.error("Error loading logo lines", e); - } finally { - if (bufferedReader != null) { - try { - bufferedReader.close(); - } catch (IOException e) { - } - } - } - } - } + boolean isStartupComplete(); } diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java similarity index 71% copy from lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java copy to lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java index 31eec3b..b57fcfa 100644 --- a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java +++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java @@ -16,6 +16,8 @@ */ package org.apache.unomi.lifecycle; +import org.apache.commons.lang3.StringUtils; +import org.apache.unomi.api.ServerInfo; import org.osgi.framework.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,12 +26,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimerTask; +import java.text.MessageFormat; +import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; @@ -37,9 +35,9 @@ import java.util.stream.Collectors; * This class listens to the global Apache Unomi bundle lifecycle, to provide statistics and state of the overall * system. It notably displays messages for successfull or unsuccessfull startups as well as startup times. */ -public class BundleWatcher implements SynchronousBundleListener, ServiceListener { +public class BundleWatcherImpl implements SynchronousBundleListener, ServiceListener, BundleWatcher { - private static final Logger logger = LoggerFactory.getLogger(BundleWatcher.class.getName()); + private static final Logger logger = LoggerFactory.getLogger(BundleWatcherImpl.class.getName()); private long startupTime; private Map<String, Boolean> requiredBundles = new ConcurrentHashMap<>(); @@ -58,6 +56,8 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener private Integer checkStartupStateRefreshInterval = 60; + private List<ServerInfo> serverInfos = new ArrayList<>(); + public void setRequiredBundles(Map<String, Boolean> requiredBundles) { this.requiredBundles = new ConcurrentHashMap<>(requiredBundles); } @@ -88,12 +88,16 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener checkExistingBundles(); bundleContext.addBundleListener(this); bundleContext.addServiceListener(this); - loadLogo(); startupTime = System.currentTimeMillis(); System.out.println("Initializing Unomi..."); logger.info("Bundle watcher initialized."); } + @Override + public List<ServerInfo> getServerInfos() { + return serverInfos; + } + private boolean allBundleStarted() { return getInactiveBundles().isEmpty(); } @@ -118,6 +122,8 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener } public void checkExistingBundles() { + serverInfos.clear(); + serverInfos.add(getBundleServerInfo(bundleContext.getBundle())); // make sure the first server info is the default one for (Bundle bundle : bundleContext.getBundles()) { if (bundle.getSymbolicName().startsWith("org.apache.unomi") && requiredBundles.containsKey(bundle.getSymbolicName())) { if (bundle.getState() == Bundle.ACTIVE) { @@ -126,6 +132,12 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener requiredBundles.put(bundle.getSymbolicName(), false); } } + if (!bundle.getSymbolicName().equals(bundleContext.getBundle().getSymbolicName())) { + ServerInfo serverInfo = getBundleServerInfo(bundle); + if (serverInfo != null) { + serverInfos.add(serverInfo); + } + } } checkStartupComplete(); } @@ -233,39 +245,44 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener } if (!startupMessageAlreadyDisplayed) { long totalStartupTime = System.currentTimeMillis() - startupTime; - if (!logoLines.isEmpty()) { + + List<String> logoLines = serverInfos.get(serverInfos.size()-1).getLogoLines(); + if (logoLines != null && !logoLines.isEmpty()) { logoLines.forEach(System.out::println); } - String buildNumber = "n/a"; - if (bundleContext.getBundle().getHeaders().get("Implementation-Build") != null) { - buildNumber = bundleContext.getBundle().getHeaders().get("Implementation-Build"); - } - String timestamp = "n/a"; - if (bundleContext.getBundle().getHeaders().get("Implementation-TimeStamp") != null) { - timestamp = bundleContext.getBundle().getHeaders().get("Implementation-TimeStamp"); - } - String versionMessage = - " " + bundleContext.getBundle().getVersion().toString() + " Build:" + buildNumber + " Timestamp:" + timestamp; - System.out.println(versionMessage); - System.out.println("--------------------------------------------------------------------------"); + System.out.println("--------------------------------------------------------------------------------------------"); + serverInfos.forEach(serverInfo -> { + String versionMessage = MessageFormat.format(" {0} {1} ({2,date,yyyy-MM-dd HH:mm:ssZ} // {3} // {4} // {5}) ", + StringUtils.rightPad(serverInfo.getServerIdentifier(), 12, " "), + serverInfo.getServerVersion(), + serverInfo.getServerBuildDate(), + serverInfo.getServerTimestamp(), + serverInfo.getServerScmBranch(), + serverInfo.getServerBuildNumber() + ); + System.out.println(versionMessage); + logger.info(versionMessage); + }); + System.out.println("--------------------------------------------------------------------------------------------"); System.out.println( - "Successfully started " + requiredBundles.size() + " bundles and " + requiredServicesFilters.size() + " " + "required " + "Server successfully started " + requiredBundles.size() + " bundles and " + requiredServicesFilters.size() + " required " + "services in " + totalStartupTime + " ms"); - logger.info("Apache Unomi version: {}", versionMessage); - logger.info("Apache Unomi successfully started {} bundles and {} required services in {} ms", requiredBundles.size(), + logger.info("Server successfully started {} bundles and {} required services in {} ms", requiredBundles.size(), requiredServicesFilters.size(), totalStartupTime); startupMessageAlreadyDisplayed = true; shutdownMessageAlreadyDisplayed = false; } } + @Override public boolean isStartupComplete() { return allBundleStarted() && matchedRequiredServicesCount == requiredServicesFilters.size(); } - private void loadLogo() { - URL logoURL = bundleContext.getBundle().getResource("logo.txt"); + private List<String> loadLogo(Bundle bundle) { + URL logoURL = bundle.getResource("unomi-logo.txt"); if (logoURL != null) { + List<String> logoLines = new ArrayList<>(); BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new InputStreamReader(logoURL.openStream())); @@ -275,6 +292,7 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener logoLines.add(line); } } + return logoLines; } catch (IOException e) { logger.error("Error loading logo lines", e); } finally { @@ -286,6 +304,52 @@ public class BundleWatcher implements SynchronousBundleListener, ServiceListener } } } + return null; + } + + public ServerInfo getBundleServerInfo(Bundle bundle) { + String serverIdentifier = "n/a"; + if (bundle.getHeaders().get("Implementation-ServerIdentifier") != null) { + serverIdentifier = bundle.getHeaders().get("Implementation-ServerIdentifier"); + } else { + return null; + } + List<String> logoLines = loadLogo(bundle); + String buildNumber = "n/a"; + if (bundle.getHeaders().get("Implementation-Build") != null) { + buildNumber = bundle.getHeaders().get("Implementation-Build"); + } + String timestamp = "n/a"; + Date buildDate = null; + if (bundle.getHeaders().get("Implementation-TimeStamp") != null) { + timestamp = bundle.getHeaders().get("Implementation-TimeStamp"); + try { + buildDate = new Date(Long.parseLong(timestamp)); + } catch (Throwable t) { + // we simply ignore this exception and keep the timestamp as it is + } + } + String scmBranch = "n/a"; + if (bundle.getHeaders().get("Implementation-ScmBranch") != null) { + scmBranch = bundle.getHeaders().get("Implementation-ScmBranch"); + } + if (bundle.getHeaders().get("Implementation-UnomiEventTypes") != null) { + // to be implemented + } + if (bundle.getHeaders().get("Implementation-UnomiCapabilities") != null) { + // to be implemented + } + ServerInfo serverInfo = new ServerInfo(); + serverInfo.setServerIdentifier(serverIdentifier); + serverInfo.setServerVersion(bundle.getVersion().toString()); + serverInfo.setServerBuildNumber(buildNumber); + serverInfo.setServerBuildDate(buildDate); + serverInfo.setServerTimestamp(timestamp); + serverInfo.setServerScmBranch(scmBranch); + if (logoLines != null) { + serverInfo.setLogoLines(logoLines); + } + return serverInfo; } } diff --git a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 1bb5a53..050a2ae 100644 --- a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -30,7 +30,7 @@ </cm:default-properties> </cm:property-placeholder> - <bean id="bundleWatcher" init-method="init" destroy-method="destroy" class="org.apache.unomi.lifecycle.BundleWatcher"> + <bean id="bundleWatcherImpl" init-method="init" destroy-method="destroy" class="org.apache.unomi.lifecycle.BundleWatcherImpl"> <property name="bundleContext" ref="blueprintBundleContext"/> <property name="requiredServices" value="${lifecycle.requiredServices}" /> <property name="checkStartupStateRefreshInterval" value="${lifecycle.checkStartupState.refresh.interval}"/> @@ -67,7 +67,7 @@ </property> </bean> - <service id="bundleWatcherService" ref="bundleWatcher"> + <service id="bundleWatcherService" ref="bundleWatcherImpl"> <interfaces> <value>org.apache.unomi.lifecycle.BundleWatcher</value> </interfaces> diff --git a/lifecycle-watcher/src/main/resources/logo.txt b/lifecycle-watcher/src/main/resources/unomi-logo.txt similarity index 93% rename from lifecycle-watcher/src/main/resources/logo.txt rename to lifecycle-watcher/src/main/resources/unomi-logo.txt index 0db2b87..1a509ad 100644 --- a/lifecycle-watcher/src/main/resources/logo.txt +++ b/lifecycle-watcher/src/main/resources/unomi-logo.txt @@ -22,5 +22,3 @@ | | / | ( <_> ) Y Y \ | |______/|___| /\____/|__|_| /__| \/ \/ - --------------------------------------------------------------------------- \ No newline at end of file diff --git a/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java b/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java index 4c5796d..2375e7b 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java +++ b/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java @@ -33,7 +33,7 @@ class UnomiPropertyTypeKeyword extends AbstractKeyword { private final ProfileService profileService; private final SchemaRegistryImpl schemaRegistry; - private static final class PropertyTypeJsonValidator extends AbstractJsonValidator { + private static final class UnomiPropertyTypeJsonValidator extends AbstractJsonValidator { String schemaPath; JsonNode schemaNode; @@ -42,7 +42,7 @@ class UnomiPropertyTypeKeyword extends AbstractKeyword { ProfileService profileService; SchemaRegistryImpl schemaRegistry; - public PropertyTypeJsonValidator(String keyword, String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext, ProfileService profileService, SchemaRegistryImpl schemaRegistry) { + public UnomiPropertyTypeJsonValidator(String keyword, String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext, ProfileService profileService, SchemaRegistryImpl schemaRegistry) { super(keyword); this.schemaPath = schemaPath; this.schemaNode = schemaNode; @@ -105,6 +105,6 @@ class UnomiPropertyTypeKeyword extends AbstractKeyword { @Override public JsonValidator newValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) throws JsonSchemaException, Exception { - return new PropertyTypeJsonValidator(this.getValue(), schemaPath, schemaNode, parentSchema, validationContext, profileService, schemaRegistry); + return new UnomiPropertyTypeJsonValidator(this.getValue(), schemaPath, schemaNode, parentSchema, validationContext, profileService, schemaRegistry); } } diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/view.json b/services/src/main/resources/META-INF/cxs/schemas/events/view.json index a85188a..1840449 100644 --- a/services/src/main/resources/META-INF/cxs/schemas/events/view.json +++ b/services/src/main/resources/META-INF/cxs/schemas/events/view.json @@ -14,7 +14,6 @@ "properties" : { "properties" : { "type" : "object", - "unomiPropertyTypes" : [ "events" ], "maxProperties": 50 }, "source" : {
