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