diff options
Diffstat (limited to 'sli/provider/src/main')
8 files changed, 3130 insertions, 0 deletions
diff --git a/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java new file mode 100755 index 000000000..d3ab6c33a --- /dev/null +++ b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java @@ -0,0 +1,1274 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.ccsdk.sli.core.sli.provider; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisherBuilder; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MdsalHelper { + + private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class); + private static Properties yangMappingProperties = new Properties(); + private static final String IP_ADDRESS="IpAddress"; + private static final String IPV4_ADDRESS="Ipv4Address"; + private static final String IPV6_ADDRESS="Ipv6Address"; + + private static final String IP_PREFIX="IpPrefix"; + private static final String SETTING_PROPERTY="Setting property "; + private static final String BUILDER="-builder"; + + @Deprecated + public static void setProperties(Properties input) { + setYangMappingProperties(input); + } + + @Deprecated + public static void setYangMappingProperties(Properties properties) { + for (Object propNameObj : properties.keySet()) { + String propName = (String) propNameObj; + MdsalHelper.yangMappingProperties.setProperty(propName, properties.getProperty(propName)); + } + } + + @Deprecated + public static void loadProperties(String propertiesFile) { + File file = new File(propertiesFile); + Properties properties = new Properties(); + if (file.isFile() && file.canRead()) { + try (InputStream input = new FileInputStream(file)) { + properties.load(input); + MdsalHelper.setYangMappingProperties(properties); + LOG.info("Loaded properties from " + propertiesFile); + } catch (Exception e) { + LOG.error("Failed to load properties " + propertiesFile + "\n", e); + } + } else { + LOG.error("Failed to load the properties file " + propertiesFile + "\n"); + LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n"); + } + } + + public static Properties toProperties(Properties props, Object fromObj) { + return toProperties(props, fromObj, false); + } + + public static Properties toProperties(Properties props, Object fromObj, Boolean useLegacyEnumerationMapping) { + Class fromClass = null; + + if (fromObj != null) { + fromClass = fromObj.getClass(); + } + return toProperties(props, "", fromObj, fromClass, useLegacyEnumerationMapping); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj) { + return toProperties(props, pfx, fromObj, false); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj, Boolean useLegacyEnumerationMapping) { + Class fromClass = null; + + if (fromObj != null) { + fromClass = fromObj.getClass(); + } + + return toProperties(props, pfx, fromObj, fromClass, useLegacyEnumerationMapping); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) { + return toProperties(props, pfx, fromObj, fromClass, false); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass, Boolean useLegacyEnumerationMapping) { + + if (fromObj == null) { + return props; + } + String simpleTypeName = fromObj.getClass().getTypeName(); + simpleTypeName = simpleTypeName.substring(simpleTypeName.lastIndexOf(".") + 1); + + if (classHasSpecialHandling(simpleTypeName)) { + try { + + Method m = fromClass.getMethod(getStringValueMethod(simpleTypeName), null); + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retValue = m.invoke(fromObj); + if (retValue != null) { + String propVal = null; + if (IP_ADDRESS.equals(simpleTypeName) || IP_PREFIX.equals(simpleTypeName) + || IPV4_ADDRESS.equals(simpleTypeName) || IPV6_ADDRESS.equals(simpleTypeName)) { + propVal = (String) retValue; + } else if ("Dscp".equals(simpleTypeName)) { + propVal = String.valueOf((short) retValue); + } else if ("PortNumber".equals(simpleTypeName)) { + propVal = String.valueOf((Integer) retValue); + } + LOG.debug(SETTING_PROPERTY + pfx + " to " + propVal); + props.setProperty(pfx, propVal); + } + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + + ".getValue() to Properties entry", e); + } + } else if (fromObj instanceof List) { + List fromList = (List) fromObj; + + for (int i = 0; i < fromList.size(); i++) { + toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass, useLegacyEnumerationMapping); + } + props.setProperty(pfx + "_length", Integer.toString(fromList.size())); + + } else if (isYangGenerated(fromClass)) { + // Class is yang generated. + + String propNamePfx = null; + + // If called from a list (so prefix ends in ']'), don't + // add class name again + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx; + } else { + propNamePfx = toLowerHyphen(fromClass.getSimpleName()); + } + + if (propNamePfx.endsWith(BUILDER)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // save from + + int numGetters = 0; + String lastGetterName = null; + String propVal = null; + + for (Method m : fromClass.getMethods()) { + if (isGetter(m)) { + + numGetters++; + lastGetterName = m.getName(); + + Class returnType = m.getReturnType(); + String fieldName; + if (m.getName().startsWith("get")) { + fieldName = toLowerHyphen(m.getName().substring(3)); + } else { + + fieldName = toLowerHyphen(m.getName().substring(2)); + } + + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + + // Is the return type a yang generated class? + if (isYangGenerated(returnType)) { + // Is it an enum? + if (returnType.isEnum()) { + // Return type is a typedef. Save its value. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + Object retValue = m.invoke(fromObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + String propName = propNamePfx + "." + fieldName; + if (useLegacyEnumerationMapping) { + propVal = retValue.toString(); + props.setProperty(propName, mapEnumeratedValue(fieldName, propVal)); + } else { + Method method = retValue.getClass().getMethod("getName"); + String yangValue = (String) method.invoke(retValue); + props.setProperty(propName, yangValue); + } + + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert Yang-generated enum returned by " + + fromClass.getName() + "." + m.getName() + "() to Properties entry", + e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retValue = m.invoke(fromObj); + + if (retValue instanceof byte[]) { + retValue = new String((byte[]) retValue, "UTF-8"); + } + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + toProperties(props, propNamePfx + "." + fieldName, retValue, returnType, useLegacyEnumerationMapping); + } + } catch (Exception e) { + + if (m.getName().equals("getKey")) { + LOG.trace("Caught " + e.getClass().getName() + + " exception trying to convert results from getKey() - ignoring"); + } else { + LOG.error("Caught exception trying to convert Yang-generated class returned by" + + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } + } else if (returnType.equals(Class.class)) { + + } else if (List.class.isAssignableFrom(returnType)) { + + // This getter method returns a list. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retList = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + // Figure out what type of elements are stored in + // this array. + Type paramType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0]; + toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType, useLegacyEnumerationMapping); + } catch (Exception e) { + LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "." + + m.getName() + "() to Properties entry", e); + } + + } else { + + // Method returns something that is not a List and not + // yang-generated. + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object propValObj = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (propValObj != null) { + if (propValObj instanceof byte[]) { + propVal = new String((byte[]) propValObj, "UTF-8"); + } else { + propVal = propValObj.toString(); + } + LOG.debug(SETTING_PROPERTY + propName + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + if (m.getName().equals("getKey")) { + LOG.trace("Caught " + e.getClass().getName() + + " exception trying to convert results from getKey() - ignoring"); + } else { + LOG.error("Caught exception trying to convert value returned by" + fromClass.getName() + + "." + m.getName() + "() to Properties entry", e); + } + } + } + + } + } + + // End of method loop. If there was only one getter, named + // "getValue", then + // set value identified by "prefix" to that one value. + if ((numGetters == 1) && ("getValue".equals(lastGetterName))) { + props.setProperty(propNamePfx, propVal); + } + } else { + // Class is not yang generated and not a list + // It must be an element of a leaf list - set "prefix" to value + String fromVal = null; + if (fromObj instanceof byte[]) { + try { + fromVal = new String((byte[]) fromObj, "UTF-8"); + } catch (Exception e) { + LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e); + fromVal = fromObj.toString(); + } + + } else { + fromVal = fromObj.toString(); + } + LOG.debug(SETTING_PROPERTY + pfx + " to " + fromVal); + props.setProperty(pfx, fromVal); + } + + return (props); + } + + public static Object toBuilder(Properties props, Object toObj) { + + return (toBuilder(props, "", toObj)); + } + + public static List toList(Properties props, String pfx, List toObj, Class elemType) { + + int maxIdx = -1; + boolean foundValue = false; + + if (props.containsKey(pfx + "_length")) { + try { + int listLength = Integer.parseInt(props.getProperty(pfx + "_length")); + + if (listLength > 0) { + maxIdx = listLength - 1; + } + } catch (NumberFormatException e) { + LOG.info("Invalid input for length ", e); + } + } + + String arrayKey = pfx + "["; + int arrayKeyLength = arrayKey.length(); + if (maxIdx == -1) { + // Figure out array size + for (Object pNameObj : props.keySet()) { + String key = (String) pNameObj; + + if (key.startsWith(arrayKey)) { + String idxStr = key.substring(arrayKeyLength); + int endloc = idxStr.indexOf("]"); + if (endloc != -1) { + idxStr = idxStr.substring(0, endloc); + } + try { + int curIdx = Integer.parseInt(idxStr); + if (curIdx > maxIdx) { + maxIdx = curIdx; + } + } catch (Exception e) { + LOG.error("Illegal subscript in property {}", key, e); + } + + } + } + } + + for (int i = 0; i <= maxIdx; i++) { + + String curBase = pfx + "[" + i + "]"; + + if (isYangGenerated(elemType)) { + + if (isIpAddress(elemType)) { + + String curValue = props.getProperty(curBase, ""); + + if ((curValue != null) && (curValue.length() > 0)) { + toObj.add(IpAddressBuilder.getDefaultInstance(curValue)); + foundValue = true; + } + } else if (isIpv4Address(elemType)) { + String curValue = props.getProperty(curBase, ""); + + if ((curValue != null) && (curValue.length() > 0)) { + toObj.add(new Ipv4Address(curValue)); + foundValue = true; + } + + } else if (isIpv6Address(elemType)) { + String curValue = props.getProperty(curBase, ""); + + if ((curValue != null) && (curValue.length() > 0)) { + toObj.add(new Ipv6Address(curValue)); + foundValue = true; + } + } else if (isIpPrefix(elemType)) { + + String curValue = props.getProperty(curBase, ""); + + if ((curValue != null) && (curValue.length() > 0)) { + toObj.add(IpPrefixBuilder.getDefaultInstance(curValue)); + foundValue = true; + } + } else if (isPortNumber(elemType)) { + + String curValue = props.getProperty(curBase, ""); + + if ((curValue != null) && (curValue.length() > 0)) { + toObj.add(PortNumber.getDefaultInstance(curValue)); + foundValue = true; + } + } else if (isDscp(elemType)) { + + String curValue = props.getProperty(curBase, ""); + + if ((curValue != null) && (curValue.length() > 0)) { + toObj.add(Dscp.getDefaultInstance(curValue)); + foundValue = true; + } + } else { + String builderName = elemType.getName() + "Builder"; + try { + Class builderClass = Class.forName(builderName); + Object builderObj = builderClass.newInstance(); + Method buildMethod = builderClass.getMethod("build"); + builderObj = toBuilder(props, curBase, builderObj, true); + if (builderObj != null) { + Object builtObj = buildMethod.invoke(builderObj); + toObj.add(builtObj); + foundValue = true; + } + + } catch (ClassNotFoundException e) { + LOG.warn("Could not find builder class {}", builderName, e); + } catch (Exception e) { + LOG.error("Caught exception trying to populate list from {}", pfx, e); + } + } + } else { + // Must be a leaf list + String curValue = props.getProperty(curBase, ""); + + toObj.add(curValue); + + if ((curValue != null) && (curValue.length() > 0)) { + foundValue = true; + } + } + + } + + if (foundValue) { + return (toObj); + } else { + return (null); + } + + } + + public static Object toBuilder(Properties props, String pfx, Object toObj) { + return (toBuilder(props, pfx, toObj, false)); + } + + public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) { + + Class toClass = toObj.getClass(); + boolean foundValue = false; + + Ipv4Address addr; + + if (isYangGenerated(toClass)) { + // Class is yang generated. + String propNamePfx = null; + if (preservePfx) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith(BUILDER)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length()); + } + } + + if (toObj instanceof Identifier) { + return (toObj); + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + if (isSetter(m)) { + Class paramTypes[] = m.getParameterTypes(); + Class paramClass = paramTypes[0]; + + String fieldName = toLowerHyphen(m.getName().substring(3)); + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + + String paramValue = props.getProperty(propName); + if (paramValue == null) { + + } else if ("".equals(paramValue)) { + LOG.trace(propName + " was set to the empty string, setting it to null"); + paramValue = null; + } else { + + } + + // Is the return type a yang generated class? + if (isYangGenerated(paramClass)) { + // Is it an enum? + if (paramClass.isEnum()) { + + // Param type is a typedef. + if ((paramValue != null) && (paramValue.length() > 0)) { + Object paramObj = null; + + try { + paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue)); + } catch (Exception e) { + LOG.error("Caught exception trying to convert field " + propName + " to enum " + + paramClass.getName(), e); + } + + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + m.invoke(toObj, paramObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to create Yang-generated enum expected by" + + toClass.getName() + "." + m.getName() + "() from Properties entry", e); + } + } + } else { + + String simpleName = paramClass.getSimpleName(); + + if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName) + || IP_ADDRESS.equals(simpleName)) { + + + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue); + + if (IPV4_ADDRESS.equals(simpleName)) { + m.invoke(toObj, ipAddr.getIpv4Address()); + } else if (IPV6_ADDRESS.equals(simpleName)) { + m.invoke(toObj, ipAddr.getIpv6Address()); + + } else { + m.invoke(toObj, ipAddr); + } + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + + "(" + paramValue + ")", e); + + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to call " + toClass.getName() + "." + + m.getName() + "() with Properties entry", e); + } + } + } else if (IP_PREFIX.equals(simpleName)) { + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue); + m.invoke(toObj, ipPrefix); + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + + "(" + paramValue + ")", e); + } + } + } else if ("PortNumber".equals(simpleName)) { + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + PortNumber portNumber = PortNumber.getDefaultInstance(paramValue); + m.invoke(toObj, portNumber); + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + + "(" + paramValue + ")", e); + } + } + } else if ("Dscp".equals(simpleName)) { + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + Dscp dscp = Dscp.getDefaultInstance(paramValue); + m.invoke(toObj, dscp); + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + + "(" + paramValue + ")", e); + } + } + } else if ("RouteDistinguisher".equals(simpleName)) { + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + RouteDistinguisher routeDistinguisher = RouteDistinguisherBuilder.getDefaultInstance(paramValue); + m.invoke(toObj, routeDistinguisher); + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + + "(" + paramValue + ")", e); + } + } + } + else { + // setter expects a yang-generated class. Need + // to + // create a builder to set it. + + String builderName = paramClass.getName() + "Builder"; + Class builderClass = null; + Object builderObj = null; + Object paramObj = null; + + Object constObj = null; + + try { + builderClass = Class.forName(builderName); + builderObj = builderClass.newInstance(); + paramObj = toBuilder(props, propNamePfx, builderObj); + } catch (ClassNotFoundException e) { + LOG.trace("Builder class {} not found catching ClassNotFoundException and trying other methods", + builderName); + if (paramValue == null) { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + m.invoke(toObj, new Object[] { null }); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e1) { + LOG.error("Caught exception trying to cally" + toClass.getName() + "." + + m.getName() + "() with Properties entry", e1); + } + } else { + try { + // See if I can find a constructor I + // can + // use + Constructor[] constructors = paramClass.getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (String.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (Long.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(Long.parseLong(paramValue)); + } + } + } + + } + + if (constObj == null) { + + // Last chance - see if + // parameter class has a static + // method + // getDefaultInstance(String) + try { + Method gm = + paramClass.getMethod("getDefaultInstance", String.class); + + int gmodifier = gm.getModifiers(); + if (Modifier.isStatic(gmodifier)) { + // Invoke static + // getDefaultInstance(String) + paramObj = gm.invoke(null, paramValue); + } + + } catch (Exception gme) { + LOG.info("Unable to find static method getDefaultInstance for " + + "class {}", paramClass.getSimpleName(), gme); + } + } + + } catch (Exception e1) { + LOG.warn( + "Could not find a suitable constructor for " + paramClass.getName(), + e1); + } + + if (constObj == null) { + LOG.warn("Could not find builder class " + builderName + + " and could not find a String or Long constructor or static " + + "getDefaultInstance(String) - trying just to set passing paramValue"); + + } + } + } catch (Exception e) { + LOG.error("Caught exception trying to create builder " + builderName, e); + } + + if (paramObj != null && builderClass != null) { + + try { + Method buildMethod = builderClass.getMethod("build"); + + Object builtObj = buildMethod.invoke(paramObj); + + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + m.invoke(toObj, builtObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to set Yang-generated class expected by" + + toClass.getName() + "." + m.getName() + "() from Properties entry", + e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + if (constObj != null) { + m.invoke(toObj, constObj); + } else { + m.invoke(toObj, paramValue); + } + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by" + + toClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(paramClass)) { + // Figure out what type of args are in List and pass + // that to toList(). + + Type paramType = m.getGenericParameterTypes()[0]; + Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0]; + Object paramObj = new LinkedList(); + try { + paramObj = toList(props, propName, (List) paramObj, (Class) elementType); + } catch (Exception e) { + LOG.error("Caught exception trying to create list expected as argument to {}.{}", + toClass.getName(), m.getName(), e); + } + + if (paramObj != null) { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + m.invoke(toObj, paramObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to convert List returned by" + toClass.getName() + + "." + m.getName() + "() to Properties entry", e); + } + } + } else { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + if ((paramValue != null) && (paramValue.length() > 0)) { + + Object constObj = null; + + try { + // See if I can find a constructor I can use + Constructor[] constructors = paramClass.getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (String.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (Long.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(Long.parseLong(paramValue)); + } + } + } + + } + + if (constObj != null) { + try { + m.invoke(toObj, constObj); + foundValue = true; + } catch (Exception e2) { + LOG.error("Caught exception trying to call " + m.getName(), e2); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by" + + toClass.getName() + "." + m.getName() + "() to Properties entry", + e); + } + } + } catch (Exception e1) { + LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1); + } + + } + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + if (foundValue) { + return (toObj); + } else { + return (null); + } + } + + private static boolean classHasSpecialHandling(String simpleName) { + if (IP_ADDRESS.equals(simpleName) || IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName) + || IP_PREFIX.equals(simpleName) || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) { + return true; + } + return false; + } + + private static String getStringValueMethod(String simpleName){ + if (IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)) { + return("stringValue"); + } else { + return("getValue"); + } + } + + public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) { + boolean foundValue = false; + + if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) { + // Class is yang generated. + String propNamePfx = null; + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith(BUILDER)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + if (isGetter(m)) { + Class returnClass = m.getReturnType(); + + String fieldName = toLowerHyphen(m.getName().substring(3)); + if (fieldName != null) { + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + } else { + fieldName = ""; + } + String propName = propNamePfx + "." + fieldName; + + // Is the return type a yang generated class? + if (isYangGenerated(returnClass)) { + // Is it an enum? + if (returnClass.isEnum()) { + pstr.print("\n\n * " + propName); + } else { + + String simpleName = returnClass.getSimpleName(); + + if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName) + || IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName) + || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) { + pstr.print("\n\n * " + propName); + } else { + printPropertyList(pstr, propNamePfx, returnClass); + } + + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(returnClass)) { + // Figure out what type of args are in List and pass + // that to toList(). + + Type returnType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0]; + Class elementClass = (Class) elementType; + printPropertyList(pstr, + propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]", + elementClass); + + } else if (!returnClass.equals(Class.class)) { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + pstr.print("\n\n * " + propName); + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + } + + public static boolean isYangGenerated(Class c) { + if (c != null) { + return (c.getName().startsWith("org.opendaylight.yang.gen.")); + } + return false; + } + + public static boolean isIpPrefix(Class c) { + + if (c == null) { + return (false); + } + if (!isIetfInet(c)) { + return (false); + } + String simpleName = c.getSimpleName(); + return (IP_PREFIX.equals(simpleName)); + } + + public static boolean isIpv4Address(Class c) { + + if (c == null) { + return (false); + } + if (!isIetfInet(c)) { + return (false); + } + String simpleName = c.getSimpleName(); + return (IPV4_ADDRESS.equals(simpleName)); + } + + public static boolean isIpv6Address(Class c) { + + if (c == null) { + return (false); + } + if (!isIetfInet(c)) { + return (false); + } + String simpleName = c.getSimpleName(); + return (IPV6_ADDRESS.equals(simpleName)); + } + + public static boolean isIpAddress(Class c) { + + if (c == null) { + return (false); + } + if (!isIetfInet(c)) { + return (false); + } + String simpleName = c.getSimpleName(); + return (IP_ADDRESS.equals(simpleName)); + } + + public static boolean isPortNumber(Class c) { + + if (c == null) { + return (false); + } + if (!isIetfInet(c)) { + return (false); + } + + String simpleName = c.getSimpleName(); + return ("PortNumber".equals(simpleName)); + } + + public static boolean isDscp(Class c) { + + if (c == null) { + return (false); + } + if (!isIetfInet(c)) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Dscp".equals(simpleName)); + } + + public static boolean isIetfInet(Class c) { + + Package p = c.getPackage(); + if (p != null) { + String pkgName = p.getName(); + + if ((pkgName != null) && (pkgName.indexOf("yang.ietf.inet.types") > -1)) { + return (true); + } + } + + return (false); + } + + public static String toLowerHyphen(String inStr) { + if (inStr == null) { + return (null); + } + + String str = inStr.substring(0, 1).toLowerCase(); + if (inStr.length() > 1) { + str = str + inStr.substring(1); + } + + String regex = "([a-z0-9A-Z])(?=[A-Z])"; + String replacement = "$1-"; + + String retval = str.replaceAll(regex, replacement).toLowerCase(); + + return (retval); + } + + // This is called when mapping the yang value back to a valid java enumeration + public static String toJavaEnum(String inStr) { + if (inStr == null) { + return (null); + } else if (inStr.length() == 0) { + return (inStr); + } + + // This is needed for enums containing under scores + inStr = inStr.replaceAll("_", ""); + + // This will strip out all periods, which cannot be in a java enum + inStr = inStr.replaceAll("\\.", ""); + + // This is needed for enums containing spaces + inStr = inStr.replaceAll(" ", ""); + + String[] terms = inStr.split("-"); + StringBuffer sbuff = new StringBuffer(); + + // appends an _ if the string starts with a digit to make it a valid java enum + if (Character.isDigit(inStr.charAt(0))) { + sbuff.append('_'); + } + // If the string contains hyphens it will convert the string to upperCamelCase without hyphens + for (String term : terms) { + sbuff.append(term.substring(0, 1).toUpperCase()); + if (term.length() > 1) { + sbuff.append(term.substring(1)); + } + } + return (sbuff.toString()); + + } + + public static boolean isGetter(Method m) { + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) { + if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) { + if (!"getClass".equals(m.getName())) { + return (true); + } + } + + if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) { + return (true); + } + + if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) { + return (true); + } + } + + return (false); + } + + public static boolean isSetter(Method m) { + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) { + if (m.getName().matches("^set[A-Z].*")) { + Class[] paramTypes = m.getParameterTypes(); + if (paramTypes[0].isAssignableFrom(Identifier.class) + || Identifier.class.isAssignableFrom(paramTypes[0])) { + return (false); + } else { + return (true); + } + } + + } + + return (false); + } + + @Deprecated + public static String getFullPropertiesPath(String propertiesFileName) { + String karafHome = System.getProperty("karaf.home","/opt/lsc/controller"); + return karafHome + "/configuration/" + propertiesFileName; + } + + // This is called when mapping a valid java enumeration back to the yang model value + @Deprecated + public static String mapEnumeratedValue(String propertyName, String propertyValue) { + LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue); + String mappingKey = "yang." + propertyName + "." + propertyValue; + if (yangMappingProperties.containsKey(mappingKey)) { + return (yangMappingProperties.getProperty(mappingKey)); + } else { + LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value."); + return propertyValue; + } + } + +} diff --git a/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java new file mode 100644 index 000000000..992ed64d4 --- /dev/null +++ b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java @@ -0,0 +1,1355 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.ccsdk.sli.core.sli.provider; + +import java.io.PrintStream; +import java.io.FileDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import java.util.Arrays; +import java.util.ArrayList; +import java.io.*; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.common.base.Strings; + + +public class PrintYangToProp { + + private static final Logger LOG = LoggerFactory.getLogger(PrintYangToProp.class); + public static final String PROPERTIES_FILE=""; + private static Properties properties; + private static final String BUILDER="-builder"; + private static final String IMPL="-impl"; + private static final String TO_PROPERTIES_STRING="() to Properties entry"; + private static final String CAUGHT_EXCEPTION_MSG="Caught exception trying to convert value returned by "; + public static Properties prop = new Properties(); + public static ArrayList<String> propList = new ArrayList<>(); + + + public static Properties toProperties(Properties props, Object fromObj) { + Class fromClass = null; + + if (fromObj != null) + { + fromClass = fromObj.getClass(); + } + return (toProperties(props, "", fromObj, fromClass)); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj) + { + Class fromClass = null; + + if (fromObj != null) + { + fromClass = fromObj.getClass(); + } + + return(toProperties(props, pfx, fromObj, fromClass)); + } + + public static Properties toProperties(Properties props, String pfx, + Object fromObj, Class fromClass) { + + if (fromObj == null) { + return (props); + } + + + String simpleName = fromClass.getSimpleName(); + + if (fromObj instanceof List) { + + + List fromList = (List) fromObj; + + for (int i = 0; i < fromList.size(); i++) { + toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass); + } + props.setProperty(pfx + "_length", "" + fromList.size()); + + } else if (isYangGenerated(fromClass)) { + + String propNamePfx = null; + + // If called from a list (so prefix ends in ']'), don't + // add class name again + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx ; + } else { + propNamePfx = toLowerHyphen(fromClass.getSimpleName()); + } + + if (propNamePfx.endsWith(BUILDER)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - BUILDER.length()); + } + + if (propNamePfx.endsWith(IMPL)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - IMPL.length()); + } + } + + // Iterate through getter methods to figure out values we need to + // save from + + for (Method m : fromClass.getMethods()) { + + if (isGetter(m)) { + + Class returnType = m.getReturnType(); + String fieldName = toLowerHyphen(m.getName().substring(3)); + if(m != null && m.getName().matches("^is[A-Z].*")){ + fieldName = toLowerHyphen(m.getName().substring(2)); + } + + if(Strings.isNullOrEmpty(fieldName)) fieldName = fieldName.substring(0, 1).toLowerCase()+ fieldName.substring(1); + + + // Is the return type a yang generated class? + if (isYangGenerated(returnType)) { + + // Is it an enum? + if (returnType.isEnum()) { + // Return type is a typedef. Save its value. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + Object retValue = m.invoke(fromObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + String propName = propNamePfx + "." + + fieldName; + String propVal = retValue.toString(); + String yangProp = "yang." + fieldName + "." + propVal; + if ( properties.containsKey(yangProp)) { + propVal = properties.getProperty(yangProp); + } + props.setProperty(propName, propVal); + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert Yang-generated enum returned by " + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } else if (isIpv4Address(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv4Address retValue = (Ipv4Address) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + String propVal = retValue.getValue(); + + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + CAUGHT_EXCEPTION_MSG + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } else if (isIpv6Address(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv6Address retValue = (Ipv6Address) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + String propVal = retValue.getValue(); + + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + CAUGHT_EXCEPTION_MSG + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } else if (isIpv4Prefix(returnType)) { + + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv4Prefix retValue = (Ipv4Prefix) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + String propVal = retValue.getValue(); + + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + CAUGHT_EXCEPTION_MSG + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } else if (isIpv6Prefix(returnType)) { + //System.out.println("isIpv6Prefix"); + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv6Prefix retValue = (Ipv6Prefix) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + String propVal = retValue.getValue().toString(); + //LOG.debug("Setting property " + propName + // + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + CAUGHT_EXCEPTION_MSG + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retValue = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + toProperties(props, propNamePfx + "." + fieldName, retValue, returnType); + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert Yang-generated class returned by" + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } + } else if (returnType.equals(Class.class)) { + + //LOG.debug(m.getName() + // + " returns a Class object - not interested"); + + } else if (List.class.isAssignableFrom(returnType)) { + + // This getter method returns a list. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retList = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + // Figure out what type of elements are stored in this array. + Type paramType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) paramType) + .getActualTypeArguments()[0]; + toProperties(props, propNamePfx + "." + fieldName, + retList, (Class)elementType); + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert List returned by " + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + + } else { + + // Method returns something that is not a List and not + // yang-generated. + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object propValObj = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (propValObj != null) { + String propVal = propValObj.toString(); + //LOG.debug("Setting property " + propName + // + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + CAUGHT_EXCEPTION_MSG + + fromClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, e); + } + } + + } + } + + } else { + // Class is not yang generated and not a list + // Do nothing. + + } + + return (props); + } + + public static Object toBuilder(Properties props, Object toObj) { + + return (toBuilder(props, "", toObj)); + } + + public static List toList(Properties props, String pfx, List toObj, + Class elemType) { + + int maxIdx = -1; + boolean foundValue = false; + + //LOG.debug("Saving properties to List<" + elemType.getName() + // + "> from " + pfx); + + // Figure out array size + for (Object pNameObj : props.keySet()) { + String key = (String) pNameObj; + + if (key.startsWith(pfx + "[")) { + String idxStr = key.substring(pfx.length() + 1); + int endloc = idxStr.indexOf("]"); + if (endloc != -1) { + idxStr = idxStr.substring(0, endloc); + } + + try { + int curIdx = Integer.parseInt(idxStr); + if (curIdx > maxIdx) { + maxIdx = curIdx; + } + } catch (Exception e) { + LOG.error("Illegal subscript in property " + key); + } + + } + } + + //LOG.debug(pfx + " has max index of " + maxIdx); + for (int i = 0; i <= maxIdx; i++) { + + String curBase = pfx + "[" + i + "]"; + + if (isYangGenerated(elemType)) { + String builderName = elemType.getName() + "Builder"; + try { + Class builderClass = Class.forName(builderName); + Object builderObj = builderClass.newInstance(); + Method buildMethod = builderClass.getMethod("build"); + builderObj = toBuilder(props, curBase, builderObj, true); + if (builderObj != null) { + //LOG.debug("Calling " + builderObj.getClass().getName() + // + "." + buildMethod.getName() + "()"); + Object builtObj = buildMethod.invoke(builderObj); + toObj.add(builtObj); + foundValue = true; + } + + } catch (ClassNotFoundException e) { + LOG.warn("Could not find builder class " + builderName, e); + } catch (Exception e) { + LOG.error("Caught exception trying to populate list from " + + pfx); + } + } + + } + + if (foundValue) { + return (toObj); + } else { + return (null); + } + + } + + public static Object toBuilder(Properties props, String pfx, Object toObj) { + return(toBuilder(props, pfx, toObj, false)); + } + + public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) { + Class toClass = toObj.getClass(); + boolean foundValue = false; + + //LOG.debug("Saving properties to " + toClass.getName() + " class from " + // + pfx); + + Ipv4Address addr; + + if (isYangGenerated(toClass)) { + // Class is yang generated. + //LOG.debug(toClass.getName() + " is a Yang-generated class"); + + String propNamePfx = null; + if (preservePfx) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith(BUILDER)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - BUILDER.length()); + } + + if (propNamePfx.endsWith(IMPL)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - IMPL.length()); + } + } + + if (toObj instanceof Identifier) { + //LOG.debug(toClass.getName() + " is a Key - skipping"); + return (toObj); + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + // LOG.debug("Is " + m.getName() + " method a setter?"); + if (isSetter(m)) { + // LOG.debug(m.getName() + " is a setter"); + Class paramTypes[] = m.getParameterTypes(); + Class paramClass = paramTypes[0]; + + String fieldName = toLowerHyphen(m.getName().substring(3)); + fieldName = fieldName.substring(0, 1).toLowerCase() + + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + + String paramValue = props.getProperty(propName); + if (paramValue == null) { + //LOG.debug(propName + " is unset"); + } else { + //LOG.debug(propName + " = " + paramValue); + } + + // Is the return type a yang generated class? + if (isYangGenerated(paramClass)) { + // Is it an enum? + if (paramClass.isEnum()) { + + //LOG.debug(m.getName() + " expects an Enum"); + // Param type is a typedef. + if (paramValue != null) { + Object paramObj = null; + + try { + paramObj = Enum.valueOf(paramClass, + toUpperCamelCase(paramValue)); + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert field " + + propName + " to enum " + + paramClass.getName(), e); + } + + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + //LOG.debug("Calling " + // + toObj.getClass().getName() + "." + // + m.getName() + "(" + paramValue + // + ")"); + m.invoke(toObj, paramObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to create Yang-generated enum expected by" + + toClass.getName() + + "." + + m.getName() + + "() from Properties entry", + e); + } + } + } else { + + String simpleName = paramClass.getSimpleName(); + LOG.info("simpleName:" + simpleName); + + if ("Ipv4Address".equals(simpleName) + || "Ipv6Address".equals(simpleName) || "Ipv4Prefix".equals(simpleName) || "Ipv6Prefix".equals(simpleName)) { + + if (paramValue != null) { + if("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName)){ + try { + IpAddress ipAddr = IpAddressBuilder + .getDefaultInstance(paramValue); + + + if ("Ipv4Address".equals(simpleName)) + { + m.invoke(toObj, ipAddr.getIpv4Address()); + } + else + { + m.invoke(toObj, ipAddr.getIpv6Address()); + + } + foundValue = true; + } catch (Exception e) { + LOG.error( + "Caught exception calling " + + toClass.getName() + "." + + m.getName() + "(" + + paramValue + ")", e); + + } + }else if("Ipv4Prefix".equals(simpleName)|| "Ipv6Prefix".equals(simpleName)){ + try { + IpPrefix ipPrefix = IpPrefixBuilder + .getDefaultInstance(paramValue); + + + if ("Ipv4Prefix".equals(simpleName)) + { + m.invoke(toObj, ipPrefix.getIpv4Prefix()); + } + else + { + m.invoke(toObj, ipPrefix.getIpv6Prefix()); + + } + foundValue = true; + } catch (Exception e) { + LOG.error( + "Caught exception calling " + + toClass.getName() + "." + + m.getName() + "(" + + paramValue + ")", e); + + } + } + } + + } else { + // setter expects a yang-generated class. Need + // to + // create a builder to set it. + + String builderName = paramClass.getName() + + "Builder"; + Class builderClass = null; + Object builderObj = null; + Object paramObj = null; + + //LOG.debug(m.getName() + // + " expects a yang-generated class - looking for builder " + // + builderName); + try { + builderClass = Class.forName(builderName); + builderObj = builderClass.newInstance(); + paramObj = toBuilder(props, propNamePfx, + builderObj); + } catch (ClassNotFoundException e) { + Object constObj = null; + try { + // See if I can find a constructor I can + // use + Constructor[] constructors = paramClass + .getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c + .getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (String.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c + .getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (Long.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(Long + .parseLong(paramValue)); + } + } + } + + } + + if (constObj != null) { + try { + m.invoke(toObj, constObj); + foundValue = true; + } catch (Exception e2) { + LOG.error( + "Caught exception trying to call " + + m.getName(), + e2); + } + } + } catch (Exception e1) { + LOG.warn( + "Could not find a suitable constructor for " + + paramClass.getName(), + e1); + } + + if (paramObj == null) { + LOG.warn("Could not find builder class " + + builderName + + " and could not find a String or Long constructor - trying just to set passing paramValue"); + + } + + } catch (Exception e) { + LOG.error( + "Caught exception trying to create builder " + + builderName, e); + } + + if (paramObj != null) { + + try { + + Method buildMethod = builderClass + .getMethod("build"); + //LOG.debug("Calling " + // + paramObj.getClass().getName() + // + "." + buildMethod.getName() + // + "()"); + Object builtObj = buildMethod + .invoke(paramObj); + + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + //LOG.debug("Calling " + // + toObj.getClass().getName() + // + "." + m.getName() + "()"); + m.invoke(toObj, builtObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to set Yang-generated class expected by" + + toClass.getName() + + "." + + m.getName() + + "() from Properties entry", + e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + //LOG.debug("Calling " + // + toObj.getClass().getName() + // + "." + m.getName() + "(" + // + paramValue + ")"); + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by" + + toClass.getName() + + "." + + m.getName() + + TO_PROPERTIES_STRING, + e); + } + } + } + } + }else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(paramClass)) { + + //LOG.debug("Parameter class " + paramClass.getName() + // + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type paramType = m.getGenericParameterTypes()[0]; + Type elementType = ((ParameterizedType) paramType) + .getActualTypeArguments()[0]; + Object paramObj = new LinkedList(); + try { + paramObj = toList(props, propName, + (List) paramObj, (Class) elementType); + } catch (Exception e) { + LOG.error("Caught exception trying to create list expected as argument to " + + toClass.getName() + "." + m.getName()); + } + + if (paramObj != null) { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + //LOG.debug("Calling " + // + toObj.getClass().getName() + "." + // + m.getName() + "(" + paramValue + // + ")"); + m.invoke(toObj, paramObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert List returned by" + + toClass.getName() + "." + + m.getName() + + TO_PROPERTIES_STRING, + e); + } + } + } else { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + //LOG.debug("Parameter class " + // + paramClass.getName() + // + " is not a yang-generated class or a List"); + + if (paramValue != null) { + + Object constObj = null; + + try { + // See if I can find a constructor I can use + Constructor[] constructors = paramClass + .getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (String.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c + .getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (Long.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(Long + .parseLong(paramValue)); + } + } + } + + } + + if (constObj != null) { + try { + //LOG.debug("Calling " + // + toObj.getClass() + // .getName() + "." + // + m.getName() + "(" + // + constObj + ")"); + m.invoke(toObj, constObj); + foundValue = true; + } catch (Exception e2) { + LOG.error( + "Caught exception trying to call " + + m.getName(), e2); + } + } else { + try { + boolean isAccessible = m + .isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + //LOG.debug("Calling " + // + toObj.getClass() + // .getName() + "." + // + m.getName() + "(" + // + paramValue + ")"); + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by" + + toClass.getName() + + "." + + m.getName() + + TO_PROPERTIES_STRING, + e); + } + } + } catch (Exception e1) { + LOG.warn( + "Could not find a suitable constructor for " + + paramClass.getName(), e1); + } + + /* + * try { boolean isAccessible = + * m.isAccessible(); if (!isAccessible) { + * m.setAccessible(true); } LOG.debug("Calling " + * + toObj.getClass().getName() + "." + + * m.getName() + "(" + paramValue + ")"); + * m.invoke(toObj, paramValue); if + * (!isAccessible) { + * m.setAccessible(isAccessible); } foundValue = + * true; + * + * } catch (Exception e) { LOG.error( + * "Caught exception trying to convert value returned by" + * + toClass.getName() + "." + m.getName() + + * "() to Properties entry", e); } + */ + } + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + if (foundValue) { + return (toObj); + } else { + return (null); + } + } + + public static Properties getProperties(PrintStream pstr, String pfx, + Class toClass) { + boolean foundValue = false; + + //LOG.debug("Analyzing " + toClass.getName() + " class : pfx " + pfx); + + if (isYangGenerated(toClass) + && (!Identifier.class.isAssignableFrom(toClass))) { + // Class is yang generated. + //LOG.debug(toClass.getName() + " is a Yang-generated class"); + + if (toClass.getName().endsWith("Key")) { + if (Identifier.class.isAssignableFrom(toClass)) { + //LOG.debug(Identifier.class.getName() + // + " is assignable from " + toClass.getName()); + } else { + + //LOG.debug(Identifier.class.getName() + // + " is NOT assignable from " + toClass.getName()); + } + } + + String propNamePfx = null; + if (pfx.endsWith("]")) { + propNamePfx = pfx; + }else if(pfx.indexOf(".CLASS_FOUND") != -1){ + pfx = pfx.replace(".CLASS_FOUND",""); + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith(BUILDER)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - BUILDER.length()); + } + + if (propNamePfx.endsWith(IMPL)) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - IMPL.length()); + } + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + //LOG.debug("Is " + m.getName() + " method a getter?"); + if (isGetter(m)) { + // LOG.debug(m.getName() + " is a getter"); + Class returnClass = m.getReturnType(); + + String fieldName = toLowerHyphen(m.getName().substring(3)); + if(m != null && m.getName().matches("^is[A-Z].*")){ + fieldName = toLowerHyphen(m.getName().substring(2)); + } + fieldName = fieldName.substring(0, 1).toLowerCase() + + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + //System.out.println("****" + propName); + + // Is the return type a yang generated class? + if (isYangGenerated(returnClass)) { + // Is it an enum? + if (returnClass.isEnum()) { + + //LOG.debug(m.getName() + " is an Enum"); + //pstr.print("\n" + propName); + //pstr.print("\n" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\n"); + pstr.print("\"" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\","); + prop.setProperty(propName,""); + propList.add(propName); + + } else { + + String simpleName = returnClass.getSimpleName(); + //System.out.println("simpleName:" + simpleName); + + if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName) || "Ipv4Prefix".equals(simpleName) || "Ipv6Prefix".equals(simpleName) || "IpPrefix".equals(simpleName)) { + //LOG.debug(m.getName()+" is an "+simpleName); + //pstr.print("\n" + propName); + //pstr.print("\n" + propName + ":" + simpleName + "\n"); + pstr.print("\"" + propName + ":" + simpleName + "\","); + prop.setProperty(propName,""); + propList.add(propName); + } else { + boolean isString = false; + boolean isNumber = false; + boolean isBoolean = false; + boolean isIdentifier = false; + //System.out.println("simpleName:" + simpleName); + //System.out.println("propName:" + propName); + for(Method mthd : returnClass.getMethods()){ + String methodName = mthd.getName(); + //System.out.println("methodName:" + methodName); + if(methodName.equals("getValue")){ + Class retType = mthd.getReturnType(); + //System.out.println("retType:" + retType); + isString = String.class.isAssignableFrom(retType); + isNumber = Number.class.isAssignableFrom(retType); + isBoolean = Boolean.class.isAssignableFrom(retType); + isIdentifier = Identifier.class.isAssignableFrom(retType); + //System.out.println("isString:" + isString); + //System.out.println("isNumber:" + isNumber); + //System.out.println("isNumber:" + isNumber); + break; + } + } + + if(isString){ + pstr.print("\"" + propName + ":String\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(isNumber){ + pstr.print("\"" + propName + ":Number\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(isBoolean){ + pstr.print("\"" + propName + ":Boolean\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(isIdentifier){ + //System.out.println("isIdentifier"); + //isIdentifer so skipping + continue; + }else{ + /* + System.out.println("fieldName:" + fieldName); + System.out.println("simpleName:" + simpleName); + System.out.println("returnClass:" + returnClass); + System.out.println("pstr:" + pstr); + System.out.println("propNamePfx:" + propNamePfx); + */ + getProperties(pstr, propNamePfx + ".CLASS_FOUND", returnClass); + } + } + + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(returnClass)) { + + //LOG.debug("Parameter class " + // + returnClass.getName() + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type returnType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) returnType) + .getActualTypeArguments()[0]; + Class elementClass = (Class) elementType; + //LOG.debug("Calling printPropertyList on list type (" + //+ elementClass.getName() + // + "), pfx is (" + // + pfx + // + "), toClass is (" + // + toClass.getName() + ")"); + //System.out.println("List propNamePfx:" + propNamePfx+ "." + toLowerHyphen(elementClass.getSimpleName()) + "[]"); + if(String.class.isAssignableFrom(elementClass)){ + pstr.print("\"" + propName + ":[String,String,...]\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(Number.class.isAssignableFrom(elementClass)){ + pstr.print("\"" + propName + ":[Number,Number,...]\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(Boolean.class.isAssignableFrom(elementClass)){ + pstr.print("\"" + propName + ":[Boolean,Boolean,...]\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(Identifier.class.isAssignableFrom(elementClass)){ + continue; + }else{ + getProperties( + pstr, + propNamePfx + + "." + + toLowerHyphen(elementClass + .getSimpleName()) + "[]", + elementClass); + } + + } else if (!returnClass.equals(Class.class)) { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + //LOG.debug("Parameter class " + // + returnClass.getName() + // + " is not a yang-generated class or a List"); + + //pstr.print("\n" + propName); + String className=returnClass.getName(); + int nClassNameIndex = className.lastIndexOf('.'); + String nClassName = className; + if(nClassNameIndex != -1){ + nClassName=className.substring(nClassNameIndex+1); + } + boolean isString = String.class.isAssignableFrom(returnClass); + boolean isNumber = Number.class.isAssignableFrom(returnClass); + boolean isBoolean = Boolean.class.isAssignableFrom(returnClass); + //pstr.print("\n" + propName +":" + nClassName +"\n"); + boolean isIdentifier = Identifier.class.isAssignableFrom(returnClass); + if(!isIdentifier && !nClassName.equals("[C")){ + if(isNumber){ + pstr.print("\"" + propName +":Number\","); + }else if(isBoolean){ + pstr.print("\"" + propName +":Boolean\","); + }else{ + if(nClassName.equals("[B")){ + pstr.print("\"" + propName +":Binary\","); + }else{ + pstr.print("\"" + propName +":" + nClassName +"\","); + } + } + prop.setProperty(propName,""); + propList.add(propName); + } + + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + return prop; + } + + public static boolean isYangGenerated(Class c) { + if (c == null) { + return (false); + } else { + //System.out.println(c.getName()); + return (c.getName().startsWith("org.opendaylight.yang.gen.")); + } + } + + public static boolean isIpv4Address(Class c) { + + if (c == null ) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Ipv4Address".equals(simpleName)) ; + } + + public static boolean isIpv6Address(Class c) { + + if (c == null ) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Ipv6Address".equals(simpleName)) ; + } + public static boolean isIpv4Prefix(Class c) { + + if (c == null ) { + return (false); + } + String simpleName = c.getSimpleName(); + //System.out.println("simpleName:" + simpleName); + return ("Ipv4Prefix".equals(simpleName)) ; + } + + public static boolean isIpv6Prefix(Class c) { + + if (c == null ) { + return (false); + } + String simpleName = c.getSimpleName(); + //System.out.println("simpleName:" + simpleName); + return ("Ipv6Prefix".equals(simpleName)) ; + } + + public static String toLowerHyphen(String inStr) { + if (inStr == null) { + return (null); + } + + String str = inStr.substring(0, 1).toLowerCase(); + if (inStr.length() > 1) { + str = str + inStr.substring(1); + } + + String regex = "([a-z0-9A-Z])(?=[A-Z])"; + String replacement = "$1-"; + + String retval = str.replaceAll(regex, replacement).toLowerCase(); + + //LOG.debug("Converting " + inStr + " => " + str + " => " + retval); + return (retval); + } + + public static String toUpperCamelCase(String inStr) { + if (inStr == null) { + return (null); + } + + String[] terms = inStr.split("-"); + StringBuffer sbuff = new StringBuffer(); + // Check if string begins with a digit + if (Character.isDigit(inStr.charAt(0))) { + sbuff.append('_'); + } + for (String term : terms) { + sbuff.append(term.substring(0, 1).toUpperCase()); + if (term.length() > 1) { + sbuff.append(term.substring(1)); + } + } + return (sbuff.toString()); + + } + + public static boolean isGetter(Method m) { + //System.out.println(m); + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) + && (m.getParameterTypes().length == 0)) { + if ((m.getName().matches("^is[A-Z].*") || m.getName().matches("^get[A-Z].*")) + && m.getReturnType().equals(Boolean.class)) { + return (true); + } + if (m.getName().matches("^get[A-Z].*") + && !m.getReturnType().equals(void.class)) { + return (true); + } + + } + + return (false); + } + + public static boolean isSetter(Method m) { + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) + && (m.getParameterTypes().length == 1)) { + if (m.getName().matches("^set[A-Z].*")) { + Class[] paramTypes = m.getParameterTypes(); + if (paramTypes[0].isAssignableFrom(Identifier.class) + || Identifier.class.isAssignableFrom(paramTypes[0])) { + return (false); + } else { + return (true); + } + } + + } + + return (false); + } + + public static void main(String[] args){ + + try(PrintStream ps = new PrintStream(new FileOutputStream(FileDescriptor.out))){ + PrintYangToProp printYangToProp = new PrintYangToProp(); + String className = args[0]; + //ClassLoader classLoader = PrintYangToProp.class.getClassLoader(); + //Class aClass = classLoader.loadClass(className); + Class cl = Class.forName(className); + //printPropertyList(ps,"",cl); + //JsonObject jsonObj = Json.createObjectBuilder().build(); + Properties p = getProperties(ps,"",cl); + //System.out.println(p); + + }catch(Exception e){ + e.printStackTrace(); + } + } + + +} diff --git a/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java new file mode 100644 index 000000000..08e957f1d --- /dev/null +++ b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java @@ -0,0 +1,98 @@ +package org.onap.ccsdk.sli.core.sli.provider; + +import java.util.HashMap; +import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor; +import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; +import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder; +import org.onap.ccsdk.sli.core.sli.SvcLogicResource; +import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicResolver; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicClassResolver implements SvcLogicResolver { + + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicClassResolver.class); + private static HashMap<String, SvcLogicAdaptor> adaptorMap = new HashMap<>(); + + public void registerAdaptor(SvcLogicAdaptor adaptor) { + String name = adaptor.getClass().getName(); + LOG.info("Registering adaptor " + name); + adaptorMap.put(name, adaptor); + + } + + public void unregisterAdaptor(String name) { + if (adaptorMap.containsKey(name)) { + LOG.info("Unregistering " + name); + adaptorMap.remove(name); + } + } + + private SvcLogicAdaptor getAdaptorInstance(String name) { + if (adaptorMap.containsKey(name)) { + return adaptorMap.get(name); + } else { + + SvcLogicAdaptor adaptor = (SvcLogicAdaptor) resolve(name); + + if (adaptor != null) { + registerAdaptor(adaptor); + } + + return adaptor; + } + } + + private Object resolve(String className) { + + Bundle bundle = FrameworkUtil.getBundle(SvcLogicClassResolver.class); + + if (bundle == null) { + // Running outside OSGi container (e.g. jUnit). Use Reflection + // to resolve class + try { + return (Class.forName(className).newInstance()); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + + LOG.error("Could not resolve class " + className, e); + return null; + } + + } else { + BundleContext bctx = bundle.getBundleContext(); + ServiceReference sref = bctx.getServiceReference(className); + if (sref != null) { + return bctx.getService(sref); + } else { + + LOG.warn("Could not find service reference object for class " + className); + return null; + } + } + } + + @Override + public SvcLogicResource getSvcLogicResource(String resourceName) { + return (SvcLogicResource) resolve(resourceName); + } + + @Override + public SvcLogicRecorder getSvcLogicRecorder(String recorderName) { + return (SvcLogicRecorder) resolve(recorderName); + } + + @Override + public SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName) { + return (SvcLogicJavaPlugin) resolve(pluginName); + } + + @Override + public SvcLogicAdaptor getSvcLogicAdaptor(String adaptorName) { + return getAdaptorInstance(adaptorName); + } + +} diff --git a/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java new file mode 100644 index 000000000..aad7a5a6d --- /dev/null +++ b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * onap + * ================================================================================ + * Copyright (C) 2016 - 2017 ONAP + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.ccsdk.sli.core.sli.provider; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; +import java.util.Properties; +import java.util.Vector; + +import org.onap.ccsdk.sli.core.sli.ConfigurationException; +import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider; +import org.onap.ccsdk.sli.core.utils.JREFileResolver; +import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver; +import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver; +import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver; +import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Responsible for determining the properties file to use and instantiating the + * <code>DBResourceManager</code> Service. The priority for properties file + * resolution is as follows: + * + * <ol> + * <li>A directory identified by the system environment variable + * <code>SDNC_CONFIG_DIR</code></li> + * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li> + * <li>A directory identified by the JRE argument + * <code>dblib.properties</code></li> + * <li>A <code>dblib.properties</code> file located in the karaf root + * directory</li> + * </ol> + */ +public class SvcLogicPropertiesProviderImpl implements SvcLogicPropertiesProvider { + + private static final Logger log = LoggerFactory.getLogger(SvcLogicPropertiesProviderImpl.class); + + /** + * The name of the properties file for database configuration + */ + private static final String SVCLOGIC_PROP_FILE_NAME = "svclogic.properties"; + + /** + * A prioritized list of strategies for resolving dblib properties files. + */ + private Vector<PropertiesFileResolver> sliPropertiesFileResolvers = new Vector<>(); + + /** + * The configuration properties for the db connection. + */ + private Properties properties; + + /** + * Set up the prioritized list of strategies for resolving dblib properties + * files. + */ + public SvcLogicPropertiesProviderImpl() { + sliPropertiesFileResolvers + .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable")); + sliPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory")); + + sliPropertiesFileResolvers.add( + new JREFileResolver("Using property file (3) from JRE argument", SvcLogicPropertiesProviderImpl.class)); + sliPropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this)); + + // determines properties file as according to the priority described in the + // class header comment + final File propertiesFile = determinePropertiesFile(this); + if (propertiesFile != null) { + try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) { + properties = new Properties(); + properties.load(fileInputStream); + } catch (final IOException e) { + log.error("Failed to load properties for file: {}", propertiesFile.toString(), + new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(), + e)); + } + } else { + // Try to read properties as resource + + InputStream propStr = getClass().getResourceAsStream("/" + SVCLOGIC_PROP_FILE_NAME); + if (propStr != null) { + properties = new Properties(); + try { + properties.load(propStr); + propStr.close(); + } catch (IOException e) { + log.error("IO Exception",e); + properties = null; + } + } + + } + + if (properties == null) { + reportFailure("Missing configuration properties resource(3)", new ConfigurationException( + "Missing configuration properties resource(3): " + SVCLOGIC_PROP_FILE_NAME)); + } + } + + /** + * Extract svclogic config properties. + * + * @return the svclogic config properties + */ + public Properties getProperties() { + return properties; + } + + /** + * Reports the method chosen for properties resolution to the + * <code>Logger</code>. + * + * @param message + * Some user friendly message + * @param fileOptional + * The file location of the chosen properties file + * @return the file location of the chosen properties file + */ + private static File reportSuccess(final String message, final Optional<File> fileOptional) { + if (fileOptional.isPresent()) { + final File file = fileOptional.get(); + log.info("{} {}", message, file.getPath()); + return file; + } + return null; + } + + /** + * Reports fatal errors. This is the case in which no properties file could be + * found. + * + * @param message + * An appropriate fatal error message + * @param configurationException + * An exception describing what went wrong during resolution + */ + private static void reportFailure(final String message, final ConfigurationException configurationException) { + + log.error("{}", message, configurationException); + } + + /** + * Determines the dblib properties file to use based on the following priority: + * <ol> + * <li>A directory identified by the system environment variable + * <code>SDNC_CONFIG_DIR</code></li> + * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li> + * <li>A directory identified by the JRE argument + * <code>dblib.properties</code></li> + * <li>A <code>dblib.properties</code> file located in the karaf root + * directory</li> + * </ol> + */ + File determinePropertiesFile(final SvcLogicPropertiesProviderImpl resourceProvider) { + + for (final PropertiesFileResolver sliPropertiesFileResolver : sliPropertiesFileResolvers) { + final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SVCLOGIC_PROP_FILE_NAME); + if (fileOptional.isPresent()) { + return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional); + } + } + + return null; + } +} diff --git a/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java new file mode 100644 index 000000000..a23594ee3 --- /dev/null +++ b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * 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.ccsdk.sli.core.sli.provider; + +import java.util.Properties; + +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicServiceBase; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; + +public interface SvcLogicService extends SvcLogicServiceBase { + + String NAME = "org.onap.ccsdk.sli.core.sli.provider.SvcLogicService"; + + @Deprecated + Properties execute(String module, String rpc, String version, String mode, Properties parms) throws SvcLogicException; + + /** + * Execute a directed graph + * + * @param module - module name + * @param rpc - rpc name + * @param version - version. If null, use active version + * @param mode - mode (sync/async) + * @param parms - parameters, used to set SvcLogicContext attributes + * @param domDataBroker - DOMDataBroker object + * @return final values of attributes from SvcLogicContext, as Properties + * @throws SvcLogicException + */ + Properties execute(String module, String rpc, String version, String mode, Properties parms, DOMDataBroker domDataBroker) throws SvcLogicException; + + +} diff --git a/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java new file mode 100755 index 000000000..92c2aa49a --- /dev/null +++ b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.ccsdk.sli.core.sli.provider; + +import java.util.Properties; +import org.onap.ccsdk.sli.core.dblib.DbLibService; +import org.onap.ccsdk.sli.core.sli.ConfigurationException; +import org.onap.ccsdk.sli.core.sli.SvcLogicDblibStore; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.onap.ccsdk.sli.core.sli.SvcLogicStore; +import org.onap.ccsdk.sli.core.sli.SvcLogicStoreFactory; +import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider; +import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicResolver; +import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicServiceImplBase; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicServiceImpl extends SvcLogicServiceImplBase implements SvcLogicService { + + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicServiceImpl.class); + + public SvcLogicServiceImpl(SvcLogicPropertiesProvider resourceProvider, SvcLogicResolver resolver) + throws SvcLogicException { + super(null, resolver); + properties = resourceProvider.getProperties(); + this.store = getStore(); + } + + public SvcLogicServiceImpl(SvcLogicPropertiesProvider resourceProvider, DbLibService dbSvc, + SvcLogicResolver resolver) throws SvcLogicException { + super(null, resolver); + properties = resourceProvider.getProperties(); + this.store = new SvcLogicDblibStore(dbSvc); + } + + @Override + @Deprecated + // DomDataBroker is not being used, this should be removed eventually + public Properties execute(String module, String rpc, String version, String mode, Properties props, + DOMDataBroker domDataBroker) throws SvcLogicException { + return (execute(module, rpc, version, mode, props)); + } + + @Override + public SvcLogicStore getStore() throws SvcLogicException { + // Create and initialize SvcLogicStore object - used to access + // saved service logic. + if (store != null) { + return store; + } + + try { + store = SvcLogicStoreFactory.getSvcLogicStore(properties); + } catch (Exception e) { + throw new ConfigurationException("Could not get service logic store", e); + + } + + try { + store.init(properties); + } catch (SvcLogicException e) { + throw new ConfigurationException("Could not get service logic store", e); + } + + return store; + } + +} diff --git a/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml b/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml new file mode 100644 index 000000000..fb3ab9a03 --- /dev/null +++ b/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" + odl:use-default-for-reference-types="true"> + + <bean id="propProvider" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicPropertiesProviderImpl" /> + <reference id="dblibService" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" /> + <bean id="svcLogicClassResolver" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicClassResolver" /> + + <bean id="svcLogicService" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicServiceImpl"> + <argument ref="propProvider" /> + <argument ref="dblibService" /> + <argument ref="svcLogicClassResolver" /> + </bean> + + <service ref="svcLogicService"> + <interfaces> + <value>org.onap.ccsdk.sli.core.sli.provider.SvcLogicService</value> + </interfaces> + </service> + + <bean id="fileRecorder" class="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" /> + <!-- Implementation name was chosen over interface name due to the fact that this Service + was previously registered using the implementation name rather than the interface name. + To ensure backwards compatibility with abstractions polling the Service Registry for the + fileRecorder, the implementation name was chosen here. --> + <service ref="fileRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" /> + + <bean id="slf4jRecorder" class="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" /> + <!-- Implementation name was chosen over interface name due to the fact that this Service + was previously registered using the implementation name rather than the interface name. + To ensure backwards compatibility with abstractions polling the Service Registry for the + slf4jRecorder, the implementation name was chosen here. --> + <service ref="slf4jRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" /> + +</blueprint> diff --git a/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml b/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml new file mode 100644 index 000000000..fb3ab9a03 --- /dev/null +++ b/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" + odl:use-default-for-reference-types="true"> + + <bean id="propProvider" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicPropertiesProviderImpl" /> + <reference id="dblibService" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" /> + <bean id="svcLogicClassResolver" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicClassResolver" /> + + <bean id="svcLogicService" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicServiceImpl"> + <argument ref="propProvider" /> + <argument ref="dblibService" /> + <argument ref="svcLogicClassResolver" /> + </bean> + + <service ref="svcLogicService"> + <interfaces> + <value>org.onap.ccsdk.sli.core.sli.provider.SvcLogicService</value> + </interfaces> + </service> + + <bean id="fileRecorder" class="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" /> + <!-- Implementation name was chosen over interface name due to the fact that this Service + was previously registered using the implementation name rather than the interface name. + To ensure backwards compatibility with abstractions polling the Service Registry for the + fileRecorder, the implementation name was chosen here. --> + <service ref="fileRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" /> + + <bean id="slf4jRecorder" class="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" /> + <!-- Implementation name was chosen over interface name due to the fact that this Service + was previously registered using the implementation name rather than the interface name. + To ensure backwards compatibility with abstractions polling the Service Registry for the + slf4jRecorder, the implementation name was chosen here. --> + <service ref="slf4jRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" /> + +</blueprint> |