X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=restconf-client%2Fprovider%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fccsdk%2Fsli%2Fplugins%2Frestconfapicall%2FRestconfApiCallNode.java;h=620df282f43447c41e6b63f253d56f025134b972;hb=a7430938d2b83b6fe9b03360ff54206fd1259885;hp=c5f73305bb9a5b942ba3e348f849673a35f877ae;hpb=c8a20b7cdc2b563e1ea86a9e25f4ac0e748995f9;p=ccsdk%2Fsli%2Fplugins.git diff --git a/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java b/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java index c5f73305..620df282 100644 --- a/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java +++ b/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java @@ -20,13 +20,33 @@ package org.onap.ccsdk.sli.plugins.restconfapicall; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonWriter; + +import javax.ws.rs.core.UriBuilder; +import java.io.StringWriter; +import java.io.Writer; +import java.net.SocketException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; import org.onap.ccsdk.sli.core.sli.SvcLogicException; import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; +import org.onap.ccsdk.sli.plugins.restapicall.Format; import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse; import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode; -import org.onap.ccsdk.sli.plugins.restapicall.RetryException; -import org.onap.ccsdk.sli.plugins.restapicall.RetryPolicy; +import org.onap.ccsdk.sli.plugins.restapicall.XmlParser; import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatSerializer; import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatSerializerContext; import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerFactory; @@ -35,29 +55,28 @@ import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.MdsalSerializerHe import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.SerializerHelper; import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters; import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeSerializer; +import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace; import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeSerializer; -import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; import org.opendaylight.restconf.common.context.InstanceIdentifierContext; +import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.ws.rs.core.UriBuilder; -import java.net.SocketException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import static com.google.common.base.Strings.repeat; import static java.lang.String.format; +import static java.lang.String.valueOf; import static org.apache.commons.lang3.StringUtils.join; -import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.POST; +import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.DELETE; +import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.GET; +import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PATCH; import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PUT; import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.ATTEMPTS_MSG; +import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COLON; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COMMA; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COMM_FAIL; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HEADER; @@ -74,9 +93,15 @@ import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RETRY_ import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RETRY_FAIL; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.UPDATED_URL; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getSchemaCtxFromDir; +import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getUpdatedXmlReq; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getYangParameters; import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.parseUrl; import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfListenerFactory.instance; +import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR; +import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.UTF_HEADER; +import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_TREE_ERR; +import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlWriter; +import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getModuleNamespace; import static org.osgi.framework.FrameworkUtil.getBundle; /** @@ -91,9 +116,25 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { RestconfApiCallNode.class); /** - * Creates an instance of restconf api call node. + * Rest api call node service instance */ - public RestconfApiCallNode() { + private RestapiCallNode restapiCallNode; + + /** + * Creates an instance of restconf api call node with restapi call node. + * + * @param r restapi call node + */ + public RestconfApiCallNode(RestapiCallNode r) { + this.restapiCallNode = r; + } + + /** + * Returns the restapi call node instance. + * @return + */ + public RestapiCallNode getRestapiCallNode() { + return restapiCallNode; } /** @@ -121,15 +162,10 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { */ public void sendRequest(Map paramMap, SvcLogicContext ctx, Integer retryCount) throws SvcLogicException { - RestapiCallNode rest = new RestapiCallNode(); - RetryPolicy retryPolicy = null; + RestapiCallNode rest = getRestapiCallNode(); HttpResponse r = new HttpResponse(); try { YangParameters p = getYangParameters(paramMap); - if (p.partner != null) { - retryPolicy = rest.getRetryPolicyStore() - .getRetryPolicy(p.partner); - } String pp = p.responsePrefix != null ? p.responsePrefix + '.' : ""; Map props = new HashMap<>((Map)ctx.toProperties()); @@ -137,8 +173,11 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { InstanceIdentifierContext insIdCtx = getInsIdCtx(p, uri); String req = null; - if (p.httpMethod == POST || p.httpMethod == PUT) { + if (p.httpMethod != GET && p.httpMethod != DELETE) { req = serializeRequest(props, p, uri, insIdCtx); + if (p.httpMethod == PUT || p.httpMethod == PATCH) { + updateReq(req, p, insIdCtx); + } } if (req == null && p.requestBody != null) { req = p.requestBody; @@ -151,10 +190,14 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { String response = getResponse(ctx, p, pp, r); if (response != null) { - Map resProp = serializeResponse( - p, uri, response, insIdCtx); - for (Map.Entry pro : resProp.entrySet()) { - ctx.setAttribute(pro.getKey(), pro.getValue()); + try { + Map resProp = serializeResponse( + p, uri, response, insIdCtx); + for (Map.Entry pro : resProp.entrySet()) { + ctx.setAttribute(pro.getKey(), pro.getValue()); + } + } catch (SvcLogicException e) { + convertToNormalRes(ctx, p, pp, response); } } } catch (SvcLogicException e) { @@ -165,36 +208,33 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { log.error(REQ_ERR + e.getMessage(), e); String prefix = parseParam(paramMap, RES_PRE, false, null); - if (retryPolicy == null || shouldRetry == false) { - setFailureResponseStatus(ctx, prefix, e.getMessage(), r); - } else { - if (retryCount == null) { - retryCount = 0; - } - log.debug(format(ATTEMPTS_MSG, retryCount, - retryPolicy.getMaximumRetries())); - try { - retryCount = retryCount + 1; - if (retryCount < retryPolicy.getMaximumRetries() + 1) { - setRetryUri(paramMap, retryPolicy); - log.debug(format(RETRY_COUNT, retryCount, retryPolicy - .getMaximumRetries())); - sendRequest(paramMap, ctx, retryCount); - } else { - log.debug(MAX_RETRY_ERR); - setFailureResponseStatus(ctx, prefix, - e.getMessage(), r); - } - } catch (Exception ex) { - log.error(NO_MORE_RETRY, ex); - setFailureResponseStatus(ctx, prefix, RETRY_FAIL, r); - } - } + setFailureResponseStatus(ctx, prefix, e.getMessage()); } if (r != null && r.code >= 300) { - throw new SvcLogicException( - String.valueOf(r.code) + ": " + r.message); + throw new SvcLogicException(valueOf(r.code) + + COLON + " " + r.message); + } + } + + private void convertToNormalRes(SvcLogicContext ctx , + YangParameters p, String pp, String body) + throws SvcLogicException { + if (p.convertResponse) { + Map mm = null; + if (p.format == Format.XML) { + mm = XmlParser.convertToProperties(body, p.listNameList); + } else if (p.format == Format.JSON) { + mm = org.onap.ccsdk.sli.plugins.restapicall.JsonParser + .convertToProperties(body); + } + + if (mm != null) { + for (Map.Entry entry : mm.entrySet()) { + ctx.setAttribute(pp + entry.getKey(), + entry.getValue()); + } + } } } @@ -208,7 +248,7 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { * @return JSON or XML message to be sent * @throws SvcLogicException when serializing the request fails */ - protected String serializeRequest(Map properties, + public String serializeRequest(Map properties, YangParameters params, String uri, InstanceIdentifierContext insIdCtx) throws SvcLogicException { @@ -232,9 +272,9 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { * @return response message as properties * @throws SvcLogicException when serializing the response fails */ - protected Map serializeResponse(YangParameters params, - String uri, String response, - InstanceIdentifierContext insIdCtx) + public Map serializeResponse(YangParameters params, + String uri, String response, + InstanceIdentifierContext insIdCtx) throws SvcLogicException { PropertiesNodeSerializer propSer = new MdsalPropertiesNodeSerializer( insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri); @@ -260,9 +300,7 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { String uri) throws SvcLogicException { SchemaContext context = getSchemaContext(params); - ControllerContext contCtx = ControllerContext.getInstance(); - contCtx.onGlobalContextUpdated(context); - return contCtx.toInstanceIdentifier(uri); + return ParserIdentifier.toInstanceIdentifier(uri, context, null); } /** @@ -299,9 +337,9 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { * @param res http response * @return response message body */ - private String getResponse(SvcLogicContext ctx, YangParameters params, + public String getResponse(SvcLogicContext ctx, YangParameters params, String pre, HttpResponse res) { - ctx.setAttribute(pre + RES_CODE, String.valueOf(res.code)); + ctx.setAttribute(pre + RES_CODE, valueOf(res.code)); ctx.setAttribute(pre + RES_MSG, res.message); if (params.dumpHeaders && res.headers != null) { @@ -324,39 +362,123 @@ public class RestconfApiCallNode implements SvcLogicJavaPlugin { * @param ctx service logic context * @param prefix prefix to be added * @param errMsg error message - * @param res http response */ private void setFailureResponseStatus(SvcLogicContext ctx, String prefix, - String errMsg, HttpResponse res) { - res = new HttpResponse(); + String errMsg) { + HttpResponse res = new HttpResponse(); res.code = 500; res.message = errMsg; - ctx.setAttribute(prefix + RES_CODE, String.valueOf(res.code)); + ctx.setAttribute(prefix + RES_CODE, valueOf(res.code)); ctx.setAttribute(prefix + RES_MSG, res.message); } /** - * Sets the retry URI to the param map from the retry policies different - * host. + * Updates request message for JSON and XML data format, when the HTTP + * method points it as PUT or PATCH. * - * @param paramMap parameter map - * @param retryPolicy retry policy - * @throws URISyntaxException when new URI creation fails - * @throws RetryException when retry policy cannot give another host + * @param req current request message + * @param p YANG parameters + * @param insIdCtx instance identifier context + * @return update request message + * @throws SvcLogicException when the data format type is wrong */ - private void setRetryUri(Map paramMap, - RetryPolicy retryPolicy) - throws URISyntaxException, RetryException { - URI uri = new URI(paramMap.get(REST_API_URL)); - String hostName = uri.getHost(); - String retryString = retryPolicy.getNextHostName(uri.toString()); - - URI uriTwo = new URI(retryString); - URI retryUri = UriBuilder.fromUri(uri).host(uriTwo.getHost()).port( - uriTwo.getPort()).scheme(uriTwo.getScheme()).build(); - - paramMap.put(REST_API_URL, retryUri.toString()); - log.debug(UPDATED_URL + retryUri.toString()); - log.debug(format(COMM_FAIL, hostName, retryString)); + public String updateReq(String req, YangParameters p, + InstanceIdentifierContext insIdCtx) + throws SvcLogicException { + + SchemaNode schemaNode = insIdCtx.getSchemaNode(); + Namespace modNs = getModuleNamespace(schemaNode.getQName(), + insIdCtx.getSchemaContext()); + String nodeName = schemaNode.getQName().getLocalName(); + + switch (p.format) { + case JSON: + return getUpdatedJsonReq(req, nodeName, modNs.moduleName()); + + case XML: + return getXmlReqForPutOp(req, nodeName, modNs.moduleNs()); + + default: + throw new SvcLogicException(format(FORMAT_ERR, p.format)); + } + } + + /** + * Returns the updated JSON request message, when the HTTP method + * points to PUT or PATCH. + * + * @param req current JSON request message + * @param nodeName root node name + * @param modName module name of the root node + * @return update JSON request message + */ + private String getUpdatedJsonReq(String req, String nodeName, + String modName) { + Writer writer = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(writer); + jsonWriter.setIndent(repeat(" ", 4)); + + JsonParser jsonParser = new JsonParser(); + JsonObject oldJson = (JsonObject)jsonParser.parse(req); + oldJson = remChildModName(oldJson, modName); + JsonObject newJson = new JsonObject(); + newJson.add(modName + COLON + nodeName, oldJson.deepCopy()); + + Gson gson= new Gson(); + gson.toJson(newJson, jsonWriter); + return writer.toString(); + } + + /** + * Removes module name from all the updated first level child node, if it + * is same as the root node added. + * + * @param oldJson JSON object for old request + * @param modName module name of root node + * @return JSON object for old request with updated child module name + */ + private JsonObject remChildModName(JsonObject oldJson, String modName) { + Iterator> it = oldJson.entrySet().iterator(); + Map m = new HashMap<>(); + while (it.hasNext()) { + Map.Entry jNode = it.next(); + if (jNode.getKey().contains(COLON)) { + String[] modArr = jNode.getKey().split(COLON); + if (modArr[0].equals(modName)) { + it.remove(); + m.put(modArr[1], jNode.getValue()); + } + } + } + if (!m.isEmpty()) { + for (Map.Entry element : m.entrySet()) { + oldJson.add(element.getKey(), element.getValue()); + } + } + return oldJson; + } + + /** + * Returns the updated XML request message, when the HTTP method points + * to PUT or PATCH. + * + * @param req current JSON request message + * @param nodeName root node name + * @param modNs module namespace of the root node + * @return update JSON request message + * @throws SvcLogicException when XML parsing fails + */ + private String getXmlReqForPutOp(String req, String nodeName, + URI modNs) throws SvcLogicException { + req = getUpdatedXmlReq(req, nodeName, modNs.toString()); + Document oldDoc; + try { + oldDoc = DocumentHelper.parseText(req); + } catch (DocumentException e) { + throw new SvcLogicException(XML_TREE_ERR, e); + } + Writer writer = getXmlWriter( + UTF_HEADER + oldDoc.getRootElement().asXML(), "4"); + return writer.toString(); } }