Public and Private Locate entries

Issue-ID: AAF-723
Change-Id: I9dcd2e732ce64b39aaa57a6e9404f275f7ad540c
Signed-off-by: Instrumental <jonathan.gathman@att.com>
diff --git a/cadi/core/pom.xml b/cadi/core/pom.xml
index 51a0d09..c02d0f8 100644
--- a/cadi/core/pom.xml
+++ b/cadi/core/pom.xml
@@ -16,7 +16,7 @@
 		<groupId>org.onap.aaf.authz</groupId>
 		<artifactId>cadiparent</artifactId>
 		<relativePath>..</relativePath>
-		<version>2.1.9-SNAPSHOT</version>
+		<version>2.1.10-SNAPSHOT</version>
 	</parent>
 
 	<modelVersion>4.0.0</modelVersion>
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java b/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java
index a9d671c..599bb98 100644
--- a/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java
+++ b/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java
@@ -26,6 +26,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -106,7 +108,7 @@
         // First, load related System Properties
         for (Entry<Object,Object> es : System.getProperties().entrySet()) {
             String key = es.getKey().toString();
-            for (String start : new String[] {"cadi_","aaf_","cm_"}) {
+            for (String start : new String[] {"HOSTNAME","cadi_","aaf_","cm_"}) {
                 if (key.startsWith(start)) {
                     props.put(key, es.getValue());
                 }
@@ -274,41 +276,53 @@
             sb.append("] ");
         } else {
             int idx = 0;
-            if (elements[idx] instanceof Integer) {
+            if(elements[idx]!=null  && 
+            	elements[idx] instanceof Integer) {
                 sb.append('-');
                 sb.append(elements[idx]);
                 ++idx;
             }
             sb.append("] ");
-            String s;
-            boolean first = true;
-            for (Object o : elements) {
-                if (o!=null) {
-                    s=o.toString();
-                    if (first) {
-                        first = false;
-                    } else {
-                        int l = s.length();
-                        if (l>0)    {
-                            switch(s.charAt(l-1)) {
-                                case ' ':
-                                    break;
-                                default:
-                                    sb.append(' ');
-                            }
-                        }
-                    }
-                    sb.append(s);
-                }
-            }
+            write(true,sb,elements);
         }
         return sb;
     }
+    
+    private static boolean write(boolean first, StringBuilder sb, Object[] elements) {
+    	String s;
+        for (Object o : elements) {
+            if (o!=null) {
+            	if(o.getClass().isArray()) {
+            		first = write(first,sb,(Object[])o);
+            	} else {
+	                s=o.toString();
+	                if (first) {
+	                    first = false;
+	                } else {
+	                    int l = s.length();
+	                    if (l>0)    {
+	                        switch(s.charAt(l-1)) {
+	                            case ' ':
+	                                break;
+	                            default:
+	                                sb.append(' ');
+	                        }
+	                    }
+	                }
+	                sb.append(s);
+            	}
+            }
+        }
+        return first;
+    }
 
     @Override
     public void log(Exception e, Object... elements) {
-        log(Level.ERROR,e.getMessage(),elements);
-        e.printStackTrace(System.err);
+    	StringWriter sw = new StringWriter();
+    	PrintWriter pw = new PrintWriter(sw);
+    	pw.println();
+    	e.printStackTrace(pw);
+        log(Level.ERROR,elements,sw.toString());
     }
 
     @Override
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java b/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java
index 353e8e3..245b653 100644
--- a/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java
+++ b/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java
@@ -58,6 +58,7 @@
 import org.onap.aaf.cadi.taf.basic.BasicHttpTaf;
 import org.onap.aaf.cadi.taf.cert.X509Taf;
 import org.onap.aaf.cadi.taf.dos.DenialOfServiceTaf;
+import org.onap.aaf.cadi.util.FixURIinfo;
 import org.onap.aaf.cadi.util.Split;
 
 /**
@@ -158,13 +159,31 @@
     public static final String OAUTH2_TOKEN_URL = "https://AAF_LOCATE_URL/AAF_NS.token:" + AAF_DEFAULT_API_VERSION;
     public static final String OAUTH2_INTROSPECT_URL = "https://AAF_LOCATE_URL/AAF_NS.introspect:" + AAF_DEFAULT_API_VERSION;
 
-    public static final String AAF_REGISTER_AS = "aaf_register_as";
+    public static final String AAF_LOCATOR_CLASS = "aaf_locator_class";
+    // AAF Locator Entries are ADDITIONAL entries, which also gives the Property ability
+    // to set these entries manually
+    // example: adding a K8S name like "oom"
+    // this will allow Registrations to pick up 
+    // locator_ns.oom for onap's "OOM" based k8s entries, etc.
+    public static final String AAF_LOCATOR_CONTAINER="aaf_locator_container";
+    // An ID for another Container, to be used to avoid picking up the wrong internal info 
+    // for another container.
+    public static final String AAF_LOCATOR_CONTAINER_ID = "aaf_locator_container_id";
+    public static final String AAF_LOCATOR_CONTAINER_NS = "aaf_locator_container_ns";
+    public static final String AAF_LOCATOR_VERSION = "aaf_locator_version";
+    public static final String AAF_LOCATOR_PROTOCOL = "aaf_locator_protocol";
+    public static final String AAF_LOCATOR_SUBPROTOCOL = "aaf_locator_subprotocol";
+    public static final String AAF_LOCATOR_NS = "aaf_locator_ns";
+    public static final String AAF_LOCATOR_NAMES = "aaf_locator_names";
+    public static final String AAF_LOCATOR_FQDN = "aaf_locator_fqdn";
+    public static final String AAF_LOCATOR_PUBLIC_PORT = "aaf_locator_public_port";
+    public static final String AAF_LOCATOR_PUBLIC_HOSTNAME = "aaf_locator_public_hostname";
+
     public static final String AAF_APPID = "aaf_id";
     public static final String AAF_APPPASS = "aaf_password";
     public static final String AAF_LUR_CLASS = "aaf_lur_class";
     public static final String AAF_TAF_CLASS = "aaf_taf_class";
     public static final String AAF_CONNECTOR_CLASS = "aaf_connector_class";
-    public static final String AAF_LOCATOR_CLASS = "aaf_locator_class";
     public static final String AAF_CONN_TIMEOUT = "aaf_conn_timeout";
     public static final String AAF_CONN_TIMEOUT_DEF = "3000";
     public static final String AAF_CONN_IDLE_TIMEOUT = "aaf_conn_idle_timeout"; // only for Direct Jetty Access.
@@ -189,7 +208,7 @@
     public static final String AAF_HIGH_COUNT = "aaf_high_count";
     public static final String AAF_HIGH_COUNT_DEF = "1000"; // Default is 1000 entries
     public static final String AAF_PERM_MAP = "aaf_perm_map";
-    public static final String AAF_COMPONENT = "aaf_component";
+//    public static final String AAF_COMPONENT = "aaf_component";
     public static final String AAF_CERT_IDS = "aaf_cert_ids";
     public static final String AAF_DEBUG_IDS = "aaf_debug_ids"; // comma delimited
     public static final String AAF_DATA_DIR = "aaf_data_dir"; // AAF processes and Components only.
@@ -795,18 +814,39 @@
         if (_url==null) {
             access.log(Level.INIT,"No URL passed to 'loadLocator'. Disabled");
         } else {
-            String url = _url;
+            String url = _url.replace("/AAF_NS.", "/%C%CID%AAF_NS.");
+            String root_ns = access.getProperty(Config.AAF_ROOT_NS, null);
+            if(url.indexOf('%')>=0) {
+	            String str = access.getProperty(Config.AAF_LOCATOR_CONTAINER_ID, null);
+	            if(str==null) {
+	            	url = url.replace("%CID","");
+	            } else {
+	            	url = url.replace("%CID",str+'.');
+	            }
+	            str = access.getProperty(Config.AAF_LOCATOR_CONTAINER, null);
+	            if(str==null) {
+	            	url = url.replace("%C","");
+	            } else {
+	            	url = url.replace("%C",str+'.');
+	            }
+	
+	            if (root_ns==null) {
+	            	url = url.replace("%AAF_NS","");
+	            } else {
+	            	url = url.replace("%AAF_NS",root_ns);
+	            }
+            }
             String replacement;
             int idxAAFLocateUrl;
-            if ((idxAAFLocateUrl=_url.indexOf(AAF_LOCATE_URL_TAG))>0 && ((replacement=access.getProperty(AAF_LOCATE_URL, null))!=null)) {
+            if ((idxAAFLocateUrl=url.indexOf(AAF_LOCATE_URL_TAG))>0 && ((replacement=access.getProperty(AAF_LOCATE_URL, null))!=null)) {
                 StringBuilder sb = new StringBuilder(replacement);
                 if (!replacement.endsWith("/locate")) {
                     sb.append("/locate");
                 } 
-                sb.append(_url,idxAAFLocateUrl+AAF_LOCATE_URL_TAG.length(),_url.length());
+                sb.append(url,idxAAFLocateUrl+AAF_LOCATE_URL_TAG.length(),url.length());
                 url = sb.toString();
             }
-    
+            
             try {
                 Class<?> lcls = loadClass(access,AAF_LOCATOR_CLASS_DEF);
                 if (lcls==null) {
@@ -821,12 +861,13 @@
                 }
                 if (locator==null) {
                     URI locatorURI = new URI(url);
+                    FixURIinfo fui = new FixURIinfo(locatorURI);
                     Constructor<?> cnst = lcls.getConstructor(SecurityInfoC.class,URI.class);
                     locator = (Locator<URI>)cnst.newInstance(new Object[] {si,locatorURI});
-                    int port = locatorURI.getPort();
-                    String portS = port<0?"":(":"+locatorURI.getPort());
+                    int port = fui.getPort();
+                    String portS = port<0?"":(":"+port);
                     
-                    access.log(Level.INFO, "AAFLocator enabled using " + locatorURI.getScheme() +"://"+locatorURI.getHost() + portS);
+                    access.log(Level.INFO, "AAFLocator enabled using " + locatorURI.getScheme() +"://"+fui.getHost() + portS);
                 } else {
                     access.log(Level.INFO, "AAFLocator enabled using preloaded " + locator.getClass().getSimpleName());
                 }
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java
index 2305eac..cd8eff4 100644
--- a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java
+++ b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java
@@ -139,7 +139,7 @@
     
 
     @SuppressWarnings("unchecked")
-    private void init(Get getter) throws ServletException {
+    protected void init(Get getter) throws ServletException {
        sideChain = new SideChain();
         // Start with the assumption of "Don't trust anyone".
        TrustChecker tc = TrustChecker.NOTRUST; // default position
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/FCGet.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/FCGet.java
index cf7c922..1805c78 100644
--- a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/FCGet.java
+++ b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/FCGet.java
@@ -32,7 +32,7 @@
  * A private method to query the Filter config and if not exists, return the default.  This
  * cleans up the initialization code.
  */
-class FCGet implements Get {
+public class FCGet implements Get {
     /**
      * 
      */
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/util/FixURIinfo.java b/cadi/core/src/main/java/org/onap/aaf/cadi/util/FixURIinfo.java
new file mode 100644
index 0000000..7e3a239
--- /dev/null
+++ b/cadi/core/src/main/java/org/onap/aaf/cadi/util/FixURIinfo.java
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 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.aaf.cadi.util;
+
+import java.net.URI;
+
+/**
+ * URI and URL, if the host does not have "dots", will interpret Host:port as Authority
+ * 
+ * This is very problematic for Containers, which like single name entries.
+ * @author Instrumental(Jonathan)
+ *
+ */
+public class FixURIinfo {
+	private String auth;
+	private String host;
+	private int port;
+	
+	public FixURIinfo(URI uri) {
+		auth = uri.getAuthority();
+		host = uri.getHost();
+		if(host==null) {
+			if(auth!=null) {
+				int colon = auth.indexOf(':');
+				if(colon >= 0 ) {
+					host = auth.substring(0, colon);
+					port = Integer.parseInt(auth.substring(colon+1));
+				} else {
+					host = auth;
+					port = uri.getPort();
+				}
+				auth=null;
+			}
+		}
+	}
+	
+	public String getHost() {
+		return host;
+	}
+	
+	public int getPort() {
+		return port;
+	}
+
+	public String getUserInfo() {
+		return auth;
+	}
+}
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/util/Split.java b/cadi/core/src/main/java/org/onap/aaf/cadi/util/Split.java
index 4bb1d3b..97afa65 100644
--- a/cadi/core/src/main/java/org/onap/aaf/cadi/util/Split.java
+++ b/cadi/core/src/main/java/org/onap/aaf/cadi/util/Split.java
@@ -31,84 +31,93 @@
  */
 
 public class Split {
-      public static String[] split(char c, String value) {
-          return split(c,value,0,value.length());
-      }
+	private static final String[] EMPTY = new String[0];
 
-      public static String[] split(char c, String value, int start, int end) {
-          if (value==null) {
-              return new String[0];
-          }
+	public static String[] split(char c, String value) {
+		if (value==null) {
+			return EMPTY;
+		}
 
-          // Count items to preallocate Array (memory alloc is more expensive than counting twice)
-          int count,idx;
-          for (count=1,idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,++idx),++count);
-          String[] rv = new String[count];
-          if (count==1) {
-              rv[0]=value.substring(start,end);
-          } else {
-              int last=0;
-              count=-1;
-              for (idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,idx)) {
-                  rv[++count]=value.substring(last,idx);
-                  last = ++idx;
-              }
-              rv[++count]=value.substring(last,end);
-          }
-          return rv;
-    }
+		return split(c,value,0,value.length());
+	}
 
-      public static String[] splitTrim(char c, String value, int start, int end) {
-          if (value==null) {
-              return new String[0];
-          }
+	public static String[] split(char c, String value, int start, int end) {
+		if (value==null) {
+			return EMPTY;
+		}
 
-          // Count items to preallocate Array (memory alloc is more expensive than counting twice)
-          int count,idx;
-          for (count=1,idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,++idx),++count);
-          String[] rv = new String[count];
-          if (count==1) {
-              rv[0]=value.substring(start,end).trim();
-          } else {
-              int last=0;
-              count=-1;
-              for (idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,idx)) {
-                  rv[++count]=value.substring(last,idx).trim();
-                  last = ++idx;
-              }
-              rv[++count]=value.substring(last,end).trim();
-          }
-          return rv;
-    }
+		// Count items to preallocate Array (memory alloc is more expensive than counting twice)
+		int count,idx;
+		for (count=1,idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,++idx),++count);
+		String[] rv = new String[count];
+		if (count==1) {
+			rv[0]=value.substring(start,end);
+		} else {
+			int last=0;
+			count=-1;
+			for (idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,idx)) {
+				rv[++count]=value.substring(last,idx);
+				last = ++idx;
+			}
+			rv[++count]=value.substring(last,end);
+		}
+		return rv;
+	}
 
-      public static String[] splitTrim(char c, String value) {
-          return splitTrim(c,value,0,value.length());
-      }
+	public static String[] splitTrim(char c, String value, int start, int end) {
+		if (value==null) {
+			return EMPTY;
+		}
 
-      public static String[] splitTrim(char c, String value, int size) {
-          if (value==null) {
-              return new String[0];
-          }
+		// Count items to preallocate Array (memory alloc is more expensive than counting twice)
+		int count,idx;
+		for (count=1,idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,++idx),++count);
+		String[] rv = new String[count];
+		if (count==1) {
+			rv[0]=value.substring(start,end).trim();
+		} else {
+			int last=0;
+			count=-1;
+			for (idx=value.indexOf(c,start);idx>=0 && idx<end;idx=value.indexOf(c,idx)) {
+				rv[++count]=value.substring(last,idx).trim();
+				last = ++idx;
+			}
+			rv[++count]=value.substring(last,end).trim();
+		}
+		return rv;
+	}
 
-          int idx;
-          String[] rv = new String[size];
-          if (size==1) {
-              rv[0]=value.trim();
-          } else {
-              int last=0;
-              int count=-1;
-              size-=2;
-              for (idx=value.indexOf(c);idx>=0 && count<size;idx=value.indexOf(c,idx)) {
-                  rv[++count]=value.substring(last,idx).trim();
-                  last = ++idx;
-              }
-              if (idx>0) {
-                rv[++count]=value.substring(last,idx).trim();
-              } else {
-                rv[++count]=value.substring(last).trim();
-              }
-          }
-          return rv;
-      }
+	public static String[] splitTrim(char c, String value) {
+		if (value==null) {
+			return EMPTY;
+		}
+		return splitTrim(c,value,0,value.length());
+	}
+
+	public static String[] splitTrim(char c, String value, int size) {
+		if (value==null) {
+			return EMPTY;
+		}
+
+		int idx;
+		String[] rv = new String[size];
+		if (size==1) {
+			rv[0]=value.trim();
+		} else {
+			int last=0;
+			int count=-1;
+			size-=2;
+			for (idx=value.indexOf(c);idx>=0 && count<size;idx=value.indexOf(c,idx)) {
+				rv[++count]=value.substring(last,idx).trim();
+				last = ++idx;
+			}
+			if (idx>0) {
+				rv[++count]=value.substring(last,idx).trim();
+			} else {
+				rv[++count]=value.substring(last).trim();
+			}
+		}
+		return rv;
+	}
 
 }