/* * #%L * carewebframework * %% * Copyright (C) 2008 - 2016 Regenstrief Institute, Inc. * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This Source Code Form is also subject to the terms of the Health-Related * Additional Disclaimer of Warranty and Limitation of Liability available at * * http://www.carewebframework.org/licensing/disclaimer. * * #L% */ package org.carewebframework.api; import java.util.HashMap; import java.util.List; import java.util.Map; import org.carewebframework.common.MiscUtil; import org.carewebframework.common.WeakList; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextException; /** * Core class for managing the application framework. It provides a registration service for * components. It also interfaces with the Spring application context to perform automatic bean * registration. */ public class AppFramework implements ApplicationContextAware, DestructionAwareBeanPostProcessor { private ApplicationContext appContext; private final List<Object> registeredObjects = new WeakList<>(); private final List<IRegisterEvent> onRegisterList = new WeakList<>(); private final Map<String, Object> attributes = new HashMap<>(); /** * Returns the active application context. * * @return The active application context. */ public ApplicationContext getApplicationContext() { return appContext; } /** * ApplicationContextAware interface to allow container to inject itself. Sets the active * application context. * * @param appContext The active application context. */ @Override public void setApplicationContext(ApplicationContext appContext) throws BeansException { if (this.appContext != null) { throw new ApplicationContextException("Attempt to reinitialize application context."); } this.appContext = appContext; } /** * Returns the attribute map. * * @return The attribute map. */ public Map<String, Object> getAttributes() { return attributes; } /** * Gets an attribute value. * * @param key Key associated with the requested attribute. * @return The attribute value, or null if not found. */ public Object getAttribute(String key) { return attributes.get(key); } /** * Sets or removes an attribute value. * * @param key Key associated with the attribute. * @param value Value to assign to the attribute. If null, the specified attribute is removed if * it exists. */ public void setAttribute(String key, Object value) { if (value == null) { attributes.remove(key); } else { attributes.put(key, value); } } /** * Registers an object with the framework and relevant subsystems (e.g., the context manager). * * @param object Object to register * @return True if object successfully registered. False if object was already registered. */ public synchronized boolean registerObject(Object object) { if (!MiscUtil.containsInstance(registeredObjects, object)) { if (object instanceof IRegisterEvent) { IRegisterEvent onRegister = (IRegisterEvent) object; onRegisterList.add(onRegister); for (Object obj : registeredObjects) { onRegister.registerObject(obj); } } registeredObjects.add(object); for (IRegisterEvent onRegister : onRegisterList) { onRegister.registerObject(object); } return true; } return false; } /** * Remove an object registration from the framework and any relevant subsystems. * * @param object Object to unregister. * @return True if object successfully unregistered. */ public synchronized boolean unregisterObject(Object object) { int i = MiscUtil.indexOfInstance(registeredObjects, object); if (i > -1) { registeredObjects.remove(i); for (IRegisterEvent onRegister : onRegisterList) { onRegister.unregisterObject(object); } if (object instanceof IRegisterEvent) { onRegisterList.remove(object); } return true; } return false; } /** * Finds a registered object belonging to the specified class. * * @param clazz Returned object must be assignment-compatible with this class. * @param previousInstance Previous instance returned by this call. Search will start with the * entry that follows this one in the list. If this parameter is null, the search * starts at the beginning. * @return Reference to the discovered object or null if none found. */ public synchronized Object findObject(Class<?> clazz, Object previousInstance) { int i = previousInstance == null ? -1 : MiscUtil.indexOfInstance(registeredObjects, previousInstance); for (i++; i < registeredObjects.size(); i++) { Object object = registeredObjects.get(i); if (clazz.isInstance(object)) { return object; } } return null; } /** * Automatically registers any container-managed bean with the framework. * * @param bean Object to register. * @param beanName Name of the managed bean. */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { registerObject(bean); return bean; } /** * Does nothing but return the original bean instance. * * @param bean Bean instance. * @param beanName Name of the managed bean. */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * Unregister container-managed bean upon destruction. * * @param bean Bean instance. * @param beanName Name of the managed bean. */ @Override public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { unregisterObject(bean); } @Override public boolean requiresDestruction(Object bean) { return true; } }