diff options
Diffstat (limited to 'src/main/java/org/onap/crud/util')
4 files changed, 184 insertions, 16 deletions
diff --git a/src/main/java/org/onap/crud/util/CrudServiceConstants.java b/src/main/java/org/onap/crud/util/CrudServiceConstants.java index 3a02852..ae5b464 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceConstants.java +++ b/src/main/java/org/onap/crud/util/CrudServiceConstants.java @@ -39,4 +39,5 @@ public class CrudServiceConstants { public static final String CRD_COLLECTION_PROPERTIES_KEY = "crud.collection.properties.key"; public static final String CRD_RESERVED_VERSION = "_reserved_version"; public static final String CRD_RESERVED_NODE_TYPE = "_reserved_aai-type"; + public static final String CRD_HEADER_ETAG = "etag"; } diff --git a/src/main/java/org/onap/crud/util/CrudServiceUtil.java b/src/main/java/org/onap/crud/util/CrudServiceUtil.java index 6c251bc..6b5cdcd 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceUtil.java +++ b/src/main/java/org/onap/crud/util/CrudServiceUtil.java @@ -20,6 +20,15 @@ */ package org.onap.crud.util; +import java.util.AbstractMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; import org.onap.aai.db.props.AAIProperties; import org.onap.crud.exception.CrudException; import org.onap.schema.OxmModelLoader; @@ -29,15 +38,6 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; -import java.util.AbstractMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.Status; - public class CrudServiceUtil { private static Gson gson = new Gson(); @@ -54,13 +54,13 @@ public class CrudServiceUtil { } else if (clazz.isAssignableFrom(Double.class)) { return Double.parseDouble(value); } else if (clazz.isAssignableFrom(Boolean.class)) { - + // If the value is an IN/OUT direction, this gets seen as a boolean, so // check for that first. if (value.equals("OUT") || value.equals("IN")) { return value; } - + if (!value.equals("true") && !value.equals("false")) { throw new CrudException("Invalid propertry value: " + value, Status.BAD_REQUEST); } @@ -82,7 +82,7 @@ public class CrudServiceUtil { throw new CrudException(e); } } - + /** * This method will merge header property from app id in request payload if not already populated * @param propertiesFromRequest @@ -104,12 +104,12 @@ public class CrudServiceUtil { if(!propertyKeys.contains(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH)) { properties.add(new AbstractMap.SimpleEntry<String, JsonElement>(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, - (JsonElement)(new JsonPrimitive(sourceOfTruth)))); + (new JsonPrimitive(sourceOfTruth)))); } if(isAdd && !propertyKeys.contains(AAIProperties.SOURCE_OF_TRUTH)) { properties.add(new AbstractMap.SimpleEntry<String, JsonElement>(AAIProperties.SOURCE_OF_TRUTH, - (JsonElement)(new JsonPrimitive(sourceOfTruth)))); + (new JsonPrimitive(sourceOfTruth)))); } Object[] propArray = properties.toArray(); @@ -117,7 +117,7 @@ public class CrudServiceUtil { sb.append("{"); boolean first=true; for(int i=0; i<propArray.length; i++) { - + Map.Entry<String, JsonElement> entry = (Entry<String, JsonElement>) propArray[i]; if(!first) { sb.append(","); @@ -126,7 +126,17 @@ public class CrudServiceUtil { first=false; } sb.append("}"); - + return gson.fromJson(sb.toString(), JsonElement.class); } + + public static EntityTag getETagFromHeader(MultivaluedMap<String, String> headers) { + EntityTag entityTag = null; + if (headers != null && headers.containsKey(CrudServiceConstants.CRD_HEADER_ETAG)) { + String value = headers.getFirst(CrudServiceConstants.CRD_HEADER_ETAG); + entityTag = new EntityTag(value.replace("\"", "")); + } + return entityTag; + } + } diff --git a/src/main/java/org/onap/crud/util/HashGenerator.java b/src/main/java/org/onap/crud/util/HashGenerator.java new file mode 100644 index 0000000..02558fa --- /dev/null +++ b/src/main/java/org/onap/crud/util/HashGenerator.java @@ -0,0 +1,65 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +/** + * Generates a sha 256 hash + */ +public class HashGenerator { + + private MessageDigest messageDigest; + + public HashGenerator() throws NoSuchAlgorithmException { + this.messageDigest = MessageDigest.getInstance("SHA-256"); + } + + /** + * Generates a SHA 256 hash as a hexadecimal string for the inputs. + * Calls toString on the input objects to convert into a byte stream. + * @param values + * @return SHA 256 hash of the inputs as a hexadecimal string. + * @throws IOException + */ + public String generateSHA256AsHex(Object... values) throws IOException { + byte[] bytes = convertToBytes(values); + byte[] digest = messageDigest.digest(bytes); + StringBuilder result = new StringBuilder(); + for (byte byt : digest) result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1)); + return result.toString(); + } + + private byte[] convertToBytes(Object... values) throws IOException { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(bos)) { + for (Object object : values) { + out.writeObject(object.toString()); + } + return bos.toByteArray(); + } + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/crud/util/etag/EtagGenerator.java b/src/main/java/org/onap/crud/util/etag/EtagGenerator.java new file mode 100644 index 0000000..b288b78 --- /dev/null +++ b/src/main/java/org/onap/crud/util/etag/EtagGenerator.java @@ -0,0 +1,92 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.util.etag; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import org.onap.crud.event.GraphEventEdge; +import org.onap.crud.event.GraphEventVertex; +import org.onap.crud.util.HashGenerator; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * Computes hash for GraphEventVertex and GraphEventEdge + */ +public class EtagGenerator { + + private static final String AAI_LAST_MOD_TS = "aai-last-mod-ts"; + private final HashGenerator hashGenerator; + + public EtagGenerator() throws NoSuchAlgorithmException { + this.hashGenerator = new HashGenerator(); + } + + /** + * Takes in the GraphEventVertex for which the hash is to be computed. + * @param GraphEventVertex + * @return hash for the GraphEventVertex + * @throws IOException + */ + public String computeHashForVertex(GraphEventVertex graphEventVertex) throws IOException { + return hashGenerator.generateSHA256AsHex(graphEventVertex.getId(), graphEventVertex.getType(), convertPropertiesToMap(graphEventVertex.getProperties())); + } + + /** + * Takes in the GraphEventEdge for which the hash is to be computed. + * @param GraphEventEdge + * @return hash for the GraphEventEdge + * @throws IOException + */ + public String computeHashForEdge(GraphEventEdge graphEventEdge) throws IOException { + return hashGenerator.generateSHA256AsHex(graphEventEdge.getId(), graphEventEdge.getType(), + convertPropertiesToMap(graphEventEdge.getProperties()), + computeHashForVertex(graphEventEdge.getSource()), computeHashForVertex(graphEventEdge.getTarget())); + } + + private Map<String, Object> convertPropertiesToMap(JsonElement properties) { + Map<String, Object> propertiesMap = new HashMap<>(); + if (null != properties) { + JsonObject propsObject = properties.getAsJsonObject(); + for (Entry<String, JsonElement> props : propsObject.entrySet()) { + String key = props.getKey(); + String value = props.getValue().getAsString(); + propertiesMap.put(key, value); + } + } + return filterAndSortProperties(propertiesMap); + } + + private Map<String, Object> filterAndSortProperties(Map<String, Object> properties) { + return properties + .entrySet() + .stream() + .filter(x -> !x.getKey().equals(AAI_LAST_MOD_TS)) + .sorted((x, y) -> x.getKey().compareTo(y.getKey())) + .collect(LinkedHashMap::new, + (m, e) -> m.put(e.getKey(), e.getValue()), + Map::putAll); + } +}
\ No newline at end of file |