/* * Copyright (C) 2003-2011 eXo Platform SAS. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.etk.kernel.container.management; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.etk.kernel.container.KernelContainer; import org.etk.kernel.container.component.RequestLifeCycle; import org.etk.kernel.management.ManagementAware; import org.etk.kernel.management.annotations.ManagedBy; import org.etk.kernel.management.spi.ManagedResource; import org.etk.kernel.management.spi.ManagedTypeMetaData; import org.etk.kernel.management.spi.ManagementContext; import org.etk.kernel.management.spi.ManagementProvider; /** * Created by The eXo Platform SAS Author : eXoPlatform exo@exoplatform.com Jul * 28, 2011 */ public class ManagementContextImpl implements ManagementContext, ManagedResource { /** . */ private final Map<Class<?>, Object> scopingDataList; /** The registrations done by this mbean. */ private final Map<Object, ManagementContextImpl> registrations; /** . */ final Map<ManagementProvider, Object> managedSet; /** . */ private final ManagementContextImpl parent; /** . */ private final Object resource; /** . */ private final ManagedTypeMetaData typeMD; /** * An optional container setup when the management context is attached to a * container. */ final ManageableContainer container; public ManagementContextImpl(ManageableContainer container) { if (container == null) { throw new NullPointerException(); } // Object resource = null; ManagedTypeMetaData typeMD = null; MetaDataBuilder builder = new MetaDataBuilder(container.getClass()); if (builder.isBuildable()) { resource = container; typeMD = builder.build(); } // this.managedSet = new HashMap<ManagementProvider, Object>(); this.registrations = new HashMap<Object, ManagementContextImpl>(); this.parent = null; this.scopingDataList = new HashMap<Class<?>, Object>(); this.resource = resource; this.typeMD = typeMD; this.container = container; } public ManagementContextImpl(ManagementContextImpl parent, ManageableContainer container) { if (parent == null) { throw new NullPointerException(); } if (container == null) { throw new NullPointerException(); } // Object resource = null; ManagedTypeMetaData typeMD = null; MetaDataBuilder builder = new MetaDataBuilder(container.getClass()); if (builder.isBuildable()) { resource = container; typeMD = builder.build(); } // this.managedSet = new HashMap<ManagementProvider, Object>(); this.registrations = new HashMap<Object, ManagementContextImpl>(); this.parent = parent; this.scopingDataList = new HashMap<Class<?>, Object>(); this.resource = resource; this.typeMD = typeMD; this.container = container; } public ManagementContextImpl(ManagementContextImpl parent, Object resource, ManagedTypeMetaData typeMD) { if (parent == null) { throw new NullPointerException(); } if ((resource != null && typeMD == null) && (resource == null && typeMD != null)) { throw new IllegalArgumentException("Can't have resource null and meta data not null or the converse"); } // this.managedSet = new HashMap<ManagementProvider, Object>(); this.registrations = new HashMap<Object, ManagementContextImpl>(); this.parent = parent; this.scopingDataList = new HashMap<Class<?>, Object>(); this.resource = resource; this.typeMD = typeMD; this.container = null; } public ManagementContext getParent() { return parent; } public <S> void setScopingData(Class<S> scopeType, S scopingData) { this.scopingDataList.put(scopeType, scopingData); } public void register(Object o) { Object resource = null; // Apply managed by annotation ManagedBy managedBy = o.getClass().getAnnotation(ManagedBy.class); if (managedBy != null) { try { Class managedByClass = managedBy.value(); Constructor<?> blah = managedByClass.getConstructor(o.getClass()); resource = blah.newInstance(o); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } else { resource = o; } // if (resource != null) { MetaDataBuilder builder = new MetaDataBuilder(resource.getClass()); if (builder.isBuildable()) { ManagedTypeMetaData metaData = builder.build(); // ManagementContextImpl managementContext; if (resource instanceof ManageableContainer) { managementContext = ((ManageableContainer) resource).managementContext; } else { managementContext = new ManagementContextImpl(this, resource, metaData); } // registrations.put(resource, managementContext); // ManageableContainer container = findContainer(); // Install for all the providers related for (ManagementProvider provider : container.getProviders()) { Object name = provider.manage(managementContext); if (name != null) { managementContext.managedSet.put(provider, name); } } // Allow for more resource management if (resource instanceof ManagementAware) { ((ManagementAware) resource).setContext(managementContext); } } } } public void unregister(Object o) { ManagementContextImpl context = registrations.remove(o); if (context != null) { for (Map.Entry<ManagementProvider, Object> entry : context.managedSet.entrySet()) { entry.getKey().unmanage(entry.getValue()); } } } public <S> List<S> getScopingData(Class<S> scopeType) { ArrayList<S> list = new ArrayList<S>(); for (ManagementContextImpl current = this; current != null; current = current.parent) { Object scopedData = current.scopingDataList.get(scopeType); if (scopedData != null) { // It must be that type since we put it list.add((S) scopedData); } } return list; } public KernelContainer findContainer() { for (ManagementContextImpl current = this; true; current = current.parent) { if (current.container instanceof KernelContainer) { return (KernelContainer) current.container; } else if (current.parent == null) { return null; } } } public void beforeInvoke(Object managedResource) { KernelContainer container = findContainer(); if (container != null) { RequestLifeCycle.begin(container); } } public void afterInvoke(Object managedResource) { RequestLifeCycle.end(); } @Override public String toString() { return "ManagementContextImpl[container=" + container + "]"; } public Object getResource() { return resource; } public ManagedTypeMetaData getMetaData() { return typeMD; } void install(ManagementProvider provider) { // Install the current resource if necessary if (resource != null && typeMD != null) { Object name = provider.manage(this); if (name != null) { managedSet.put(provider, name); } } // Install the children except the container ones for (ManagementContextImpl registration : registrations.values()) { registration.install(provider); } } }