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