Author: dain Date: Thu Oct 28 22:02:00 2004 New Revision: 55943 Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/GBeanData.java Modified: geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/DeploymentContext.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanAttribute.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationStore.java geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/RunTest.java geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/configuration/LocalConfigStore.java geronimo/trunk/modules/system/src/test/org/apache/geronimo/system/configuration/LocalConfigStoreTest.java Log: First cut of the gbean configuration persistence We save out the current state of the configuration as it shutsdown into a state.ser file Also added GBeanData which will be used to remove direct use of GBeanMBean, which further reduces our direct use of JMX
Modified: geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/DeploymentContext.java ============================================================================== --- geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/DeploymentContext.java (original) +++ geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/DeploymentContext.java Thu Oct 28 22:02:00 2004 @@ -348,7 +348,7 @@ try { out = new ObjectOutputStream(new FileOutputStream(configSer)); try { - Configuration.storeGMBeanState(config, out); + config.getGBeanData().writeExternal(out); } catch (IOException e) { throw e; } catch (Exception e) { Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/GBeanData.java ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/GBeanData.java Thu Oct 28 22:02:00 2004 @@ -0,0 +1,151 @@ +/** + * + * Copyright 2004 The Apache Software Foundation + * + * 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. + */ +package org.apache.geronimo.gbean; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.management.ObjectName; + +/** + * @version $Rev$ $Date$ + */ +public class GBeanData implements Externalizable { + private GBeanInfo gbeanInfo; + private final Map attributes; + private final Map references; + + public GBeanData() { + attributes = new HashMap(); + references = new HashMap(); + } + + public GBeanData(GBeanInfo gbeanInfo) { + this.gbeanInfo = gbeanInfo; + attributes = new HashMap(); + references = new HashMap(); + } + + public GBeanData(GBeanData gbeanData) { + gbeanInfo = gbeanData.gbeanInfo; + attributes = new HashMap(gbeanData.attributes); + references = new HashMap(gbeanData.references); + } + + public GBeanInfo getGBeanInfo() { + return gbeanInfo; + } + + public void setGBeanInfo(GBeanInfo gbeanInfo) { + this.gbeanInfo = gbeanInfo; + } + + public Map getAttributes() { + return new HashMap(attributes); + } + + public Set getAttributeNames() { + return new HashSet(attributes.keySet()); + } + + public Object getAttribute(String name) { + return attributes.get(name); + } + + public void setAttribute(String name, Object value) { + attributes.put(name, value); + } + + public Map getReferences() { + return new HashMap(references); + } + + public Set getReferencesNames() { + return new HashSet(references.keySet()); + } + + public Set getReferencePatterns(String name) { + return (Set) references.get(name); + } + + public void setReferencePattern(String name, ObjectName pattern) { + setReferencePatterns(name, Collections.singleton(pattern)); + } + + public void setReferencePatterns(String name, Set patterns) { + references.put(name, patterns); + } + + public void writeExternal(ObjectOutput out) throws IOException { + // write the gbean info + out.writeObject(gbeanInfo); + + // write the attributes + out.writeInt(attributes.size()); + for (Iterator iterator = attributes.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String name = (String) entry.getKey(); + Object value = entry.getValue(); + try { + out.writeObject(name); + out.writeObject(value); + } catch (IOException e) { + throw (IOException) new IOException("Unable to write attribute: " + name).initCause(e); + } + } + + // write the references + out.writeInt(references.size()); + for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String name = (String) entry.getKey(); + Set value = (Set) entry.getValue(); + try { + out.writeObject(name); + out.writeObject(value); + } catch (IOException e) { + throw (IOException) new IOException("Unable to write reference pattern: " + name).initCause(e); + } + } + } + + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + // read the gbean info + gbeanInfo = (GBeanInfo) in.readObject(); + + // read the attributes + int attributeCount = in.readInt(); + for (int i = 0; i < attributeCount; i++) { + setAttribute((String) in.readObject(), in.readObject()); + } + + // read the references + int endpointCount = in.readInt(); + for (int i = 0; i < endpointCount; i++) { + setReferencePatterns((String) in.readObject(), (Set) in.readObject()); + } + } +} + Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java Thu Oct 28 22:02:00 2004 @@ -53,6 +53,7 @@ import org.apache.geronimo.gbean.GOperationSignature; import org.apache.geronimo.gbean.GReferenceInfo; import org.apache.geronimo.gbean.InvalidConfigurationException; +import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.kernel.management.NotificationType; @@ -66,10 +67,15 @@ */ public class GBeanMBean extends AbstractManagedObject implements DynamicMBean { /** - * Method name used to retrieve the RawInvoker for the GBean + * Attribute name used to retrieve the RawInvoker for the GBean */ static final String RAW_INVOKER = "$$RAW_INVOKER$$"; + /** + * Attribute name used to retrieve the GBeanData for the GBean + */ + public static final String GBEAN_DATA = "$$GBEAN_DATA$$"; + private static final Log log = LogFactory.getLog(GBeanMBean.class); private final Constructor constructor; private final GBeanLifecycleController gbeanLifecycleController; @@ -163,6 +169,23 @@ private final RawInvoker rawInvoker; /** + * Constructa a GBeanMBean using the supplied GBeanData and class loader + * + * @param gbeanData the data for the new GBean including GBeanInfo, intial attribute values, and reference patterns + * @param classLoader the class loader used to load the gbean instance and attribute/reference types + * @throws InvalidConfigurationException if the gbeanInfo is inconsistent with the actual java classes, such as + * mismatched attribute types or the intial data can not be set + */ + public GBeanMBean(GBeanData gbeanData, ClassLoader classLoader) throws InvalidConfigurationException { + this(gbeanData.getGBeanInfo(), classLoader); + try { + setGBeanData(gbeanData); + } catch (Exception e) { + throw new InvalidConfigurationException("GBeanData could not be loaded into the GBeanMBean", e); + } + } + + /** * Constructa a GBeanMBean using the supplied gbeanInfo and class loader * * @param gbeanInfo the metadata describing the attributes, operations, constructor and references of the gbean @@ -641,10 +664,70 @@ */ public Object getAttribute(String attributeName) throws ReflectionException, AttributeNotFoundException { GBeanMBeanAttribute attribute = getAttributeByName(attributeName); - if (attribute == null && attributeName.equals(RAW_INVOKER)) { + if (attribute != null) { + return attribute.getValue(); + } + + if (attributeName.equals(RAW_INVOKER)) { return rawInvoker; } - return attribute.getValue(); + + if (attributeName.equals(GBEAN_DATA)) { + return getGBeanData(); + + } + + throw new AttributeNotFoundException(attributeName); + } + + /** + * Gets the gbean data for the gbean held by this gbean mbean. + * @return the gbean data + */ + public GBeanData getGBeanData() { + GBeanData gbeanData = new GBeanData(); + + // add the gbean info + gbeanData.setGBeanInfo(gbeanInfo); + + // add the attributes + for (int i = 0; i < attributes.length; i++) { + GBeanMBeanAttribute attribute = attributes[i]; + if (attribute.isPersistent()) { + String name = attribute.getName(); + Object value = attribute.getPersistentValue(); + gbeanData.setAttribute(name, value); + } + } + + // add the references + for (int i = 0; i < references.length; i++) { + GBeanMBeanReference reference = references[i]; + String name = reference.getName(); + Set patterns = reference.getPatterns(); + gbeanData.setReferencePatterns(name, patterns); + } + return gbeanData; + } + + public void setGBeanData(GBeanData gbeanData) throws ReflectionException, AttributeNotFoundException { + // set the attributes + Map attributes = gbeanData.getAttributes(); + for (Iterator iterator = attributes.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String name = (String) entry.getKey(); + Object value = entry.getValue(); + setAttribute(name, value); + } + + // add the references + Map references = gbeanData.getReferences(); + for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String name = (String) entry.getKey(); + Set patterns = (Set) entry.getValue(); + setReferencePatterns(name, patterns); + } } /** @@ -860,8 +943,19 @@ RAW_INVOKER, RawInvoker.class, new MethodInvoker() { - public Object invoke(Object target, Object[] arguments) throws Exception { + public Object invoke(Object target, Object[] arguments) { return rawInvoker; + } + }, + null)); + + attributesMap.put(GBEAN_DATA, + new GBeanMBeanAttribute(this, + GBEAN_DATA, + GBeanData.class, + new MethodInvoker() { + public Object invoke(Object target, Object[] arguments) { + return getGBeanData(); } }, null)); Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanAttribute.java ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanAttribute.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanAttribute.java Thu Oct 28 22:02:00 2004 @@ -318,6 +318,20 @@ } } + public Object getPersistentValue() { + if (!persistent) { + } + if (getInvoker != null && gmbean.getTarget() != null) { + try { + persistentValue = getInvoker.invoke(gmbean.getTarget(), null); + } catch (Throwable throwable) { + log.error("Could not get the current value of persistent attribute. The persistent " + + "attribute will not reflect the current state attribute. " + getDescription(), throwable); + } + } + return persistentValue; + } + public void setValue(Object value) throws ReflectionException { if (gmbean.isOffline()) { if (persistent || special) { Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java Thu Oct 28 22:02:00 2004 @@ -44,6 +44,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.geronimo.gbean.jmx.GBeanMBean; import org.apache.geronimo.gbean.GBeanInfo; +import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.kernel.config.ConfigurationManager; import org.apache.geronimo.kernel.config.ConfigurationManagerImpl; import org.apache.geronimo.kernel.config.InvalidConfigException; @@ -259,6 +260,23 @@ throw e; } catch (Exception e) { throw new RuntimeException(e); + } + } + + /** + * Gets the gbean data for the gbean held by this gbean mbean. + * @return the gbean data + * @throws InstanceNotFoundException if no such gbean exists with the specified name + */ + public GBeanData getGBeanData(ObjectName name) throws InstanceNotFoundException { + try { + return (GBeanData) getAttribute(name, GBeanMBean.GBEAN_DATA); + } catch (InstanceNotFoundException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw (AssertionError) new AssertionError("getGBeanData can not throw checked exceptions").initCause(e); } } Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java Thu Oct 28 22:02:00 2004 @@ -46,7 +46,7 @@ import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.GBeanInfoFactory; import org.apache.geronimo.gbean.GBeanLifecycle; -import org.apache.geronimo.gbean.GReferenceInfo; +import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.gbean.jmx.GBeanMBean; import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.kernel.jmx.JMXUtil; @@ -86,6 +86,7 @@ private static final Log log = LogFactory.getLog(Configuration.class); private final Kernel kernel; + private final String objectNameString; private final ObjectName objectName; private final URI id; /** @@ -98,6 +99,7 @@ private final List dependencies; private final byte[] gbeanState; private final Collection repositories; + private final ConfigurationStore configurationStore; private URL baseURL; private Map gbeans; @@ -117,8 +119,9 @@ * @param repositories a Collection<Repository> of repositories used to resolve dependencies * @param dependencies a List<URI> of dependencies */ - public Configuration(Kernel kernel, String objectName, URI id, ConfigurationModuleType moduleType, URI parentID, ConfigurationParent parent, List classPath, byte[] gbeanState, Collection repositories, List dependencies) { + public Configuration(Kernel kernel, String objectName, URI id, ConfigurationModuleType moduleType, URI parentID, ConfigurationParent parent, List classPath, byte[] gbeanState, Collection repositories, List dependencies, ConfigurationStore configurationStore) { this.kernel = kernel; + this.objectNameString = objectName; this.objectName = JMXUtil.getObjectName(objectName); this.id = id; this.moduleType = moduleType; @@ -128,6 +131,7 @@ this.classPath = classPath; this.dependencies = dependencies; this.repositories = repositories; + this.configurationStore = configurationStore; } public void doStart() throws Exception { @@ -204,6 +208,10 @@ log.info("Started configuration " + id); } + public String getObjectName() { + return objectNameString; + } + private static void setGBeanBaseUrl(GBeanMBean gbean, URL baseUrl) throws ReflectionException, AttributeNotFoundException { GBeanInfo gbeanInfo = gbean.getGBeanInfo(); Set attributes = gbeanInfo.getAttributes(); @@ -216,7 +224,7 @@ } } - public void doStop() { + public void doStop() throws Exception { log.info("Stopping configuration " + id); if (gbeans == null) { return; @@ -241,6 +249,11 @@ } catch (InvalidConfigException e) { log.info(e); } + + if (configurationStore != null) { + configurationStore.updateConfiguration(this); + } + gbeans = null; } @@ -326,18 +339,19 @@ * @return a Map<ObjectName, GBeanMBean> of GBeans loaded from the persisted state * @throws InvalidConfigException if there is a problem deserializing the state */ - public static Map loadGBeans(byte[] gbeanState, ClassLoader cl) throws InvalidConfigException { + private static Map loadGBeans(byte[] gbeanState, ClassLoader cl) throws InvalidConfigException { Map gbeans = new HashMap(); ObjectName objectName = null; try { ObjectInputStream ois = new ConfigInputStream(new ByteArrayInputStream(gbeanState), cl); try { while (true) { - objectName = null; objectName = (ObjectName) ois.readObject(); - GBeanInfo info = (GBeanInfo) ois.readObject(); - GBeanMBean gbean = new GBeanMBean(info, cl); - loadGMBeanState(gbean, ois); + + GBeanData gbeanData = new GBeanData(); + gbeanData.readExternal(ois); + GBeanMBean gbean = new GBeanMBean(gbeanData, cl); + gbeans.put(objectName, gbean); } } catch (EOFException e) { @@ -353,14 +367,9 @@ } public static void loadGMBeanState(GBeanMBean gbean, ObjectInputStream ois) throws IOException, AttributeNotFoundException, ReflectionException, ClassNotFoundException { - int attributeCount = ois.readInt(); - for (int i = 0; i < attributeCount; i++) { - gbean.setAttribute((String) ois.readObject(), ois.readObject()); - } - int endpointCount = ois.readInt(); - for (int i = 0; i < endpointCount; i++) { - gbean.setReferencePatterns((String) ois.readObject(), (Set) ois.readObject()); - } + GBeanData gbeanData = new GBeanData(); + gbeanData.readExternal(ois); + gbean.setGBeanData(gbeanData); } /** @@ -385,8 +394,7 @@ GBeanMBean gbean = (GBeanMBean) entry.getValue(); try { oos.writeObject(objectName); - oos.writeObject(gbean.getGBeanInfo()); - storeGMBeanState(gbean, oos); + gbean.getGBeanData().writeExternal(oos); } catch (Exception e) { throw new InvalidConfigException("Unable to serialize GBeanState for " + objectName, e); } @@ -399,36 +407,6 @@ return baos.toByteArray(); } - public static void storeGMBeanState(GBeanMBean gbean, ObjectOutputStream oos) throws IOException, ReflectionException { - List persistentAttributes = gbean.getGBeanInfo().getPersistentAttributes(); - oos.writeInt(persistentAttributes.size()); - for (Iterator j = persistentAttributes.iterator(); j.hasNext();) { - GAttributeInfo attributeInfo = (GAttributeInfo) j.next(); - String name = attributeInfo.getName(); - Object value = null; - try { - value = gbean.getAttribute(name); - } catch (ReflectionException e) { - throw e; - } catch (AttributeNotFoundException e) { - throw new AssertionError("Unable to get attribute " + name + " from GBean " + gbean.getObjectName()); - } - try { - oos.writeObject(name); - oos.writeObject(value); - } catch (IOException e) { - throw (IOException) new IOException("Unable to write attribute: " + name).initCause(e); - } - } - Set endpointsSet = gbean.getGBeanInfo().getReferences(); - oos.writeInt(endpointsSet.size()); - for (Iterator iterator = endpointsSet.iterator(); iterator.hasNext();) { - GReferenceInfo gEndpointInfo = (GReferenceInfo) iterator.next(); - oos.writeObject(gEndpointInfo.getName()); - oos.writeObject(gbean.getReferencePatterns(gEndpointInfo.getName())); - } - } - public static final GBeanInfo GBEAN_INFO; static { @@ -446,6 +424,7 @@ infoFactory.addReference("Parent", ConfigurationParent.class); infoFactory.addReference("Repositories", Repository.class); + infoFactory.addReference("ConfigurationStore", ConfigurationStore.class); infoFactory.setConstructor(new String[]{ "kernel", @@ -457,7 +436,8 @@ "classPath", "gBeanState", "Repositories", - "dependencies"}); + "dependencies", + "ConfigurationStore"}); GBEAN_INFO = infoFactory.getBeanInfo(); } Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationStore.java ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationStore.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationStore.java Thu Oct 28 22:02:00 2004 @@ -71,6 +71,13 @@ GBeanMBean getConfiguration(URI id) throws NoSuchConfigException, IOException, InvalidConfigException; /** + * Updates the saved state of the configuration. + * + * @param configuration the configuration to update + */ + void updateConfiguration(Configuration configuration) throws NoSuchConfigException, Exception; + + /** * Return the base URL for the specified ID * * @param id the unique ID for a Configuration Modified: geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/RunTest.java ============================================================================== --- geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/RunTest.java (original) +++ geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/RunTest.java Thu Oct 28 22:02:00 2004 @@ -69,7 +69,7 @@ JarOutputStream jos = new JarOutputStream(new FileOutputStream(carFile), manifest); jos.putNextEntry(new ZipEntry("META-INF/config.ser")); ObjectOutputStream oos = new ObjectOutputStream(jos); - Configuration.storeGMBeanState(config, oos); + config.getGBeanData().writeExternal(oos); oos.flush(); jos.closeEntry(); jos.putNextEntry(new ZipEntry("org/apache/geronimo/kernel/config/MyGBean.class")); Modified: geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/configuration/LocalConfigStore.java ============================================================================== --- geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/configuration/LocalConfigStore.java (original) +++ geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/configuration/LocalConfigStore.java Thu Oct 28 22:02:00 2004 @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URI; @@ -36,20 +37,24 @@ import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.GBeanInfoFactory; import org.apache.geronimo.gbean.GBeanLifecycle; -import org.apache.geronimo.gbean.InvalidConfigurationException; import org.apache.geronimo.gbean.WaitingException; import org.apache.geronimo.gbean.jmx.GBeanMBean; +import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.kernel.config.Configuration; import org.apache.geronimo.kernel.config.ConfigurationStore; import org.apache.geronimo.kernel.config.InvalidConfigException; import org.apache.geronimo.kernel.config.NoSuchConfigException; +import org.apache.geronimo.kernel.jmx.JMXUtil; import org.apache.geronimo.system.serverinfo.ServerInfo; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Implementation of ConfigurationStore using the local filesystem. @@ -59,7 +64,8 @@ public class LocalConfigStore implements ConfigurationStore, GBeanLifecycle { private static final String INDEX_NAME = "index.properties"; private static final String BACKUP_NAME = "index.backup"; - private final String objectName; + private final Kernel kernel; + private final ObjectName objectName; private final URI root; private final ServerInfo serverInfo; private final Properties index = new Properties(); @@ -71,6 +77,7 @@ * Constructor is only used for direct testing with out a kernel. */ public LocalConfigStore(File rootDir) { + kernel = null; objectName = null; serverInfo = null; this.root = null; @@ -78,15 +85,16 @@ log = LogFactory.getLog("LocalConfigStore:"+rootDir.getName()); } - public LocalConfigStore(String objectName, URI root, ServerInfo serverInfo) { - this.objectName = objectName; + public LocalConfigStore(Kernel kernel, String objectName, URI root, ServerInfo serverInfo) throws MalformedObjectNameException { + this.kernel = kernel; + this.objectName = new ObjectName(objectName); this.root = root; this.serverInfo = serverInfo; log = LogFactory.getLog("LocalConfigStore:"+root.toString()); } public String getObjectName() { - return objectName; + return objectName.toString(); } public void doStart() throws WaitingException, FileNotFoundException, IOException { @@ -239,6 +247,27 @@ return loadConfig(getRoot(configID)); } + public synchronized void updateConfiguration(Configuration configuration) throws NoSuchConfigException, Exception { + File root = getRoot(configuration.getID()); + File stateFile = new File(root, "META-INF/state.ser"); + try { + FileOutputStream fos = new FileOutputStream(stateFile); + ObjectOutputStream oos; + try { + oos = new ObjectOutputStream(fos); + GBeanData gbeanData = kernel.getGBeanData(JMXUtil.getObjectName(configuration.getObjectName())); + gbeanData.writeExternal(oos); + oos.flush(); + } finally { + fos.close(); + } + } catch (Exception e) { + log.error("state store failed", e); + stateFile.delete(); + throw e; + } + } + public List listConfiguations() { List configs; synchronized (this) { @@ -273,23 +302,30 @@ } private GBeanMBean loadConfig(File configRoot) throws IOException, InvalidConfigException { - FileInputStream fis = new FileInputStream(new File(configRoot, "META-INF/config.ser")); + File file = new File(configRoot, "META-INF/state.ser"); + if (!file.isFile()) { + file = new File(configRoot, "META-INF/config.ser"); + if (!file.isFile()) { + throw new InvalidConfigException("Configuration does not contain a META-INF/config.ser file"); + } + } + + FileInputStream fis = new FileInputStream(file); try { ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(fis)); GBeanMBean config; try { - config = new GBeanMBean(Configuration.GBEAN_INFO); - } catch (InvalidConfigurationException e) { - throw new InvalidConfigException("Unable to instantiate Configuration GBeanMBean", e); - } - try { - Configuration.loadGMBeanState(config, ois); + GBeanData gbeanData = new GBeanData(); + gbeanData.readExternal(ois); + config = new GBeanMBean(gbeanData, Configuration.class.getClassLoader()); } catch (ClassNotFoundException e) { //TODO more informative exceptions throw new InvalidConfigException("Unable to read attribute ", e); } catch (Exception e) { throw new InvalidConfigException("Unable to set attribute ", e); } + + config.setReferencePattern("ConfigurationStore", objectName); return config; } finally { fis.close(); @@ -350,12 +386,13 @@ static { GBeanInfoFactory infoFactory = new GBeanInfoFactory(LocalConfigStore.class); + infoFactory.addAttribute("kernel", Kernel.class, false); infoFactory.addAttribute("objectName", String.class, false); infoFactory.addAttribute("root", URI.class, true); infoFactory.addReference("ServerInfo", ServerInfo.class); infoFactory.addInterface(ConfigurationStore.class); - infoFactory.setConstructor(new String[]{"objectName", "root", "ServerInfo"}); + infoFactory.setConstructor(new String[]{"kernel", "objectName", "root", "ServerInfo"}); GBEAN_INFO = infoFactory.getBeanInfo(); } Modified: geronimo/trunk/modules/system/src/test/org/apache/geronimo/system/configuration/LocalConfigStoreTest.java ============================================================================== --- geronimo/trunk/modules/system/src/test/org/apache/geronimo/system/configuration/LocalConfigStoreTest.java (original) +++ geronimo/trunk/modules/system/src/test/org/apache/geronimo/system/configuration/LocalConfigStoreTest.java Thu Oct 28 22:02:00 2004 @@ -80,7 +80,7 @@ JarOutputStream jos = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(sourceFile))); jos.putNextEntry(new ZipEntry("META-INF/config.ser")); ObjectOutputStream oos = new ObjectOutputStream(jos); - Configuration.storeGMBeanState(gbean, oos); + gbean.getGBeanData().writeExternal(oos); oos.flush(); jos.closeEntry(); jos.close();