diff options
Diffstat (limited to 'graph-inventory')
20 files changed, 517 insertions, 44 deletions
diff --git a/graph-inventory/aai-client/pom.xml b/graph-inventory/aai-client/pom.xml index d95ef8d1c0..d532103c40 100644 --- a/graph-inventory/aai-client/pom.xml +++ b/graph-inventory/aai-client/pom.xml @@ -65,7 +65,7 @@ <artifactItem> <groupId>org.onap.aai.traversal</groupId> <artifactId>aai-traversal</artifactId> - <version>1.6.3</version> + <version>1.7.2</version> <outputDirectory>${project.build.directory}/antlr</outputDirectory> <includes>**/*.g4</includes> </artifactItem> @@ -93,7 +93,7 @@ <destination>${project.build.directory}/generated-sources</destination> <destinationClasspath>org.onap.aaiclient.client.generated.fluentbuilders</destinationClasspath> <builderName>AAIFluentTypeBuilder</builderName> - <swaggerLocation>${project.build.directory}/swagger/onap/aai_swagger_yaml/aai_swagger_v19.yaml</swaggerLocation> + <swaggerLocation>${project.build.directory}/swagger/onap/aai_swagger_yaml/aai_swagger_LATEST.yaml</swaggerLocation> <singularBuilderClass>org.onap.aaiclient.client.aai.entities.uri.AAIFluentSingleType</singularBuilderClass> <pluralBuilderClass>org.onap.aaiclient.client.aai.entities.uri.AAIFluentPluralType</pluralBuilderClass> <topLevelBuilderClass>org.onap.aaiclient.client.aai.entities.uri.AAIFluentTopLevelType</topLevelBuilderClass> diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/CacheControlFeature.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/CacheControlFeature.java new file mode 100644 index 0000000000..1e7c3e7f71 --- /dev/null +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/CacheControlFeature.java @@ -0,0 +1,137 @@ +package org.onap.aaiclient.client; + +import java.io.Closeable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import javax.annotation.PreDestroy; +import javax.cache.Cache; +import javax.cache.CacheManager; +import javax.cache.Caching; +import javax.cache.configuration.Factory; +import javax.cache.configuration.FactoryBuilder; +import javax.cache.configuration.MutableCacheEntryListenerConfiguration; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheWriter; +import javax.cache.spi.CachingProvider; +import javax.ws.rs.core.Feature; +import javax.ws.rs.core.FeatureContext; +import javax.ws.rs.ext.Provider; +import org.apache.cxf.jaxrs.client.cache.CacheControlClientReaderInterceptor; +import org.apache.cxf.jaxrs.client.cache.CacheControlClientRequestFilter; +import org.apache.cxf.jaxrs.client.cache.Entry; +import org.apache.cxf.jaxrs.client.cache.Key; + + +@Provider +public class CacheControlFeature implements Feature, Closeable { + private CachingProvider provider; + private CacheManager manager; + private Cache<Key, Entry> cache; + private boolean cacheResponseInputStream; + private Factory<ExpiryPolicy> expiryPolicy; + + @Override + public boolean configure(final FeatureContext context) { + // TODO: read context properties to exclude some patterns? + final Cache<Key, Entry> entryCache = createCache(context.getConfiguration().getProperties()); + context.register(new CacheControlClientRequestFilter(entryCache)); + CacheControlClientReaderInterceptor reader = new CacheControlClientReaderInterceptor(entryCache); + reader.setCacheResponseInputStream(cacheResponseInputStream); + context.register(reader); + return true; + } + + @PreDestroy // TODO: check it is called + public void close() { + for (final Closeable c : Arrays.asList(cache, manager, provider)) { + try { + if (c != null) { + c.close(); + } + } catch (final Exception e) { + // no-op + } + } + } + + private Cache<Key, Entry> createCache(final Map<String, Object> properties) { + final Properties props = new Properties(); + props.putAll(properties); + + final String prefix = this.getClass().getName() + "."; + final String uri = props.getProperty(prefix + "config-uri"); + final String name = props.getProperty(prefix + "name", this.getClass().getName()); + + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + + provider = Caching.getCachingProvider(); + try { + synchronized (contextClassLoader) { + manager = provider.getCacheManager(uri == null ? provider.getDefaultURI() : new URI(uri), + contextClassLoader, props); + if (manager.getCache(name) == null) { + final MutableConfiguration<Key, Entry> configuration = new MutableConfiguration<Key, Entry>() + .setReadThrough("true".equalsIgnoreCase(props.getProperty(prefix + "readThrough", "false"))) + .setWriteThrough( + "true".equalsIgnoreCase(props.getProperty(prefix + "writeThrough", "false"))) + .setManagementEnabled( + "true".equalsIgnoreCase(props.getProperty(prefix + "managementEnabled", "false"))) + .setStatisticsEnabled( + "true".equalsIgnoreCase(props.getProperty(prefix + "statisticsEnabled", "false"))) + .setStoreByValue( + "true".equalsIgnoreCase(props.getProperty(prefix + "storeByValue", "false"))); + + final String loader = props.getProperty(prefix + "loaderFactory"); + if (loader != null) { + @SuppressWarnings("unchecked") + Factory<? extends CacheLoader<Key, Entry>> f = + newInstance(contextClassLoader, loader, Factory.class); + configuration.setCacheLoaderFactory(f); + } + final String writer = props.getProperty(prefix + "writerFactory"); + if (writer != null) { + @SuppressWarnings("unchecked") + Factory<? extends CacheWriter<Key, Entry>> f = + newInstance(contextClassLoader, writer, Factory.class); + configuration.setCacheWriterFactory(f); + } + if (expiryPolicy != null) { + + configuration.setExpiryPolicyFactory(expiryPolicy); + } + configuration.addCacheEntryListenerConfiguration(new MutableCacheEntryListenerConfiguration( + FactoryBuilder.factoryOf(new CacheLogger()), null, true, true)); + + cache = manager.createCache(name, configuration); + } else { + cache = manager.getCache(name); + } + return cache; + } + } catch (final URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + @SuppressWarnings("unchecked") + private static <T> T newInstance(final ClassLoader contextClassLoader, final String clazz, final Class<T> cast) { + try { + return (T) contextClassLoader.loadClass(clazz).newInstance(); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + } + + public void setCacheResponseInputStream(boolean cacheStream) { + this.cacheResponseInputStream = cacheStream; + } + + public void setExpiryPolicyFactory(Factory<ExpiryPolicy> f) { + this.expiryPolicy = f; + } +} diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/CacheLogger.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/CacheLogger.java new file mode 100644 index 0000000000..f3dc610125 --- /dev/null +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/CacheLogger.java @@ -0,0 +1,53 @@ +package org.onap.aaiclient.client; + +import java.io.Serializable; +import javax.cache.event.CacheEntryCreatedListener; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.CacheEntryExpiredListener; +import javax.cache.event.CacheEntryListenerException; +import javax.cache.event.CacheEntryRemovedListener; +import javax.cache.event.CacheEntryUpdatedListener; +import org.apache.cxf.jaxrs.client.cache.Entry; +import org.apache.cxf.jaxrs.client.cache.Key; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CacheLogger implements CacheEntryExpiredListener<Key, Entry>, CacheEntryCreatedListener<Key, Entry>, + CacheEntryUpdatedListener<Key, Entry>, CacheEntryRemovedListener<Key, Entry>, Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory.getLogger(CacheLogger.class); + + @Override + public void onExpired(Iterable<CacheEntryEvent<? extends Key, ? extends Entry>> events) + throws CacheEntryListenerException { + for (CacheEntryEvent<? extends Key, ? extends Entry> event : events) { + logger.debug("{} expired key: {}", event.getSource().getName(), event.getKey().getUri()); + } + } + + @Override + public void onRemoved(Iterable<CacheEntryEvent<? extends Key, ? extends Entry>> events) + throws CacheEntryListenerException { + for (CacheEntryEvent<? extends Key, ? extends Entry> event : events) { + logger.debug("{} removed key: {}", event.getSource().getName(), event.getKey().getUri()); + } + } + + @Override + public void onUpdated(Iterable<CacheEntryEvent<? extends Key, ? extends Entry>> events) + throws CacheEntryListenerException { + for (CacheEntryEvent<? extends Key, ? extends Entry> event : events) { + logger.debug("{} updated key: {}", event.getSource().getName(), event.getKey().getUri()); + } + } + + @Override + public void onCreated(Iterable<CacheEntryEvent<? extends Key, ? extends Entry>> events) + throws CacheEntryListenerException { + for (CacheEntryEvent<? extends Key, ? extends Entry> event : events) { + logger.debug("{} created key: {}", event.getSource().getName(), event.getKey().getUri()); + } + } + +} diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/FlushCache.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/FlushCache.java new file mode 100644 index 0000000000..0f290ff620 --- /dev/null +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/FlushCache.java @@ -0,0 +1,41 @@ +package org.onap.aaiclient.client; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.cache.CacheManager; +import javax.cache.Caching; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import org.apache.cxf.jaxrs.client.cache.Key; +import org.onap.so.client.CacheProperties; + +public class FlushCache implements ClientResponseFilter { + + private static final Set<String> modifyMethods = + new HashSet<>(Arrays.asList(HttpMethod.DELETE, HttpMethod.PATCH, HttpMethod.PUT, HttpMethod.POST)); + + private final CacheProperties props; + + public FlushCache(CacheProperties props) { + this.props = props; + } + + @Override + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { + + if (responseContext.getStatus() >= 200 && responseContext.getStatus() <= 299) { + if (FlushCache.modifyMethods.contains(requestContext.getMethod())) { + + CacheManager cacheManager = Caching.getCachingProvider().getCacheManager( + Caching.getCachingProvider().getDefaultURI(), Thread.currentThread().getContextClassLoader()); + cacheManager.getCache(props.getCacheName()).remove( + new Key(requestContext.getUri(), requestContext.getAcceptableMediaTypes().get(0).toString())); + } + } + } + +} diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIClient.java index 1f747e6c8c..fc5ef86e56 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIClient.java @@ -21,10 +21,11 @@ package org.onap.aaiclient.client.aai; import java.net.URI; -import java.util.HashMap; -import java.util.Map; import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; +import org.javatuples.Pair; import org.onap.aaiclient.client.graphinventory.GraphInventoryClient; import org.onap.aaiclient.client.graphinventory.exceptions.GraphInventoryUriComputationException; import org.onap.so.client.RestClient; @@ -38,19 +39,19 @@ public class AAIClient extends GraphInventoryClient { protected AAIVersion version; protected AAIClient() { - super(AAIProperties.class, new HashMap<String, String>()); + super(AAIProperties.class, new MultivaluedHashMap<>()); } protected AAIClient(AAIVersion version) { - super(AAIProperties.class, new HashMap<String, String>()); + super(AAIProperties.class, new MultivaluedHashMap<>()); this.version = version; } - protected AAIClient(Map<String, String> additionalHeaders) { + protected AAIClient(MultivaluedMap<String, Pair<String, String>> additionalHeaders) { super(AAIProperties.class, additionalHeaders); } - protected AAIClient(AAIVersion version, Map<String, String> additionalHeaders) { + protected AAIClient(AAIVersion version, MultivaluedMap<String, Pair<String, String>> additionalHeaders) { super(AAIProperties.class, additionalHeaders); this.version = version; } diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java index 378db87d9b..d894a0fa0d 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java @@ -20,11 +20,14 @@ package org.onap.aaiclient.client.aai; +import javax.ws.rs.core.MultivaluedHashMap; +import org.javatuples.Pair; import org.onap.aaiclient.client.aai.entities.AAIResultWrapper; import org.onap.aaiclient.client.aai.entities.uri.AAIFluentTypeReverseLookup; import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory; import org.onap.aaiclient.client.graphinventory.GraphInventoryQueryClient; import org.onap.aaiclient.client.graphinventory.entities.DSLQuery; +import org.onap.aaiclient.client.graphinventory.entities.uri.Depth; import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryUri; import com.google.common.collect.ImmutableMap; @@ -32,16 +35,19 @@ public class AAIDSLQueryClient extends GraphInventoryQueryClient<AAIDSLQueryClient, DSLQuery, AAIResultWrapper, AAIObjectType> { public AAIDSLQueryClient() { - super(new AAIClient(ImmutableMap.of("X-DslApiVersion", "V2"))); + super(new AAIClient(new MultivaluedHashMap<String, Pair<String, String>>( + ImmutableMap.of("ALL", Pair.with("X-DslApiVersion", "V2"))))); + } public AAIDSLQueryClient(AAIVersion version) { - super(new AAIClient(version, ImmutableMap.of("X-DslApiVersion", "V2"))); + super(new AAIClient(version, new MultivaluedHashMap<String, Pair<String, String>>( + ImmutableMap.of("ALL", Pair.with("X-DslApiVersion", "V2"))))); } @Override protected GraphInventoryUri getQueryUri() { - return AAIUriFactory.createResourceUri(AAIObjectType.DSL); + return AAIUriFactory.createResourceUri(AAIObjectType.DSL).depth(Depth.ZERO); } diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIProperties.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIProperties.java index ac8a6e6e52..9c7798f4c5 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIProperties.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIProperties.java @@ -20,6 +20,7 @@ package org.onap.aaiclient.client.aai; +import org.onap.so.client.CacheProperties; import org.onap.so.client.RestProperties; public interface AAIProperties extends RestProperties { @@ -34,4 +35,15 @@ public interface AAIProperties extends RestProperties { public default boolean mapNotFoundToEmpty() { return true; } + + default CacheProperties getCacheProperties() { + return new AAICacheProperties() {}; + } + + public interface AAICacheProperties extends CacheProperties { + + default String getCacheName() { + return "aai-http-cache"; + } + } } diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClient.java index 0f69b0cc8f..df124efe9a 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClient.java @@ -21,8 +21,9 @@ package org.onap.aaiclient.client.aai; import java.net.URI; -import java.util.Map; import java.util.Optional; +import javax.ws.rs.core.MultivaluedMap; +import org.javatuples.Pair; import org.onap.aaiclient.client.graphinventory.GraphInventoryPatchConverter; import org.onap.aaiclient.client.graphinventory.GraphInventoryRestClient; import org.onap.logging.filter.base.ONAPComponents; @@ -31,9 +32,10 @@ import org.onap.so.client.ResponseExceptionMapper; public class AAIRestClient extends GraphInventoryRestClient { private final AAIProperties aaiProperties; - private final Map<String, String> additionalHeaders; + private final MultivaluedMap<String, Pair<String, String>> additionalHeaders; - protected AAIRestClient(AAIProperties props, URI uri, Map<String, String> additionalHeaders) { + protected AAIRestClient(AAIProperties props, URI uri, + MultivaluedMap<String, Pair<String, String>> additionalHeaders) { super(props, uri); this.aaiProperties = props; this.additionalHeaders = additionalHeaders; @@ -45,16 +47,24 @@ public class AAIRestClient extends GraphInventoryRestClient { } @Override - protected void initializeHeaderMap(Map<String, String> headerMap) { - headerMap.put("X-FromAppId", aaiProperties.getSystemName()); - headerMap.put("X-TransactionId", requestId); - headerMap.putAll(additionalHeaders); + protected void initializeHeaderMap(MultivaluedMap<String, Pair<String, String>> headerMap) { + headerMap.add("ALL", Pair.with("X-FromAppId", aaiProperties.getSystemName())); + headerMap.add("ALL", Pair.with("X-TransactionId", requestId)); + additionalHeaders.forEach((k, v) -> { + headerMap.addAll(k, v); + }); String auth = aaiProperties.getAuth(); String key = aaiProperties.getKey(); if (auth != null && !auth.isEmpty() && key != null && !key.isEmpty()) { addBasicAuthHeader(auth, key); } + + if (!aaiProperties.additionalHeaders().isEmpty()) { + aaiProperties.additionalHeaders().forEach((k, v) -> { + headerMap.addAll(k, v); + }); + } } @Override diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientI.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientI.java index 3b08761568..0e404e138b 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientI.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientI.java @@ -45,6 +45,6 @@ public interface AAIRestClientI { Optional<ServiceInstance> getServiceInstanceById(String serviceInstanceId, String serviceType, String globalSubscriberId); - void updateServiceInstance(String globalSubscriberId, String serviceType, String serviceInstanceId, + void updateServiceInstance(String serviceInstanceId, String serviceType, String globalSubscriberId, ServiceInstance serviceInstance); } diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientImpl.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientImpl.java index c31d393b36..bf9ad56da7 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientImpl.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIRestClientImpl.java @@ -106,8 +106,8 @@ public class AAIRestClientImpl implements AAIRestClientI { } @Override - public Optional<ServiceInstance> getServiceInstanceById(String globalSubscriberId, String serviceType, - String serviceInstanceId) { + public Optional<ServiceInstance> getServiceInstanceById(String serviceInstanceId, String serviceType, + String globalSubscriberId) { Response response = new AAIResourcesClient().getFullResponse( AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId) .serviceSubscription(serviceType).serviceInstance(serviceInstanceId))); @@ -115,7 +115,7 @@ public class AAIRestClientImpl implements AAIRestClientI { } @Override - public void updateServiceInstance(String globalSubscriberId, String serviceType, String serviceInstanceId, + public void updateServiceInstance(String serviceInstanceId, String serviceType, String globalSubscriberId, ServiceInstance serviceInstance) { try { new AAIResourcesClient().update(AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business() diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIVersion.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIVersion.java index 51b756464e..ab214d8672 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIVersion.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIVersion.java @@ -34,7 +34,9 @@ public enum AAIVersion implements GraphInventoryVersion { V18("v18"), V19("v19"), V20("v20"), - V21("v21"); + V21("v21"), + V22("v22"), + V23("v23"); public static final AAIVersion LATEST = AAIVersion.values()[AAIVersion.values().length - 1]; private final String value; diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryClient.java index f8f977d117..af875fa274 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryClient.java @@ -21,22 +21,22 @@ package org.onap.aaiclient.client.graphinventory; import java.net.URI; -import java.util.Map; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import org.javatuples.Pair; import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryUri; import org.onap.aaiclient.client.graphinventory.entities.uri.HttpAwareUri; import org.onap.so.client.RestClient; import org.onap.so.client.RestProperties; import org.onap.so.client.RestPropertiesLoader; -import com.google.common.collect.ImmutableMap; public abstract class GraphInventoryClient { private RestProperties props; - protected final Map<String, String> additionalHeaders; + protected final MultivaluedMap<String, Pair<String, String>> additionalHeaders; protected GraphInventoryClient(Class<? extends RestProperties> propertiesClass, - Map<String, String> additionalHeaders) { - + MultivaluedMap<String, Pair<String, String>> additionalHeaders) { RestProperties props = RestPropertiesLoader.getInstance().getNewImpl(propertiesClass); this.props = props; this.additionalHeaders = additionalHeaders; @@ -70,7 +70,7 @@ public abstract class GraphInventoryClient { public abstract String getGraphDBName(); - public Map<String, String> getAdditionalHeaders() { - return ImmutableMap.copyOf(this.additionalHeaders); + public MultivaluedMap<String, Pair<String, String>> getAdditionalHeaders() { + return new MultivaluedHashMap<>(this.additionalHeaders); } } diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java index a192e3828a..1438dbe51a 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java @@ -32,6 +32,7 @@ import org.onap.aaiclient.client.aai.entities.Results; import org.onap.aaiclient.client.graphinventory.entities.GraphInventoryResultWrapper; import org.onap.aaiclient.client.graphinventory.entities.Pathed; import org.onap.aaiclient.client.graphinventory.entities.ResourceAndUrl; +import org.onap.aaiclient.client.graphinventory.entities.uri.Depth; import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryUri; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.type.TypeReference; @@ -39,7 +40,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; public abstract class GraphInventoryQueryClient<S, I, Wrapper extends GraphInventoryResultWrapper<?>, Type extends GraphInventoryObjectType> { - private Optional<String> depth = Optional.empty(); + private Optional<Depth> depth = Optional.empty(); private boolean nodesOnly = false; private Optional<GraphInventorySubgraphType> subgraph = Optional.empty(); private GraphInventoryClient client; @@ -108,7 +109,7 @@ public abstract class GraphInventoryQueryClient<S, I, Wrapper extends GraphInven public abstract Type createType(String name, String uri); - public S depth(String depth) { + public S depth(Depth depth) { this.depth = Optional.of(depth); return (S) this; } @@ -128,7 +129,7 @@ public abstract class GraphInventoryQueryClient<S, I, Wrapper extends GraphInven protected GraphInventoryUri setupQueryParams(GraphInventoryUri uri) { GraphInventoryUri clone = uri.clone(); if (this.depth.isPresent()) { - clone.queryParam("depth", depth.get()); + clone.queryParam("depth", depth.get().toString()); } if (this.nodesOnly) { clone.queryParam("nodesOnly", ""); diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryResourcesClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryResourcesClient.java index 343e888ce1..5dbe91586a 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryResourcesClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryResourcesClient.java @@ -42,9 +42,13 @@ import org.onap.aaiclient.client.graphinventory.entities.uri.HttpAwareUri; import org.onap.aaiclient.client.graphinventory.exceptions.GraphInventoryMultipleItemsException; import org.onap.so.client.RestClient; import org.onap.so.client.RestProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class GraphInventoryResourcesClient<Self, Uri extends GraphInventoryResourceUri<?, ?>, SingleUri extends GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?>, PluralUri extends GraphInventoryPluralResourceUri<?, ?>, EdgeLabel extends GraphInventoryEdgeLabel, Wrapper extends GraphInventoryResultWrapper, TransactionalClient, SingleTransactionClient> { + private static final Logger logger = LoggerFactory.getLogger(GraphInventoryResourcesClient.class); + protected GraphInventoryClient client; protected GraphInventoryResourcesClient(GraphInventoryClient client) { @@ -147,6 +151,27 @@ public abstract class GraphInventoryResourcesClient<Self, Uri extends GraphInven String resourceVersion = (String) result.get("resource-version"); giRC = client.createClient(clone.resourceVersion(resourceVersion)); giRC.delete(); + + } + + /** + * Deletes object from GraphInventory only if exists. Automatically handles resource-version. + * + * @param uri + * @return + */ + public void deleteIfExists(SingleUri uri) { + GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> clone = (SingleUri) uri.clone(); + RestClient giRC = client.createClient(clone); + Optional<Map<String, Object>> result = giRC.get(new GenericType<Map<String, Object>>() {}); + if (result.isPresent()) { + String resourceVersion = (String) result.get().get("resource-version"); + giRC = client.createClient(clone.resourceVersion(resourceVersion)); + giRC.delete(); + } else { + logger.warn(clone.build() + " already does not exist in " + client.getGraphDBName() + + " therefore delete call not executed"); + } } /** diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryRestClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryRestClient.java index c2422085aa..6ccd1a2cab 100644 --- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryRestClient.java +++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryRestClient.java @@ -21,10 +21,16 @@ package org.onap.aaiclient.client.graphinventory; import java.net.URI; -import java.util.Map; import java.util.Optional; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; +import org.javatuples.Pair; +import org.onap.aaiclient.client.CacheControlFeature; +import org.onap.aaiclient.client.FlushCache; import org.onap.logging.filter.base.ONAPComponentsList; +import org.onap.so.client.AddCacheHeaders; +import org.onap.so.client.CacheFactory; import org.onap.so.client.ResponseExceptionMapper; import org.onap.so.client.RestClientSSL; import org.onap.so.client.RestProperties; @@ -41,11 +47,26 @@ public abstract class GraphInventoryRestClient extends RestClientSSL { super(props, Optional.of(uri)); } + + protected ClientBuilder enableCaching(ClientBuilder builder) { + builder.register(new AddCacheHeaders(props.getCacheProperties())); + builder.register(new FlushCache(props.getCacheProperties())); + CacheControlFeature cacheControlFeature = new CacheControlFeature(); + cacheControlFeature.setCacheResponseInputStream(true); + cacheControlFeature.setExpiryPolicyFactory(new CacheFactory(props.getCacheProperties())); + builder.property("org.onap.aaiclient.client.CacheControlFeature.name", + props.getCacheProperties().getCacheName()); + + builder.register(cacheControlFeature); + + return builder; + } + @Override public abstract ONAPComponentsList getTargetEntity(); @Override - protected abstract void initializeHeaderMap(Map<String, String> headerMap); + protected abstract void initializeHeaderMap(MultivaluedMap<String, Pair<String, String>> headerMap); @Override protected abstract Optional<ResponseExceptionMapper> addResponseExceptionMapper(); diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIDSLQueryClientTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIDSLQueryClientTest.java index 36fc1db57c..68858de9a4 100644 --- a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIDSLQueryClientTest.java +++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIDSLQueryClientTest.java @@ -1,7 +1,8 @@ package org.onap.aaiclient.client.aai; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.net.URISyntaxException; +import org.javatuples.Pair; import org.junit.Test; public class AAIDSLQueryClientTest { @@ -12,6 +13,6 @@ public class AAIDSLQueryClientTest { public void verifyHeadersTest() throws URISyntaxException { AAIDSLQueryClient client = new AAIDSLQueryClient(); - assertEquals("V2", client.getClient().getAdditionalHeaders().get("X-DslApiVersion")); + assertTrue(client.getClient().getAdditionalHeaders().get("ALL").contains(Pair.with("X-DslApiVersion", "V2"))); } } diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIQueryClientTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIQueryClientTest.java index 29d862478c..a3b026a420 100644 --- a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIQueryClientTest.java +++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIQueryClientTest.java @@ -54,6 +54,7 @@ import org.onap.aaiclient.client.graphinventory.GraphInventoryClient; import org.onap.aaiclient.client.graphinventory.GraphInventorySubgraphType; import org.onap.aaiclient.client.graphinventory.entities.Pathed; import org.onap.aaiclient.client.graphinventory.entities.ResourceAndUrl; +import org.onap.aaiclient.client.graphinventory.entities.uri.Depth; import org.onap.so.client.RestClient; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -92,7 +93,7 @@ public class AAIQueryClientTest { @Test public void testCreateClient() { - String depth = "testDepth"; + Depth depth = Depth.ZERO; GraphInventorySubgraphType subgraph = GraphInventorySubgraphType.STAR; aaiQueryClient.depth(depth); @@ -103,7 +104,7 @@ public class AAIQueryClientTest { doReturn(aaiUri).when(aaiUri).clone(); aaiQueryClient.setupQueryParams(aaiUri); - verify(aaiUri, times(1)).queryParam("depth", depth); + verify(aaiUri, times(1)).queryParam("depth", "0"); verify(aaiUri, times(1)).queryParam("nodesOnly", ""); verify(aaiUri, times(1)).queryParam("subgraph", subgraph.toString()); } diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java index 36ba1f3e76..03fd0acd4f 100644 --- a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java +++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java @@ -108,6 +108,27 @@ public class AAIResourcesClientTest { } @Test + public void verifyDeleteIfExists() { + AAIResourceUri path = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf("test2")); + wireMockRule.stubFor(get(urlPathEqualTo("/aai/" + AAIVersion.LATEST + path.build())) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withStatus(404))); + AAIResourcesClient client = aaiClient; + client.deleteIfExists(path); + } + + @Test + public void verifyDeleteIfExists_exists() { + AAIResourceUri path = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf("test2")); + wireMockRule.stubFor(get(urlPathEqualTo("/aai/" + AAIVersion.LATEST + path.build())) + .willReturn(aResponse().withHeader("Content-Type", "application/json") + .withBodyFile("aai/resources/mockObject.json").withStatus(200))); + wireMockRule.stubFor(delete(urlPathEqualTo("/aai/" + AAIVersion.LATEST + path.build())) + .withQueryParam("resource-version", equalTo("1234")).willReturn(aResponse().withStatus(204))); + AAIResourcesClient client = aaiClient; + client.deleteIfExists(path); + } + + @Test public void verifyBasicAuth() { AAIResourceUri path = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf("test3")); wireMockRule.stubFor(get(urlPathEqualTo("/aai/" + AAIVersion.LATEST + path.build().toString())) diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIRestClientTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIRestClientTest.java index b73454fe67..9b34095a23 100644 --- a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIRestClientTest.java +++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIRestClientTest.java @@ -25,7 +25,11 @@ import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; import static org.hamcrest.CoreMatchers.containsString; import static org.mockito.ArgumentMatchers.any; @@ -35,10 +39,13 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; -import java.util.HashMap; +import java.net.URL; +import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.Response; +import org.javatuples.Pair; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -48,6 +55,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.onap.aaiclient.client.defaultproperties.DefaultAAIPropertiesImpl; import org.onap.aaiclient.client.graphinventory.GraphInventoryPatchConverter; import org.onap.aaiclient.client.graphinventory.exceptions.GraphInventoryPatchDepthExceededException; +import org.onap.so.client.RestClient; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.junit.WireMockRule; import com.google.common.collect.ImmutableMap; @@ -68,7 +76,7 @@ public class AAIRestClientTest { @Test public void failPatchOnComplexObject() throws URISyntaxException { - AAIRestClient client = new AAIRestClient(props, new URI(""), new HashMap<String, String>()); + AAIRestClient client = new AAIRestClient(props, new URI(""), new MultivaluedHashMap<>()); this.thrown.expect(GraphInventoryPatchDepthExceededException.class); this.thrown.expectMessage(containsString("Object exceeds allowed depth for update action")); client.patch( @@ -77,7 +85,7 @@ public class AAIRestClientTest { @Test public void verifyPatchValidation() throws URISyntaxException { - AAIRestClient client = new AAIRestClient(props, new URI(""), new HashMap<String, String>()); + AAIRestClient client = new AAIRestClient(props, new URI(""), new MultivaluedHashMap<>()); AAIRestClient spy = spy(client); GraphInventoryPatchConverter patchValidatorMock = mock(GraphInventoryPatchConverter.class); doReturn(patchValidatorMock).when(spy).getPatchConverter(); @@ -90,10 +98,121 @@ public class AAIRestClientTest { @Test public void verifyAdditionalHeadersTest() throws URISyntaxException { AAIRestClient client = new AAIRestClient(new DefaultAAIPropertiesImpl(wireMockRule.port()), new URI("/test"), - ImmutableMap.of("test", "value")); + new MultivaluedHashMap<String, Pair<String, String>>( + ImmutableMap.of("ALL", Pair.with("test", "value"), "GET", Pair.with("get test", "value")))); wireMockRule.stubFor(get(urlPathEqualTo("/test")).willReturn(aResponse().withStatus(200))); client.get(); wireMockRule.verify(getRequestedFor(urlPathEqualTo("/test")).withHeader("X-FromAppId", equalTo("MSO")) - .withHeader("X-TransactionId", matching(".*")).withHeader("test", equalTo("value"))); + .withHeader("X-TransactionId", matching(".*")).withHeader("test", equalTo("value")) + .withHeader("get test", equalTo("value"))); + } + + + @Test + public void cacheGetTest() throws URISyntaxException, InterruptedException { + + wireMockRule.stubFor(get(urlPathMatching("/cached")) + .willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/plain").withBody("value"))); + + AAIProperties props = new AAIProperties() { + + @Override + public URL getEndpoint() throws MalformedURLException { + return new URL(String.format("http://localhost:%s", wireMockRule.port())); + } + + @Override + public String getSystemName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isCachingEnabled() { + return true; + } + + @Override + public AAIVersion getDefaultVersion() { + return AAIVersion.LATEST; + } + + @Override + public String getAuth() { + return null; + } + + @Override + public String getKey() { + return null; + } + + }; + RestClient client = new AAIRestClient(props, new URI("/cached"), new MultivaluedHashMap<>()); + + Response response = client.get(); + + response.readEntity(String.class); + response = client.get(); + response.readEntity(String.class); + verify(1, getRequestedFor(urlEqualTo("/cached"))); + + } + + @Test + public void cachePutTest() throws URISyntaxException, InterruptedException { + + wireMockRule.stubFor(put(urlPathMatching("/cached/1")).willReturn(aResponse().withStatus(200))); + + wireMockRule.stubFor(get(urlPathMatching("/cached/1")) + .willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody("{}"))); + + AAIProperties props = new AAIProperties() { + + @Override + public URL getEndpoint() throws MalformedURLException { + return new URL(String.format("http://localhost:%s", wireMockRule.port())); + } + + @Override + public String getSystemName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isCachingEnabled() { + return true; + } + + @Override + public AAIVersion getDefaultVersion() { + return AAIVersion.LATEST; + } + + @Override + public String getAuth() { + return null; + } + + @Override + public String getKey() { + return null; + } + + }; + + RestClient client = new AAIRestClient(props, new URI("/cached/1"), new MultivaluedHashMap<>()); + + + Response response = client.get(); + + response.readEntity(String.class); + client.put("wow"); + + client.get(); + response.readEntity(String.class); + verify(2, getRequestedFor(urlEqualTo("/cached/1"))); + } } diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java index ec09af8a4e..fc42d9ca0d 100644 --- a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java +++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java @@ -1,6 +1,10 @@ package org.onap.graphinventory.generate; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -26,6 +30,9 @@ public class SwaggerConverter { } public Map<String, ObjectType> getDoc(String swaggerLocation) throws JsonProcessingException { + + + swaggerLocation = processLocation(swaggerLocation); Swagger swagger = new SwaggerParser().read(swaggerLocation); Map<String, Path> paths = swagger.getPaths().entrySet().stream() @@ -168,4 +175,19 @@ public class SwaggerConverter { return output; } + + private String processLocation(String swaggerLocation) { + + java.nio.file.Path path = Paths.get(swaggerLocation); + try { + return Files.list(path.getParent()) + .filter(it -> it.getFileName().toString() + .matches(path.getFileName().toString().replaceFirst("LATEST", "v\\\\\\d+"))) + .sorted(Comparator.reverseOrder()).map(it -> it.toString()).findFirst().orElseGet(null); + } catch (IOException e) { + log.error(e); + } + + return null; + } } |