001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mx.persistence;
023:
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.FileOutputStream;
027: import java.io.IOException;
028: import java.io.ObjectInputStream;
029: import java.io.ObjectOutputStream;
030: import javax.management.Attribute;
031: import javax.management.AttributeList;
032: import javax.management.Descriptor;
033: import javax.management.MBeanAttributeInfo;
034: import javax.management.MBeanException;
035: import javax.management.MBeanInfo;
036: import javax.management.modelmbean.ModelMBeanAttributeInfo;
037: import javax.management.modelmbean.ModelMBeanInfo;
038:
039: import org.jboss.mx.modelmbean.ModelMBeanConstants;
040: import org.jboss.mx.modelmbean.ModelMBeanInvoker;
041: import org.jboss.mx.persistence.PersistenceManager;
042:
043: import org.jboss.logging.Logger;
044: import org.jboss.util.StringPropertyReplacer;
045:
046: /**
047: * Object Stream Persistence Manager. <p>
048: *
049: * Persists the MBean to the file system using an Object Stream.
050: * Includes code based on examples in Juha's JMX Book. <p>
051: *
052: * Object Streams written to disk are admittedly lacking in the area of
053: * "long-term", "portable", or "human-readable" persistence. They are fairly
054: * straightforward, however.
055: * Primarily, this class is useful for demonstration and "quick & dirty" persistence.
056: *
057: * @todo currently metadata as well as data is stored. only data needs to be stored.
058: * @author Matt Munz
059: * @author Scott.Stark@jboss.org
060: * @version $Revision: 57200 $
061: */
062: public class ObjectStreamPersistenceManager extends Object implements
063: PersistenceManager {
064: protected static Logger log = Logger
065: .getLogger(ObjectStreamPersistenceManager.class);
066: /** A flag set to true to prevent attribute updates from within load
067: * triggering stores.
068: */
069: protected boolean isLoading;
070:
071: // Constructors --------------------------------------------------
072:
073: public ObjectStreamPersistenceManager() {
074: super ();
075: }
076:
077: // Public --------------------------------------------------------
078:
079: /**
080: * deserializes state from the object input stream
081: *
082: * @param mbean
083: * @param metadata
084: * @exception MBeanException
085: */
086: public void load(ModelMBeanInvoker mbean, MBeanInfo metadata)
087: throws MBeanException {
088: log.debug("load, resource:" + mbean.getResource());
089:
090: if (metadata == null) {
091: return;
092: }
093: if (log.isTraceEnabled())
094: log.trace("metadata: " + metadata);
095:
096: File storeFile = getStoreFile(metadata, false);
097: if (storeFile == null) {
098: return;
099: }
100:
101: try {
102: FileInputStream fis = new FileInputStream(storeFile);
103: ObjectInputStream ois = new ObjectInputStream(fis);
104: ModelMBeanInfo storeMetadata = (ModelMBeanInfo) ois
105: .readObject();
106: ois.close();
107: log.debug("metadata deserialized");
108: if (log.isTraceEnabled())
109: log.trace("storeMetadata: " + storeMetadata);
110: loadFromMetadata(mbean, storeMetadata);
111: } catch (Exception e) {
112: log.error("Error loading MBean state", e);
113: }
114: }
115:
116: /** What we need to get here is 1) the persist location, and 2) the entire
117: * contents of the mbean. #2 contains the entire contents (state) of the
118: * model object, as well as the meta data that the mbean provides.
119: * As such, serializing this (MBeanInfo) object (brute force) in effect
120: * serializes the model as well.
121: *
122: * @param metadata
123: * @exception MBeanException
124: */
125: public void store(MBeanInfo metadata) throws MBeanException {
126: if (isLoading()) {
127: return;
128: }
129:
130: log.debug("store");
131: if (log.isTraceEnabled())
132: log.trace("metadata: " + metadata);
133: File storeFile = getStoreFile(metadata, true);
134: if (storeFile == null) {
135: return;
136: }
137:
138: try {
139: log
140: .debug("Storing to file: "
141: + storeFile.getAbsolutePath());
142: FileOutputStream fos = new FileOutputStream(storeFile);
143: ObjectOutputStream oos = new ObjectOutputStream(fos);
144: oos.writeObject(metadata);
145: } catch (IOException e) {
146: throw new MBeanException(e, "Error in persisting MBean.");
147: }
148: }
149:
150: // Protected -----------------------------------------------------
151:
152: /** Obtain the attribute values from the metadata and invoke setAttributes
153: * on the mbean invoker.
154: *
155: * @param mbean the invoker and assocaited mbean resource
156: * @param metadata the metadata to use as the attributes value source
157: */
158: protected void loadFromMetadata(ModelMBeanInvoker mbean,
159: ModelMBeanInfo metadata) {
160: AttributeList attributes = new AttributeList();
161: // iterate over all attributes in metadata
162: MBeanAttributeInfo[] attrs = metadata.getAttributes();
163: for (int i = 0; i < attrs.length; i++) {
164: /// for each attribute, create a new Attribute object and add it to the collection
165: ModelMBeanAttributeInfo attributeInfo = (ModelMBeanAttributeInfo) attrs[i];
166: Descriptor attrDesc = attributeInfo.getDescriptor();
167: Object name = attrDesc
168: .getFieldValue(ModelMBeanConstants.NAME);
169: Object value = attrDesc
170: .getFieldValue(ModelMBeanConstants.ATTRIBUTE_VALUE);
171: Object updated = attrDesc
172: .getFieldValue(ModelMBeanConstants.LAST_UPDATED_TIME_STAMP2);
173:
174: // set only if value has been set; otherwise cannot distinguish
175: // between a null value and a value never set
176: if (updated != null) {
177: log.debug("loading attribute name: " + name
178: + ", value: " + value);
179: Attribute curAttribute = new Attribute(name.toString(),
180: value);
181: attributes.add(curAttribute);
182: }
183: }
184:
185: try {
186: setIsLoading(true);
187: mbean.setAttributes(attributes);
188: } finally {
189: setIsLoading(false);
190: }
191: }
192:
193: protected boolean isLoading() {
194: return isLoading;
195: }
196:
197: protected void setIsLoading(boolean newIsLoading) {
198: isLoading = newIsLoading;
199: }
200:
201: protected File getStoreFile(MBeanInfo metadata, boolean createFile)
202: throws MBeanException {
203: Descriptor d = ((ModelMBeanInfo) metadata).getMBeanDescriptor();
204: String dirPath = (String) d
205: .getFieldValue(ModelMBeanConstants.PERSIST_LOCATION);
206: String file = (String) d
207: .getFieldValue(ModelMBeanConstants.PERSIST_NAME);
208: if (dirPath == null) {
209: log.debug("No " + ModelMBeanConstants.PERSIST_LOCATION
210: + " descriptor value found, using '.'");
211: dirPath = ".";
212: }
213: if (file == null) {
214: log.debug("No " + ModelMBeanConstants.PERSIST_NAME
215: + " descriptor value found");
216: return null;
217: }
218:
219: dirPath = StringPropertyReplacer.replaceProperties(dirPath);
220: file = StringPropertyReplacer.replaceProperties(file);
221: File dir = new File(dirPath);
222: File storeFile = new File(dir, file);
223: boolean exists = storeFile.exists();
224: log.debug("Store file is: " + storeFile.getAbsolutePath());
225: if (exists == false && createFile == true) {
226: dir.mkdirs();
227: try {
228: storeFile.createNewFile();
229: } catch (IOException e) {
230: throw new MBeanException(e,
231: "Failed to create store file");
232: }
233: } else if (exists == false) {
234: storeFile = null;
235: }
236: return storeFile;
237: }
238: }
|