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.misc.env.util;
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.InvocationTargetException;
27 import java.util.concurrent.ConcurrentHashMap;
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;
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>
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
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>
50 * There is no way to do this kind of specialized behavior in ThreadLocal.
56 public class RefreshableThreadObject<T extends Creatable<T>> {
57 private Map<Thread,T> objs;
58 private long refreshed;
59 private Constructor<T> cnst;
62 * The passed in class <b>must</b> implement the constructor
64 * public MyClass(Env env) {
69 * @throws APIException
71 public RefreshableThreadObject(Class<T> clss) throws APIException {
72 objs = new ConcurrentHashMap<Thread,T>();
74 cnst = clss.getConstructor(new Class[]{Env.class} );
75 } catch (Exception e) {
76 throw new APIException(e);
81 * Get the "T" class from the current thread
85 * @throws APIException
87 public T get(Env env) throws APIException {
88 Thread t = Thread.currentThread();
90 if(obj==null || refreshed>obj.created()) {
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);
98 T destroyMe = objs.put(t,obj);
100 destroyMe.destroy(env);
107 * Mark the timestamp of refreshed.
111 public void refresh(Env env) {
112 refreshed = System.currentTimeMillis();
116 * Remove the object from the Thread instances
119 public void remove(Env env) {
120 T obj = objs.remove(Thread.currentThread());