* 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.StringBufferInputStream;
+import java.io.StringWriter;
+import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
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;
logIt = new StreamLogIt(System.out);
init(null);
}
-
+
/**
* This Constructor soly exists to instantiate Servlet Context Based Logging that will call "init" later.
* @param sc
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();
}
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()) {
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) {
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<>();
} 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) {
prevKeyFile=newKeyFile;
}
-
+
String loglevel = props.getProperty(Config.CADI_LOGLEVEL);
if (loglevel!=null) {
try {
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);
}
}
- 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;
}
}
}
- 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
? symm.depass(encrypted)
: encrypted;
}
-
+
public String encrypt(String unencrypted) throws IOException {
return Symm.ENC+symm.enpass(unencrypted);
}
public String getProperty(String tag) {
return props.getProperty(tag);
}
-
+
public Properties getProperties() {
return props;
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;
}
ps.println(buildMsg(level,elements));
ps.flush();
}
-
}
public void set(LogIt logit) {
logIt = logit;
}
+
+ public void setStreamLogIt(PrintStream ps) {
+ logIt = new StreamLogIt(ps);
+ }
+
+ public String toString() {
+ return props.toString();
+ }
}