2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6 * ===========================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END====================================================
22 package org.onap.aaf.cadi;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.PrintStream;
29 import java.io.PrintWriter;
30 import java.io.StringWriter;
31 import java.text.SimpleDateFormat;
32 import java.util.ArrayList;
33 import java.util.Date;
34 import java.util.List;
35 import java.util.Map.Entry;
36 import java.util.Properties;
38 import org.onap.aaf.cadi.config.Config;
39 import org.onap.aaf.cadi.config.SecurityInfo;
41 public class PropAccess implements Access {
42 // Sonar says cannot be static... it's ok. not too many PropAccesses created.
43 private final SimpleDateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
45 public static final Level DEFAULT = Level.AUDIT;
49 private Properties props;
50 private List<String> recursionProtection = null;
55 logIt = new StreamLogIt(System.out);
60 * This Constructor soly exists to instantiate Servlet Context Based Logging that will call "init" later.
63 protected PropAccess(Object o) {
64 logIt = new StreamLogIt(System.out);
65 props = new Properties();
68 public PropAccess(String ... args) {
69 this(System.out,args);
72 public PropAccess(PrintStream ps, String[] args) {
73 logIt = new StreamLogIt(ps==null?System.out:ps);
77 public PropAccess(LogIt logit, String[] args) {
81 public PropAccess(Properties p) {
85 public PropAccess(PrintStream ps, Properties p) {
86 logIt = new StreamLogIt(ps==null?System.out:ps);
90 protected void init(final LogIt logIt, final String[] args) {
92 Properties nprops=new Properties();
94 for (String arg : args) {
95 if ((eq=arg.indexOf('='))>0) {
96 String key = arg.substring(0, eq);
97 if(Config.CADI_PROP_FILES.equals(key)) {
98 nprops.setProperty(key,arg.substring(eq+1));
105 for (String arg : args) {
106 if ((eq=arg.indexOf('='))>0) {
107 props.setProperty(arg.substring(0, eq),arg.substring(eq+1));
112 protected void init(Properties p) {
113 // Make sure these two are set before any changes in Logging
115 level=DEFAULT.maskOf();
117 props = new Properties();
119 // Find the "cadi_prop_files"
121 for (Entry<Object,Object> es : System.getProperties().entrySet()) {
122 String key = es.getKey().toString();
123 if(Config.CADI_PROP_FILES.equals(key)) {
124 props.put(key,es.getValue().toString());
128 // Second, overlay or fill in with Passed in Props
133 // Third, load any Chained Property Files
134 load(props.getProperty(Config.CADI_PROP_FILES));
136 // Fourth, System.getProperties takes precedence over Files
137 for (Entry<Object,Object> es : System.getProperties().entrySet()) {
138 String key = es.getKey().toString();
139 for (String start : new String[] {"HOSTNAME","cadi_","aaf_","cm_"}) {
140 if (key.startsWith(start)) {
141 props.put(key, es.getValue());
146 String sLevel = props.getProperty(Config.CADI_LOGLEVEL);
148 level=Level.valueOf(sLevel).maskOf();
150 // Setup local Symmetrical key encryption
153 symm = Symm.obtain(this);
154 } catch (CadiException e) {
155 System.err.append("FATAL ERROR: Cannot obtain Key Information.");
156 e.printStackTrace(System.err);
161 name = props.getProperty(Config.CADI_LOGNAME, name);
163 specialConversions();
166 private void specialConversions() {
167 // Critical - if no Security Protocols set, then set it. We'll just get messed up if not
168 if (props.get(Config.CADI_PROTOCOLS)==null) {
169 props.setProperty(Config.CADI_PROTOCOLS, SecurityInfo.HTTPS_PROTOCOLS_DEFAULT);
173 temp=props.get(Config.CADI_PROTOCOLS);
174 if (props.get(Config.HTTPS_PROTOCOLS)==null && temp!=null) {
175 props.put(Config.HTTPS_PROTOCOLS, temp);
179 if ("1.7".equals(System.getProperty("java.specification.version"))
180 && (temp==null || (temp instanceof String && ((String)temp).contains("TLSv1.2")))) {
181 System.setProperty(Config.HTTPS_CIPHER_SUITES, Config.HTTPS_CIPHER_SUITES_DEFAULT);
186 private void load(String cadi_prop_files) {
187 if (cadi_prop_files==null) {
190 String prevKeyFile = props.getProperty(Config.CADI_KEYFILE);
191 int prev = 0, end = cadi_prop_files.length();
195 idx = cadi_prop_files.indexOf(File.pathSeparatorChar,prev);
199 File file = new File(filename=cadi_prop_files.substring(prev,idx));
201 printf(Level.INIT,"Loading CADI Properties from %s",file.getAbsolutePath());
203 FileInputStream fis = new FileInputStream(file);
207 String chainProp = props.getProperty(Config.CADI_PROP_FILES);
208 if (chainProp!=null) {
209 if (recursionProtection==null) {
210 recursionProtection = new ArrayList<>();
211 recursionProtection.add(cadi_prop_files);
213 if (!recursionProtection.contains(chainProp)) {
214 recursionProtection.add(chainProp);
215 load(chainProp); // recurse
221 } catch (Exception e) {
222 log(e,filename,"cannot be opened");
225 printf(Level.WARN,"Warning: recursive CADI Property %s does not exist",file.getAbsolutePath());
231 for (Entry<Object, Object> es : props.entrySet()) {
232 Object value = es.getValue();
233 if (value instanceof String) {
234 String trim = ((String)value).trim();
235 // Remove Beginning/End Quotes, which might be there if mixed with Bash Props
236 int s = 0, e=trim.length()-1;
237 if (s<e && trim.charAt(s)=='"' && trim.charAt(e)=='"') {
238 trim=trim.substring(s+1,e);
240 if (trim!=value) { // Yes, I want OBJECT equals
241 props.setProperty((String)es.getKey(), trim);
245 // Reset Symm if Keyfile Changes:
246 String newKeyFile = props.getProperty(Config.CADI_KEYFILE);
247 if ((prevKeyFile!=null && newKeyFile!=null) || (newKeyFile!=null && !newKeyFile.equals(prevKeyFile))) {
249 symm = Symm.obtain(this);
250 } catch (CadiException e) {
251 System.err.append("FATAL ERROR: Cannot obtain Key Information.");
252 e.printStackTrace(System.err);
256 prevKeyFile=newKeyFile;
259 String loglevel = props.getProperty(Config.CADI_LOGLEVEL);
260 if (loglevel!=null) {
262 level=Level.valueOf(loglevel).maskOf();
263 } catch (IllegalArgumentException e) {
264 printf(Level.ERROR,"%s=%s is an Invalid Log Level",Config.CADI_LOGLEVEL,loglevel);
268 specialConversions();
272 public void load(InputStream is) throws IOException {
274 load(props.getProperty(Config.CADI_PROP_FILES));
278 public void log(Level level, Object ... elements) {
279 if (willLog(level)) {
280 logIt.push(level,elements);
284 protected StringBuilder buildMsg(Level level, Object[] elements) {
285 return buildMsg(name,iso8601,level,elements);
288 public static StringBuilder buildMsg(final String name, final SimpleDateFormat sdf, Level level, Object[] elements) {
289 StringBuilder sb = new StringBuilder(sdf.format(new Date()));
291 sb.append(level.name());
295 int end = elements.length;
300 if(elements[idx]!=null &&
301 elements[idx] instanceof Integer) {
303 sb.append(elements[idx]);
307 write(true,sb,elements);
312 private static boolean write(boolean first, StringBuilder sb, Object[] elements) {
314 for (Object o : elements) {
316 if(o.getClass().isArray()) {
317 first = write(first,sb,(Object[])o);
325 switch(s.charAt(l-1)) {
341 public void log(Exception e, Object... elements) {
342 StringWriter sw = new StringWriter();
343 PrintWriter pw = new PrintWriter(sw);
345 e.printStackTrace(pw);
346 log(Level.ERROR,elements,sw.toString());
350 public void printf(Level level, String fmt, Object... elements) {
351 if (willLog(level)) {
352 log(level,String.format(fmt, elements));
357 public void setLogLevel(Level level) {
358 this.level = level.maskOf();
362 public boolean willLog(Level level) {
363 return level.inMask(this.level);
367 public ClassLoader classLoader() {
368 return ClassLoader.getSystemClassLoader();
372 public String getProperty(String tag, String def) {
373 return props.getProperty(tag,def);
377 public String decrypt(String encrypted, boolean anytext) throws IOException {
378 return (encrypted!=null && (anytext==true || encrypted.startsWith(Symm.ENC)))
379 ? symm.depass(encrypted)
383 public String encrypt(String unencrypted) throws IOException {
384 return Symm.ENC+symm.enpass(unencrypted);
390 public String getProperty(String tag) {
391 return props.getProperty(tag);
395 public Properties getProperties() {
399 public void setProperty(String tag, String value) {
401 props.put(tag, value);
402 if (Config.CADI_KEYFILE.equals(tag)) {
403 // reset decryption too
405 symm = Symm.obtain(this);
406 } catch (CadiException e) {
407 System.err.append("FATAL ERROR: Cannot obtain Key Information.");
408 e.printStackTrace(System.err);
415 public interface LogIt {
416 public void push(Level level, Object ... elements) ;
419 private class StreamLogIt implements LogIt {
420 private PrintStream ps;
422 public StreamLogIt(PrintStream ps) {
426 public void push(Level level, Object ... elements) {
427 ps.println(buildMsg(level,elements));
432 public void set(LogIt logit) {
436 public void setStreamLogIt(PrintStream ps) {
437 logIt = new StreamLogIt(ps);
440 public String toString() {
441 return props.toString();