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.IOException;
026: import java.util.Collection;
027: import java.util.Enumeration;
028: import java.util.Vector;
029:
030: import javax.management.Descriptor;
031: import javax.management.InstanceNotFoundException;
032: import javax.management.JMException;
033: import javax.management.MBeanException;
034: import javax.management.MBeanInfo;
035: import javax.management.MBeanServer;
036: import javax.management.MBeanServerFactory;
037: import javax.management.MalformedObjectNameException;
038: import javax.management.ObjectName;
039: import javax.management.modelmbean.InvalidTargetObjectTypeException;
040: import javax.management.modelmbean.ModelMBean;
041: import javax.management.modelmbean.ModelMBeanInfo;
042:
043: import org.jboss.mx.modelmbean.ModelMBeanConstants;
044: import org.jboss.mx.modelmbean.ModelMBeanInvoker;
045: import org.jboss.mx.modelmbean.RequiredModelMBeanInstantiator;
046: import org.jboss.mx.server.registry.MbeanInfoDb;
047:
048: /**
049: * Class responsible for storing and loading the MBean info database.
050: * @author Matt Munz
051: */
052: public class MbeanInfoDbPm extends MBeanInfoOdb implements
053: PersistenceManager {
054:
055: protected boolean fLoadedFromFs;
056: protected Vector fNamesToRestore;
057: protected Vector fInfosToRestore;
058: protected MBeanServer fMbeanServer;
059: protected MbeanInfoDb fMbeanInfoDb;
060: protected File fMbiDbRoot;
061:
062: public MbeanInfoDbPm() {
063: super ();
064: }
065:
066: /**
067: * @todo finish implementing
068: */
069: public void load(ModelMBeanInvoker mbean, MBeanInfo info)
070: throws MBeanException {
071:
072: logger().debug("Loading the MBI DB");
073: setMbeanInfoDb((MbeanInfoDb) mbean.getResource());
074: if (!loadedFromFs()) {
075:
076: // get mbi db root from descriptor
077: Descriptor d = ((ModelMBeanInfo) info).getMBeanDescriptor();
078: String dir = (String) d
079: .getFieldValue(ModelMBeanConstants.PERSIST_LOCATION);
080: if ((dir != null) && (!dir.equals(""))) {
081:
082: setMbiDbRoot(new File(dir));
083: }
084: String message = "Loading the MBI DB from the filesystem. location: ";
085: message += mbiDbRoot();
086: logger().debug(message);
087: File[] mbiFiles = mbiDbRoot().listFiles();
088: if (mbiFiles == null) {
089:
090: return;
091: }
092: // loop over each item in the mbeaninfo store
093: for (int index = 0; index < mbiFiles.length; index++) {
094:
095: /// for each, load, make a new mbean, and register that mbean
096: File curFile = mbiFiles[index];
097: ObjectName nameToRestore = null;
098: try {
099:
100: nameToRestore = objectName(curFile);
101: } catch (MalformedObjectNameException cause) {
102:
103: throw new MBeanException(cause,
104: "Object Name was stored incorrectly.");
105: }
106: MBeanInfo infoToRestore = null;
107: try {
108:
109: infoToRestore = load(curFile);
110: } catch (IOException cause) {
111:
112: throw new MBeanException(cause,
113: "Couldn't read the MBeanInfo file.");
114: } catch (ClassNotFoundException cause2) {
115:
116: String message2 = "Couldn't find the Class specified in the object file.";
117: throw new MBeanException(cause2, message2);
118: }
119: if (infoToRestore == null) {
120:
121: throw new MBeanException(new Exception(
122: "Null loaded MBean info. Error on load."),
123: "Could not load");
124: }
125: namesToRestore().add(nameToRestore);
126: infosToRestore().add(infoToRestore);
127: }
128: setLoadedFromFs(true);
129: }
130: try {
131:
132: register();
133: } catch (Exception cause) {
134:
135: throw new MBeanException(cause,
136: "Error trying to register loaded MBeans");
137: }
138: }
139:
140: public void store(MBeanInfo info) throws MBeanException {
141:
142: logger().debug("storing MBI DB State");
143: Enumeration queue = mbeanInfoDb().mbiPersistenceQueue();
144: for (; queue.hasMoreElements();) {
145:
146: ObjectName curName = (ObjectName) queue.nextElement();
147: logger().debug("queue elem: " + curName);
148: MBeanInfo curInfo = null;
149: try {
150:
151: curInfo = getMBeanServer().getMBeanInfo(curName);
152: } catch (InstanceNotFoundException cause) {
153:
154: throw new MBeanException(cause);
155: } catch (JMException cause3) {
156:
157: throw new MBeanException(cause3);
158: }
159: if (curInfo == null) {
160:
161: throw new MBeanException(new Exception(
162: "Current MBean Info object is null."),
163: "Could not store null object.");
164: }
165: try {
166:
167: store(curName, curInfo);
168: } catch (IOException cause2) {
169:
170: throw new MBeanException(cause2);
171: }
172: mbeanInfoDb().removeFromMbiQueue(curName);
173: logger().info("Successfully stored mbi for " + curName);
174: }
175: }
176:
177: protected void store(ObjectName name, MBeanInfo info)
178: throws IOException {
179:
180: File location = new File(mbiDbRoot(), fileName(name));
181: logger().debug("Storing mbi at: " + location);
182: mbiDbRoot().mkdirs();
183: store(info, location);
184: }
185:
186: /**
187: * Iterates over the loaded MBean infos and ObjectNames, creates an MBean for each, and
188: * registers it with the server. This includes creating the resource object as well.
189: */
190: protected void register() throws JMException,
191: InvalidTargetObjectTypeException {
192:
193: // iterate over all loaded infos and register them.
194: logger().debug("registering...");
195: Enumeration names = namesToRestore().elements();
196: Enumeration infos = infosToRestore().elements();
197: try {
198:
199: while (names.hasMoreElements() && infos.hasMoreElements()) {
200:
201: ObjectName curName = (ObjectName) names.nextElement();
202: logger().debug("curName: " + curName);
203: ModelMBeanInfo curInfo = (ModelMBeanInfo) infos
204: .nextElement();
205: Descriptor mbeanDescriptor = curInfo
206: .getMBeanDescriptor();
207: String fieldName = ModelMBeanConstants.RESOURCE_CLASS;
208: String className = (String) mbeanDescriptor
209: .getFieldValue(fieldName);
210: logger().debug("className: " + className);
211: Object resource = getMBeanServer().instantiate(
212: className);
213: ModelMBean modelmbean = RequiredModelMBeanInstantiator
214: .instantiate();
215: modelmbean.setModelMBeanInfo(curInfo);
216: modelmbean.setManagedResource(resource,
217: "ObjectReference");
218: getMBeanServer().registerMBean(modelmbean, curName);
219: }
220: } finally {
221:
222: namesToRestore().removeAllElements();
223: infosToRestore().removeAllElements();
224: }
225: }
226:
227: protected MBeanServer getMBeanServer() throws JMException {
228:
229: if (fMbeanServer == null) {
230:
231: Collection col = MBeanServerFactory.findMBeanServer(null);
232: if (col.isEmpty()) {
233:
234: throw new JMException("No MBeanServer found");
235: }
236: fMbeanServer = (MBeanServer) col.iterator().next();
237: }
238: return fMbeanServer;
239: }
240:
241: /**
242: * JDK 1.3.1 substitute for jdk 1.4.1 String.replaceAll()
243: * Does not accept regular expressions...
244: * returns the object string where all instances of target are replaced with replacement
245: * @todo replace with a more appropriate string util if available
246: */
247: protected String replaceAll(String object, String target,
248: String replacement) {
249:
250: return replaceAll(object, target, replacement, 0);
251: }
252:
253: /**
254: * Iterative
255: */
256: protected String replaceAll(String object, String target,
257: String replacement, int curIndex) {
258: int indexOfMatch = object.indexOf(target, curIndex);
259: if (indexOfMatch < curIndex) {
260:
261: return object;
262: }
263: String prefix = "";
264: if (indexOfMatch > 0) {
265:
266: prefix = object.substring(0, indexOfMatch);
267: }
268: String tail = object.substring(indexOfMatch + target.length());
269: String newObject = prefix + replacement + tail;
270: return replaceAll(newObject, target, replacement, indexOfMatch
271: + replacement.length());
272: }
273:
274: protected String objNameSeparator() {
275:
276: return ":";
277: }
278:
279: protected String objNameSepRep() {
280:
281: return "___";
282: }
283:
284: protected String fileName(ObjectName name) {
285:
286: String fileName = name.getCanonicalName();
287: fileName = replaceAll(fileName, objNameSeparator(),
288: objNameSepRep());
289: return fileName;
290: }
291:
292: protected ObjectName objectName(File fileName)
293: throws MalformedObjectNameException {
294:
295: String objectName = fileName.getName();
296: objectName = replaceAll(objectName, objNameSepRep(),
297: objNameSeparator());
298: return new ObjectName(objectName);
299: }
300:
301: protected boolean loadedFromFs() {
302:
303: return fLoadedFromFs;
304: }
305:
306: protected void setLoadedFromFs(boolean newLoadedFromFs) {
307:
308: fLoadedFromFs = newLoadedFromFs;
309: }
310:
311: protected Vector namesToRestore() {
312:
313: if (fNamesToRestore == null) {
314:
315: fNamesToRestore = new Vector(10);
316: }
317: return fNamesToRestore;
318: }
319:
320: protected Vector infosToRestore() {
321:
322: if (fInfosToRestore == null) {
323:
324: fInfosToRestore = new Vector(10);
325: }
326: return fInfosToRestore;
327: }
328:
329: protected File mbiDbRoot() {
330:
331: if (fMbiDbRoot == null) {
332:
333: fMbiDbRoot = new File("../conf/mbean-info-db/");
334: }
335: return fMbiDbRoot;
336: }
337:
338: protected void setMbiDbRoot(File newMbiDbRoot) {
339:
340: fMbiDbRoot = newMbiDbRoot;
341: }
342:
343: protected MbeanInfoDb mbeanInfoDb() {
344:
345: return fMbeanInfoDb;
346: }
347:
348: protected void setMbeanInfoDb(MbeanInfoDb newMbeanInfoDb) {
349:
350: fMbeanInfoDb = newMbeanInfoDb;
351: }
352: }
|