Update project structure to org.onap.aaf
[aaf/inno.git] / env / src / main / java / org / onap / aaf / inno / env / util / RefreshableThreadObject.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.inno.env.util;\r
24 \r
25 import java.lang.reflect.Constructor;\r
26 import java.lang.reflect.InvocationTargetException;\r
27 import java.util.Collections;\r
28 import java.util.HashMap;\r
29 import java.util.Map;\r
30 \r
31 import org.onap.aaf.inno.env.APIException;\r
32 import org.onap.aaf.inno.env.Creatable;\r
33 import org.onap.aaf.inno.env.Env;\r
34 import org.onap.aaf.inno.env.LifeCycle;\r
35 \r
36 \r
37 /**\r
38  * <h1>RefreshableThreadObject</h1>\r
39  * This is a ThreadLocal like implementation, but it responds to \r
40  * the {@link LifeCycle} mechanism for configuration refreshes, and \r
41  * implements {@link Creatable} (for use in destroy, etc).<p>\r
42  * \r
43  * In addition to the Thread instance semantics, it compares when the object\r
44  * was created versus the last "refresh(env)" call when getting, for the\r
45  * thread, and if necessary to replace the created object, destroying the \r
46  * previous.<p>\r
47  * \r
48  * In most cases, it's better to use the new "Pool" mechanism, as it deals with \r
49  * gaining and returning resources on an as needed basis.  This, however, remains\r
50  * in the cases where specific Objects need to be retained to specific Threads.<p>\r
51  * \r
52  * There is no way to do this kind of specialized behavior in ThreadLocal.\r
53  * \r
54  *\r
55  * @param <T>\r
56  */\r
57 public class RefreshableThreadObject<T extends Creatable<T>> {\r
58         private Map<Thread,T> objs;\r
59         private long refreshed;\r
60         private Constructor<T> cnst;\r
61         \r
62         /**\r
63          * The passed in class <b>must</b> implement the constructor\r
64          * <pre>\r
65          *   public MyClass(Env env) {\r
66          *     ...\r
67          *   }\r
68          * </pre>\r
69          * @param clss\r
70          * @throws APIException\r
71          */\r
72         public RefreshableThreadObject(Class<T> clss) throws APIException {\r
73                 objs = Collections.synchronizedMap(new HashMap<Thread,T>());\r
74                 try {\r
75                         cnst = clss.getConstructor(new Class[]{Env.class} );\r
76                 } catch (Exception e) {\r
77                         throw new APIException(e);\r
78                 }\r
79         }\r
80         \r
81         /**\r
82          * Get the "T" class from the current thread\r
83          * \r
84          * @param env\r
85          * @return T\r
86          * @throws APIException\r
87          */\r
88         public T get(Env env) throws APIException {\r
89                 Thread t = Thread.currentThread();\r
90                 T obj = objs.get(t);\r
91                 if(obj==null || refreshed>obj.created()) {\r
92                         try {\r
93                                 obj = cnst.newInstance(new Object[]{env});\r
94                         } catch (InvocationTargetException e) {\r
95                                 throw new APIException(e.getTargetException());\r
96                         } catch (Exception e) {\r
97                                 throw new APIException(e);\r
98                         }\r
99                         T destroyMe = objs.put(t,obj);\r
100                         if(destroyMe!=null) {\r
101                                 destroyMe.destroy(env);\r
102                         }\r
103                 } \r
104                 return obj;\r
105         }\r
106         \r
107         /**\r
108          * Mark the timestamp of refreshed.\r
109          * \r
110          * @param env\r
111          */\r
112         public void refresh(Env env) {\r
113                 refreshed = System.currentTimeMillis();\r
114         }\r
115         \r
116         /**\r
117          * Remove the object from the Thread instances\r
118          * @param env\r
119          */\r
120         public void remove(Env env) {\r
121                 T obj = objs.remove(Thread.currentThread());\r
122                 if(obj!=null)\r
123                         obj.destroy(env);\r
124         }\r
125 }\r