001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.geronimo.openjpa; 021 022 import java.net.URI; 023 import java.net.URISyntaxException; 024 import java.util.Collections; 025 import java.util.HashMap; 026 027 import org.apache.commons.logging.Log; 028 import org.apache.commons.logging.LogFactory; 029 import org.apache.geronimo.gbean.AbstractName; 030 import org.apache.geronimo.gbean.AbstractNameQuery; 031 import org.apache.geronimo.gbean.GBeanLifecycle; 032 import org.apache.geronimo.gbean.GBeanInfo; 033 import org.apache.geronimo.gbean.GBeanInfoBuilder; 034 import org.apache.geronimo.kernel.Kernel; 035 import org.apache.geronimo.kernel.GBeanNotFoundException; 036 import org.apache.geronimo.kernel.config.Configuration; 037 import org.apache.geronimo.kernel.lifecycle.LifecycleListener; 038 import org.apache.geronimo.kernel.repository.Artifact; 039 040 import org.apache.openjpa.enhance.PCRegistry; 041 042 /** 043 * Monitor configuration lifecycle events. Whenever a configuration is stopped, inform OpenJPA that the ClassLoader is no longer needed. 044 * 045 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 046 */ 047 public class ConfigurationMonitorGBean implements GBeanLifecycle { 048 private static final Log log = LogFactory.getLog(ConfigurationMonitorGBean.class); 049 050 private final Kernel kernel; 051 private final LifecycleListener listener; 052 private HashMap<AbstractName,ClassLoader> classLoaderMap = new HashMap<AbstractName,ClassLoader>(); 053 054 public ConfigurationMonitorGBean(Kernel kernel) { 055 this.kernel = kernel; 056 this.listener = createLifecycleListener(); 057 } 058 059 /** 060 * Create a LifecycleListenr that will be informed of lifecycle events. 061 * We only care about running (the configuration ClassLoader cannot be retrieved when the Configuration is stopping) 062 * and stopped. 063 */ 064 private LifecycleListener createLifecycleListener() { 065 return new LifecycleListener() { 066 public void loaded(AbstractName abstractName) { 067 } 068 public void starting(AbstractName abstractName) { 069 } 070 public void running(AbstractName abstractName) { 071 configurationRunning(abstractName); 072 } 073 public void stopping(AbstractName abstractName) { 074 } 075 public void stopped(AbstractName abstractName) { 076 configurationStopped(abstractName); 077 } 078 public void failed(AbstractName abstractName) { 079 } 080 public void unloaded(AbstractName abstractName) { 081 } 082 083 }; 084 } 085 086 /** 087 * Cache the ClassLoader for a newly started Configuration. 088 */ 089 private void configurationRunning(AbstractName name) { 090 try { 091 Configuration config = (Configuration)kernel.getGBean(name); 092 classLoaderMap.put(name, config.getConfigurationClassLoader()); 093 } catch (GBeanNotFoundException gnfe) { 094 log.warn("Could not retrieve GBean for artifact: " + name.toString(), gnfe); 095 } 096 } 097 098 /** 099 * Notify OpenJPA that the ClassLoader will no longer be used. This allows OpenJPA to free up 100 * HARD references that would otherwise prevent Geronimo ClassLoaders from being GCed. 101 */ 102 private void configurationStopped(AbstractName name) { 103 ClassLoader classLoader = classLoaderMap.remove(name); 104 if (classLoader == null) { 105 log.debug("Could not locate ClassLoader for artifact: " + name.toString()); 106 } 107 PCRegistry.deRegister(classLoader); 108 } 109 110 /** 111 * This GBean is being started. Register our listener with the Lifecycle monitor. 112 */ 113 public void doStart() { 114 AbstractNameQuery configurationQuery = new AbstractNameQuery(Configuration.class.getName()); 115 kernel.getLifecycleMonitor().addLifecycleListener(listener, configurationQuery); 116 } 117 118 /** 119 * This GBean is being stopped. Remove the LifecycleListener. 120 */ 121 public void doStop() { 122 kernel.getLifecycleMonitor().removeLifecycleListener(listener); 123 } 124 125 public void doFail() { 126 doStop(); 127 } 128 129 public static final GBeanInfo GBEAN_INFO; 130 131 static { 132 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(ConfigurationMonitorGBean.class); 133 infoBuilder.addAttribute("kernel", Kernel.class, false); 134 infoBuilder.setConstructor(new String[] { 135 "kernel", 136 }); 137 GBEAN_INFO = infoBuilder.getBeanInfo(); 138 } 139 140 public static GBeanInfo getGBeanInfo() { 141 return GBEAN_INFO; 142 } 143 }