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: 562311 $ $Date: 2007-08-02 22:25:05 -0400 (Thu, 02 Aug 2007) $
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 }