Minor changes for Organization needs
[aaf/authz.git] / cadi / core / src / main / java / org / onap / aaf / cadi / PropAccess.java
index a9d671c..df2c076 100644 (file)
@@ -3,13 +3,15 @@
  * org.onap.aaf
  * ===========================================================================
  * Copyright (c) 2018 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.
 
 package org.onap.aaf.cadi;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -35,14 +41,13 @@ import java.util.Properties;
 
 import org.onap.aaf.cadi.config.Config;
 import org.onap.aaf.cadi.config.SecurityInfo;
+import org.onap.aaf.cadi.util.Split;
 
 public class PropAccess implements Access {
     // Sonar says cannot be static... it's ok.  not too many PropAccesses created.
-    private final SimpleDateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-
-    public static final Level DEFAULT = Level.AUDIT;
-    
+    private final SimpleDateFormat iso8601 = newISO8601();
     private Symm symm;
+    public static final Level DEFAULT = Level.AUDIT;
     private int level;
     private Properties props;
     private List<String> recursionProtection = null;
@@ -53,7 +58,7 @@ public class PropAccess implements Access {
         logIt = new StreamLogIt(System.out);
         init(null);
     }
-    
+
     /**
      * This Constructor soly exists to instantiate Servlet Context Based Logging that will call "init" later.
      * @param sc
@@ -62,29 +67,29 @@ public class PropAccess implements Access {
         logIt = new StreamLogIt(System.out);
         props = new Properties();
     }
-    
+
     public PropAccess(String ... args) {
         this(System.out,args);
     }
-    
+
     public PropAccess(PrintStream ps, String[] args) {
         logIt = new StreamLogIt(ps==null?System.out:ps);
         init(logIt,args);
     }
-    
+
     public PropAccess(LogIt logit, String[] args) {
         init(logit, args);
     }
-    
+
     public PropAccess(Properties p) {
         this(System.out,p);
     }
-    
+
     public PropAccess(PrintStream ps, Properties p) {
         logIt = new StreamLogIt(ps==null?System.out:ps);
         init(p);
     }
-    
+
     protected void init(final LogIt logIt, final String[] args) {
         this.logIt = logIt;
         Properties nprops=new Properties();
@@ -96,12 +101,15 @@ public class PropAccess implements Access {
         }
         init(nprops);
     }
-    
-    protected void init(Properties p) {
+
+    public static SimpleDateFormat newISO8601() {
+        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+    }
+
+    protected synchronized void init(Properties p) {
         // Make sure these two are set before any changes in Logging
         name = "cadi";
-        level=DEFAULT.maskOf();
-        
+
         props = new Properties();
         // First, load related System Properties
         for (Entry<Object,Object> es : System.getProperties().entrySet()) {
@@ -110,19 +118,25 @@ public class PropAccess implements Access {
                 if (key.startsWith(start)) {
                     props.put(key, es.getValue());
                 }
-            }            
+            }
         }
         // Second, overlay or fill in with Passed in Props
         if (p!=null) {
             props.putAll(p);
         }
-        
+
+        // Preset LogLevel
+        String sLevel = props.getProperty(Config.CADI_LOGLEVEL);
         // Third, load any Chained Property Files
         load(props.getProperty(Config.CADI_PROP_FILES));
-        
-        String sLevel = props.getProperty(Config.CADI_LOGLEVEL); 
-        if (sLevel!=null) {
-            level=Level.valueOf(sLevel).maskOf(); 
+
+        if(sLevel==null) { // if LogLev wasn't set before, check again after Chained Load
+            sLevel = props.getProperty(Config.CADI_LOGLEVEL);
+            if (sLevel==null) {
+                level=DEFAULT.maskOf();
+            } else {
+                level=Level.valueOf(sLevel).maskOf();
+            }
         }
         // Setup local Symmetrical key encryption
         if (symm==null) {
@@ -134,54 +148,45 @@ public class PropAccess implements Access {
                 System.exit(1);
             }
         }
-        
+
         name = props.getProperty(Config.CADI_LOGNAME, name);
-        
-        specialConversions();
-    }
 
-    private void specialConversions() {
-        // Critical - if no Security Protocols set, then set it.  We'll just get messed up if not
-        if (props.get(Config.CADI_PROTOCOLS)==null) {
-            props.setProperty(Config.CADI_PROTOCOLS, SecurityInfo.HTTPS_PROTOCOLS_DEFAULT);
-        }
-        
-        Object temp;
-        temp=props.get(Config.CADI_PROTOCOLS);
-        if (props.get(Config.HTTPS_PROTOCOLS)==null && temp!=null) {
-            props.put(Config.HTTPS_PROTOCOLS, temp);
-        }
-        
-        if (temp!=null) {
-            if ("1.7".equals(System.getProperty("java.specification.version")) 
-                    && (temp==null || (temp instanceof String && ((String)temp).contains("TLSv1.2")))) {
-                System.setProperty(Config.HTTPS_CIPHER_SUITES, Config.HTTPS_CIPHER_SUITES_DEFAULT);
-            }
-        }
+        SecurityInfo.setHTTPProtocols(this);
+
     }
 
+
     private void load(String cadi_prop_files) {
         if (cadi_prop_files==null) {
             return;
         }
         String prevKeyFile = props.getProperty(Config.CADI_KEYFILE);
-        int prev = 0, end = cadi_prop_files.length();
-        int idx;
-        String filename;
-        while (prev<end) {
-            idx = cadi_prop_files.indexOf(File.pathSeparatorChar,prev);
-            if (idx<0) {
-                idx = end;
-            }
-            File file = new File(filename=cadi_prop_files.substring(prev,idx));
+
+
+        for(String filename : Split.splitTrim(File.pathSeparatorChar, cadi_prop_files)) {
+            Properties fileProps = new Properties();
+            File file = new File(filename);
             if (file.exists()) {
                 printf(Level.INIT,"Loading CADI Properties from %s",file.getAbsolutePath());
                 try {
                     FileInputStream fis = new FileInputStream(file);
                     try {
-                        props.load(fis);
+                        fileProps.load(fis);
+                        // Only load props from recursion which are not already in props
+                        // meaning top Property file takes precedence
+                        for(Entry<Object, Object> es : fileProps.entrySet()) {
+                            if(props.get(es.getKey())==null) {
+                                String key = es.getKey().toString();
+                                String value = es.getValue().toString();
+                                props.put(key, value);
+                                if(key.contains("pass")) {
+                                    value = "vi XX";
+                                }
+                                printf(Level.DEBUG,"  %s=%s",key,value);
+                            }
+                        }
                         // Recursively Load
-                        String chainProp = props.getProperty(Config.CADI_PROP_FILES);
+                        String chainProp = fileProps.getProperty(Config.CADI_PROP_FILES);
                         if (chainProp!=null) {
                             if (recursionProtection==null) {
                                 recursionProtection = new ArrayList<>();
@@ -201,10 +206,9 @@ public class PropAccess implements Access {
             } else {
                 printf(Level.WARN,"Warning: recursive CADI Property %s does not exist",file.getAbsolutePath());
             }
-            prev = idx+1;
         }
-        
-        // Trim 
+
+        // Trim
         for (Entry<Object, Object> es : props.entrySet()) {
             Object value = es.getValue();
             if (value instanceof String) {
@@ -232,7 +236,7 @@ public class PropAccess implements Access {
 
             prevKeyFile=newKeyFile;
         }
-        
+
         String loglevel = props.getProperty(Config.CADI_LOGLEVEL);
         if (loglevel!=null) {
             try {
@@ -241,10 +245,8 @@ public class PropAccess implements Access {
                 printf(Level.ERROR,"%s=%s is an Invalid Log Level",Config.CADI_LOGLEVEL,loglevel);
             }
         }
-        
-        specialConversions();
     }
-    
+
     @Override
     public void load(InputStream is) throws IOException {
         props.load(is);
@@ -258,32 +260,56 @@ public class PropAccess implements Access {
         }
     }
 
-    protected StringBuilder buildMsg(Level level, Object[] elements) {
+    public StringBuilder buildMsg(Level level, Object[] elements) {
         return buildMsg(name,iso8601,level,elements);
     }
 
-    public static StringBuilder buildMsg(final String name, final SimpleDateFormat sdf, Level level, Object[] elements) { 
-        StringBuilder sb = new StringBuilder(sdf.format(new Date()));
-        sb.append(' ');
-        sb.append(level.name());
-        sb.append(" [");
-        sb.append(name);
-        
+    /*
+     * Need to pass in DateFormat per thread, because not marked as thread safe
+     */
+    public static StringBuilder buildMsg(final String name, final DateFormat sdf, Level level, Object[] elements) {
+        final StringBuilder sb;
         int end = elements.length;
-        if (end<=0) {
-            sb.append("] ");
+        if(sdf==null) {
+            sb = new StringBuilder();
+            write(true,sb,elements);
         } else {
-            int idx = 0;
-            if (elements[idx] instanceof Integer) {
-                sb.append('-');
-                sb.append(elements[idx]);
-                ++idx;
+            sb = new StringBuilder(
+                    sdf.format(new Date())
+                    );
+            sb.append(' ');
+            sb.append(level.name());
+            sb.append(" [");
+            sb.append(name);
+            if (end<=0) {
+                sb.append("] ");
+            } else {
+                int idx = 0;
+                if(elements[idx]!=null  &&
+                    elements[idx] instanceof Integer) {
+                    sb.append('-');
+                    sb.append(elements[idx]);
+                    ++idx;
+                }
+                sb.append("] ");
+                write(true,sb,elements);
             }
-            sb.append("] ");
-            String s;
-            boolean first = true;
-            for (Object o : elements) {
-                if (o!=null) {
+        }
+        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 if(o instanceof Throwable) {
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    PrintStream ps = new PrintStream(baos);
+                    ((Throwable)o).printStackTrace(ps);
+                    sb.append(baos.toString());
+                } else {
                     s=o.toString();
                     if (first) {
                         first = false;
@@ -302,13 +328,16 @@ public class PropAccess implements Access {
                 }
             }
         }
-        return sb;
+        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
@@ -344,7 +373,7 @@ public class PropAccess implements Access {
             ? symm.depass(encrypted)
             : encrypted;
     }
-    
+
     public String encrypt(String unencrypted) throws IOException {
         return Symm.ENC+symm.enpass(unencrypted);
     }
@@ -355,7 +384,7 @@ public class PropAccess implements Access {
     public String getProperty(String tag) {
         return props.getProperty(tag);
     }
-    
+
 
     public Properties getProperties() {
         return props;
@@ -380,10 +409,10 @@ public class PropAccess implements Access {
     public interface LogIt {
         public void push(Level level, Object ... elements) ;
     }
-    
+
     private class StreamLogIt implements LogIt {
         private PrintStream ps;
-        
+
         public StreamLogIt(PrintStream ps) {
             this.ps = ps;
         }
@@ -403,6 +432,6 @@ public class PropAccess implements Access {
     }
 
     public String toString() {
-       return props.toString();
+        return props.toString();
     }
 }