d7c9d992f9d553103d310bc5743414b34c677eba
[aaf/cadi.git] / core / src / main / java / com / att / cadi / PropAccess.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aaf\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package com.att.cadi;\r
24 \r
25 import java.io.File;\r
26 import java.io.FileInputStream;\r
27 import java.io.IOException;\r
28 import java.io.InputStream;\r
29 import java.io.PrintStream;\r
30 import java.text.SimpleDateFormat;\r
31 import java.util.ArrayList;\r
32 import java.util.Date;\r
33 import java.util.List;\r
34 import java.util.Map.Entry;\r
35 import java.util.Properties;\r
36 \r
37 import com.att.cadi.config.Config;\r
38 import com.att.cadi.config.SecurityInfo;\r
39 \r
40 public class PropAccess implements Access {\r
41         private static final SimpleDateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");\r
42 \r
43         public static Level DEFAULT = Level.AUDIT;\r
44         \r
45         private Symm symm;\r
46         private int level;\r
47         private Properties props;\r
48         private List<String> recursionProtection = null;\r
49         private PrintStream out;\r
50         \r
51         private String name;\r
52 \r
53         public PropAccess() {\r
54                 out=System.out;\r
55                 init(null);\r
56         }\r
57         \r
58         /**\r
59          * This Constructor soley exists to instantiate Servlet Context Based Logging that will call "init" later.\r
60          * @param sc\r
61          */\r
62         protected PropAccess(Object o) {\r
63                 out=System.out;\r
64                 props = new Properties();\r
65         }\r
66         \r
67         public PropAccess(String ... args) {\r
68                 this(System.out,args);\r
69         }\r
70         \r
71         public PropAccess(PrintStream ps, String[] args) {\r
72                 out=ps==null?System.out:ps;\r
73                 Properties nprops=new Properties();\r
74                 int eq;\r
75                 for(String arg : args) {\r
76                         if((eq=arg.indexOf('='))>0) {\r
77                                 nprops.setProperty(arg.substring(0, eq),arg.substring(eq+1));\r
78                         }\r
79                 }\r
80                 init(nprops);\r
81         }\r
82 \r
83         public PropAccess(Properties p) {\r
84                 this(System.out,p);\r
85         }\r
86         \r
87         public PropAccess(PrintStream ps, Properties p) {\r
88                 out=ps==null?System.out:ps;\r
89                 init(p);\r
90         }\r
91         \r
92         protected void init(Properties p) {\r
93                 // Make sure these two are set before any changes in Logging\r
94                 name = "cadi";\r
95                 level=DEFAULT.maskOf();\r
96                 \r
97                 props = new Properties();\r
98                 // First, load related System Properties\r
99                 for(Entry<Object,Object> es : System.getProperties().entrySet()) {\r
100                         String key = es.getKey().toString();\r
101                         for(String start : new String[] {"cadi_","aaf_","cm_","csp_"}) {\r
102                                 if(key.startsWith(start)) {\r
103                                         props.put(key, es.getValue());\r
104                                 }\r
105                         }                       \r
106                 }\r
107                 // Second, overlay or fill in with Passed in Props\r
108                 if(p!=null) {\r
109                         props.putAll(p);\r
110                 }\r
111                 \r
112                 // Third, load any Chained Property Files\r
113                 load(props.getProperty(Config.CADI_PROP_FILES));\r
114                 \r
115                 String sLevel = props.getProperty(Config.CADI_LOGLEVEL); \r
116                 if(sLevel!=null) {\r
117                         level=Level.valueOf(sLevel).maskOf(); \r
118                 }\r
119                 // Setup local Symmetrical key encryption\r
120                 if(symm==null) {\r
121                         symm = Symm.obtain(this);\r
122                 }\r
123                 \r
124                 name = props.getProperty(Config.CADI_LOGNAME, name);\r
125                 \r
126                 // Critical - if no Security Protocols set, then set it.  We'll just get messed up if not\r
127                 if(props.get(Config.CADI_PROTOCOLS)==null) {\r
128                         props.setProperty(Config.CADI_PROTOCOLS, SecurityInfo.HTTPS_PROTOCOLS_DEFAULT);\r
129                 }\r
130         }\r
131 \r
132         private void load(String cadi_prop_files) {\r
133                 String prevKeyFile = props.getProperty(Config.CADI_KEYFILE);\r
134 \r
135                 if(cadi_prop_files!=null) {\r
136                         int prev = 0, end = cadi_prop_files.length();\r
137                         int idx;\r
138                         String filename;\r
139                         while(prev<end) {\r
140                                 idx = cadi_prop_files.indexOf(File.pathSeparatorChar,prev);\r
141                                 if(idx<0) {\r
142                                         idx = end;\r
143                                 }\r
144                                 File file = new File(filename=cadi_prop_files.substring(prev,idx));\r
145                                 if(file.exists()) {\r
146                                         printf(Level.INIT,"Loading CADI Properties from %s",file.getAbsolutePath());\r
147                                         try {\r
148                                                 FileInputStream fis = new FileInputStream(file);\r
149                                                 try {\r
150                                                         props.load(fis);\r
151                                                         // Recursively Load\r
152                                                         String chainProp = props.getProperty(Config.CADI_PROP_FILES);\r
153                                                         if(chainProp!=null) {\r
154                                                                 if(recursionProtection==null) {\r
155                                                                         recursionProtection = new ArrayList<String>();\r
156                                                                         recursionProtection.add(cadi_prop_files);\r
157                                                                 }\r
158                                                                 if(!recursionProtection.contains(chainProp)) {\r
159                                                                         recursionProtection.add(chainProp);\r
160                                                                         load(chainProp); // recurse\r
161                                                                 }\r
162                                                         }\r
163                                                 } finally {\r
164                                                         fis.close();\r
165                                                 }\r
166                                         } catch (Exception e) {\r
167                                                 log(e,filename,"cannot be opened");\r
168                                         }\r
169                                 } else {\r
170                                         printf(Level.WARN,"Warning: recursive CADI Property %s does not exist",file.getAbsolutePath());\r
171                                 }\r
172                                 prev = idx+1;\r
173                         }\r
174                 }\r
175                 // Reset Symm if Keyfile Changes:\r
176                 String newKeyFile = props.getProperty(Config.CADI_KEYFILE);\r
177                 if((prevKeyFile==null && newKeyFile!=null) || (newKeyFile!=null && !newKeyFile.equals(prevKeyFile))) {\r
178                         symm = Symm.obtain(this);\r
179                         prevKeyFile=newKeyFile;\r
180                 }\r
181                 \r
182                 String loglevel = props.getProperty(Config.CADI_LOGLEVEL);\r
183                 if(loglevel!=null) {\r
184                         try {\r
185                                 level=Level.valueOf(loglevel).maskOf();\r
186                         } catch (IllegalArgumentException e) {\r
187                                 printf(Level.ERROR,"%s=%s is an Invalid Log Level",Config.CADI_LOGLEVEL,loglevel);\r
188                         }\r
189                 }\r
190         }\r
191         \r
192         @Override\r
193         public void load(InputStream is) throws IOException {\r
194                 props.load(is);\r
195                 load(props.getProperty(Config.CADI_PROP_FILES));\r
196         }\r
197 \r
198         @Override\r
199         public void log(Level level, Object ... elements) {\r
200                 if(willLog(level)) {\r
201                         StringBuilder sb = buildMsg(level, elements);\r
202                         out.println(sb);\r
203                         out.flush();\r
204                 }\r
205         }\r
206         \r
207         protected StringBuilder buildMsg(Level level, Object[] elements) {\r
208                 StringBuilder sb = new StringBuilder(iso8601.format(new Date()));\r
209                 sb.append(' ');\r
210                 sb.append(level.name());\r
211                 sb.append(" [");\r
212                 sb.append(name);\r
213                 \r
214                 int end = elements.length;\r
215                 if(end<=0) {\r
216                         sb.append("] ");\r
217                 } else {\r
218                         int idx = 0;\r
219                         if(elements[idx] instanceof Integer) {\r
220                                 sb.append('-');\r
221                                 sb.append(elements[idx]);\r
222                                 ++idx;\r
223                         }\r
224                         sb.append("] ");\r
225                         String s;\r
226                         boolean first = true;\r
227                         for(Object o : elements) {\r
228                                 if(o!=null) {\r
229                                         s=o.toString();\r
230                                         if(first) {\r
231                                                 first = false;\r
232                                         } else {\r
233                                                 int l = s.length();\r
234                                                 if(l>0) {\r
235                                                         switch(s.charAt(l-1)) {\r
236                                                                 case ' ':\r
237                                                                         break;\r
238                                                                 default:\r
239                                                                         sb.append(' ');\r
240                                                         }\r
241                                                 }\r
242                                         }\r
243                                         sb.append(s);\r
244                                 }\r
245                         }\r
246                 }\r
247                 return sb;\r
248         }\r
249 \r
250         @Override\r
251         public void log(Exception e, Object... elements) {\r
252                 log(Level.ERROR,e.getMessage(),elements);\r
253                 e.printStackTrace(System.err);\r
254         }\r
255 \r
256         @Override\r
257         public void printf(Level level, String fmt, Object... elements) {\r
258                 if(willLog(level)) {\r
259                         log(level,String.format(fmt, elements));\r
260                 }\r
261         }\r
262 \r
263         @Override\r
264         public void setLogLevel(Level level) {\r
265                 this.level = level.maskOf();\r
266         }\r
267 \r
268         @Override\r
269         public boolean willLog(Level level) {\r
270                 return level.inMask(this.level);\r
271         }\r
272 \r
273         @Override\r
274         public ClassLoader classLoader() {\r
275                 return ClassLoader.getSystemClassLoader();\r
276         }\r
277 \r
278         @Override\r
279         public String getProperty(String tag, String def) {\r
280                 return props.getProperty(tag,def);\r
281         }\r
282 \r
283         @Override\r
284         public String decrypt(String encrypted, boolean anytext) throws IOException {\r
285                 return (encrypted!=null && (anytext==true || encrypted.startsWith(Symm.ENC)))\r
286                         ? symm.depass(encrypted)\r
287                         : encrypted;\r
288         }\r
289         \r
290         public String encrypt(String unencrypted) throws IOException {\r
291                 return Symm.ENC+symm.enpass(unencrypted);\r
292         }\r
293 \r
294         //////////////////\r
295         // Additional\r
296         //////////////////\r
297         public String getProperty(String tag) {\r
298                 return props.getProperty(tag);\r
299         }\r
300         \r
301 \r
302         public Properties getProperties() {\r
303                 return props;\r
304         }\r
305 \r
306         public void setProperty(String tag, String value) {\r
307                 if(value!=null) {\r
308                         props.put(tag, value);\r
309                         if(Config.CADI_KEYFILE.equals(tag)) {\r
310                                 // reset decryption too\r
311                                 symm = Symm.obtain(this);\r
312                         }\r
313                 }\r
314         }\r
315 \r
316         public Properties getDME2Properties() {\r
317                 return Config.getDME2Props(this);\r
318         }\r
319 \r
320 }\r